Skip to content

Pact

Python methods for interactive with a Pact Mock Service.

Attributes

SomethingLike = Like module-attribute

Classes

Broker(broker_base_url=None, broker_username=None, broker_password=None, broker_token=None)

PactBroker helper functions.

:param broker_base_url: URL of the pact broker that pacts will be published to. Can also be supplied through the PACT_BROKER_BASE_URL environment variable. Defaults to None. :type broker_base_url: str :param broker_username: Username to use when connecting to the pact broker if authentication is required. Can also be supplied through the PACT_BROKER_USERNAME environment variable. Defaults to None. :type broker_username: str :param broker_password: Password to use when connecting to the pact broker if authentication is required. Strongly recommend supplying this value through the PACT_BROKER_PASSWORD environment variable instead. Defaults to None. :type broker_password: str :param broker_token: Authentication token to use when connecting to the pact broker. Strongly recommend supplying this value through the PACT_BROKER_TOKEN environment variable instead. Defaults to None.

Source code in src/pact/broker.py
def __init__(self, broker_base_url=None, broker_username=None, broker_password=None, broker_token=None):
    """
    Create a Broker instance.

    :param broker_base_url: URL of the pact broker that pacts will be
        published to. Can also be supplied through the PACT_BROKER_BASE_URL
        environment variable. Defaults to None.
    :type broker_base_url: str
    :param broker_username: Username to use when connecting to the pact
        broker if authentication is required. Can also be supplied through
        the PACT_BROKER_USERNAME environment variable. Defaults to None.
    :type broker_username: str
    :param broker_password: Password to use when connecting to the pact
        broker if authentication is required. Strongly recommend supplying
        this value through the PACT_BROKER_PASSWORD environment variable
        instead. Defaults to None.
    :type broker_password: str
    :param broker_token: Authentication token to use when connecting to
        the pact broker. Strongly recommend supplying this value through
        the PACT_BROKER_TOKEN environment variable instead.
        Defaults to None.
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.broker_base_url = broker_base_url
    self.broker_username = broker_username
    self.broker_password = broker_password
    self.broker_token = broker_token

Attributes

broker_base_url = broker_base_url instance-attribute
broker_password = broker_password instance-attribute
broker_token = broker_token instance-attribute
broker_username = broker_username instance-attribute

Functions

publish(consumer_name, version, pact_dir=None, tag_with_git_branch=None, consumer_tags=None, branch=None, build_url=None, auto_detect_version_properties=None)

Publish the generated pact files to the specified pact broker.

Source code in src/pact/broker.py
def publish(self, consumer_name, version, pact_dir=None,
            tag_with_git_branch=None, consumer_tags=None, branch=None, build_url=None, auto_detect_version_properties=None):
    """Publish the generated pact files to the specified pact broker."""
    if self.broker_base_url is None \
            and "PACT_BROKER_BASE_URL" not in os.environ:
        raise RuntimeError("No pact broker URL specified. "
                           + "Did you expect the PACT_BROKER_BASE_URL "
                           + "environment variable to be set?")

    pact_files = fnmatch.filter(
        os.listdir(pact_dir),
        self._normalize_consumer_name(consumer_name) + '*.json'
    )
    pact_files = list(map(lambda pact_file: f'{pact_dir}/{pact_file}', pact_files))
    command = [
        BROKER_CLIENT_PATH,
        'publish',
        '--consumer-app-version={}'.format(version)]

    command.append('--broker-base-url={}'.format(self._get_broker_base_url()))

    if self.broker_username is not None:
        command.append('--broker-username={}'.format(self.broker_username))
    if self.broker_password is not None:
        command.append('--broker-password={}'.format(self.broker_password))
    if self.broker_token is not None:
        command.append('--broker-token={}'.format(self.broker_token))

    command.extend(pact_files)

    if tag_with_git_branch:
        command.append('--tag-with-git-branch')

    if consumer_tags is not None:
        for tag in consumer_tags:
            command.extend(['-t', tag])

    if branch:
        command.extend(['--branch={}'.format(branch)])

    if build_url:
        command.extend(['--build-url={}'.format(build_url)])

    if auto_detect_version_properties is True:
        command.append('--auto-detect-version-properties')

    log.debug(f"PactBroker publish command: {command}")

    publish_process = Popen(command)
    publish_process.wait()
    if publish_process.returncode != 0:
        url = self._get_broker_base_url()
        raise RuntimeError(
            f"There was an error while publishing to the pact broker at {url}.")

Consumer(name, service_cls=Pact, tags=None, tag_with_git_branch=False, version='0.0.0', branch=None, build_url=None, auto_detect_version_properties=False)

Bases: object

A Pact consumer.

Use this class to describe the service making requests to the provider and then use has_pact_with to create a contract with a specific service:

from pact import Consumer, Provider consumer = Consumer('my-web-front-end') consumer.has_pact_with(Provider('my-backend-service'))

:param name: The name of this Consumer. This will be shown in the Pact when it is published. :type name: str :param service_cls: Pact, or a sub-class of it, to use when creating the contracts. This is useful when you have a custom URL or port for your mock service and want to use the same value on all of your contracts. :type service_cls: pact.Pact :param tags: A list of strings to use as tags to use when publishing to a pact broker. Defaults to None. :type tags: list :param tag_with_git_branch: A flag to determine whether to automatically tag a pact with the current git branch name. Defaults to False. :type tag_with_git_branch: bool :param version: The version of this Consumer. This will be used when publishing pacts to a pact broker. Defaults to '0.0.0' :param branch: The branch of this Consumer. :type branch: str :param build_url: The build URL that created the pact. :type build_url: str :param auto_detect_version_properties: Automatically detect the repository branch from known CI, environment variables or git CLI. Supports Buildkite, Circle CI, Travis CI, GitHub Actions, Jenkins, Hudson, AppVeyor, GitLab, CodeShip, Bitbucket and Azure DevOps.'. Defaults to False. :type auto_detect_version_properties: bool

Source code in src/pact/consumer.py
def __init__(self, name, service_cls=Pact, tags=None,
             tag_with_git_branch=False, version='0.0.0', branch=None, build_url=None, auto_detect_version_properties=False):
    """
    Create the Consumer class.

    :param name: The name of this Consumer. This will be shown in the Pact
        when it is published.
    :type name: str
    :param service_cls: Pact, or a sub-class of it, to use when creating
        the contracts. This is useful when you have a custom URL or port
        for your mock service and want to use the same value on all of
        your contracts.
    :type service_cls: pact.Pact
    :param tags: A list of strings to use as tags to use when publishing
        to a pact broker. Defaults to None.
    :type tags: list
    :param tag_with_git_branch: A flag to determine whether to
        automatically tag a pact with the current git branch name.
        Defaults to False.
    :type tag_with_git_branch: bool
    :param version: The version of this Consumer. This will be used when
        publishing pacts to a pact broker. Defaults to '0.0.0'
    :param branch: The branch of this Consumer.
    :type branch: str
    :param build_url: The build URL that created the pact.
    :type build_url: str
    :param auto_detect_version_properties: Automatically detect the repository branch from known CI,
        environment variables or git CLI. Supports Buildkite, Circle CI, Travis CI, GitHub Actions,
        Jenkins, Hudson, AppVeyor, GitLab, CodeShip, Bitbucket and Azure DevOps.'.
        Defaults to False.
    :type auto_detect_version_properties: bool
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.name = name
    self.service_cls = service_cls
    self.tags = tags
    self.tag_with_git_branch = tag_with_git_branch
    self.version = version
    self.branch = branch
    self.build_url = build_url
    self.auto_detect_version_properties = auto_detect_version_properties

Attributes

auto_detect_version_properties = auto_detect_version_properties instance-attribute
branch = branch instance-attribute
build_url = build_url instance-attribute
name = name instance-attribute
service_cls = service_cls instance-attribute
tag_with_git_branch = tag_with_git_branch instance-attribute
tags = tags instance-attribute
version = version instance-attribute

Functions

has_pact_with(provider, host_name='localhost', port=1234, log_dir=None, ssl=False, sslcert=None, sslkey=None, cors=False, publish_to_broker=False, broker_base_url=None, broker_username=None, broker_password=None, broker_token=None, pact_dir=None, specification_version='2.0.0', file_write_mode='overwrite')

Create a contract between the provider and this consumer.

If you are running the Pact mock service in a non-default location, you can provide the host name and port here:

from pact import Consumer, Provider consumer = Consumer('my-web-front-end') consumer.has_pact_with( ... Provider('my-backend-service'), ... host_name='192.168.1.1', ... port=8000)

:param provider: The provider service for this contract. :type provider: pact.Provider :param host_name: An optional host name to use when contacting the Pact mock service. This will need to be the same host name used by your code under test to contact the mock service. It defaults to: localhost. :type host_name: str :param port: The TCP port to use when contacting the Pact mock service. This will need to be the same port used by your code under test to contact the mock service. It defaults to: 1234 :type port: int :param log_dir: The directory where logs should be written. Defaults to the current directory. :type log_dir: str :param ssl: Flag to control the use of a self-signed SSL cert to run the server over HTTPS , defaults to False. :type ssl: bool :param sslcert: Path to a custom self-signed SSL cert file, 'ssl' option must be set to True to use this option. Defaults to None. :type sslcert: str :param sslkey: Path to a custom key and self-signed SSL cert key file, 'ssl' option must be set to True to use this option. Defaults to None. :type sslkey: str :param cors: Allow CORS OPTION requests to be accepted, defaults to False. :type cors: bool :param publish_to_broker: Flag to control automatic publishing of pacts to a pact broker. Defaults to False. :type publish_to_broker: bool :param broker_base_url: URL of the pact broker that pacts will be published to. Defaults to None. :type broker_base_url: str :param broker_username: Username to use when connecting to the pact broker if authentication is required. Defaults to None. :type broker_username: str :param broker_password: Password to use when connecting to the pact broker if authentication is required. Defaults to None. :type broker_password: str :param broker_token: Authentication token to use when connecting to the pact broker. Defaults to None. :type broker_token: str :param pact_dir: Directory where the resulting pact files will be written. Defaults to the current directory. :type pact_dir: str :param specification_version: The Pact Specification version to use. Defaults to '2.0.0'. :type version: str :param file_write_mode: How the mock service should apply multiple calls to .verify(). Pass 'overwrite' to overwrite the generated JSON file on every call to .verify() or pass 'merge' to merge all interactions into the same JSON file. When using 'merge', make sure to delete any existing JSON file before calling .verify() for the first time. Defaults to 'overwrite'. :type version: str :return: A Pact object which you can use to define the specific interactions your code will have with the provider. :rtype: pact.Pact

Source code in src/pact/consumer.py
def has_pact_with(self, provider, host_name='localhost', port=1234,
                  log_dir=None, ssl=False, sslcert=None, sslkey=None,
                  cors=False, publish_to_broker=False,
                  broker_base_url=None, broker_username=None,
                  broker_password=None, broker_token=None, pact_dir=None,
                  specification_version='2.0.0',
                  file_write_mode='overwrite'):
    """
    Create a contract between the `provider` and this consumer.

    If you are running the Pact mock service in a non-default location,
    you can provide the host name and port here:

    >>> from pact import Consumer, Provider
    >>> consumer = Consumer('my-web-front-end')
    >>> consumer.has_pact_with(
    ...   Provider('my-backend-service'),
    ...   host_name='192.168.1.1',
    ...   port=8000)

    :param provider: The provider service for this contract.
    :type provider: pact.Provider
    :param host_name: An optional host name to use when contacting the
        Pact mock service. This will need to be the same host name used by
        your code under test to contact the mock service. It defaults to:
        `localhost`.
    :type host_name: str
    :param port: The TCP port to use when contacting the Pact mock service.
        This will need to be the same port used by your code under test
        to contact the mock service. It defaults to: 1234
    :type port: int
    :param log_dir: The directory where logs should be written. Defaults to
        the current directory.
    :type log_dir: str
    :param ssl: Flag to control the use of a self-signed SSL cert to run
        the server over HTTPS , defaults to False.
    :type ssl: bool
    :param sslcert: Path to a custom self-signed SSL cert file, 'ssl'
        option must be set to True to use this option. Defaults to None.
    :type sslcert: str
    :param sslkey: Path to a custom key and self-signed SSL cert key file,
        'ssl' option must be set to True to use this option.
        Defaults to None.
    :type sslkey: str
    :param cors: Allow CORS OPTION requests to be accepted,
        defaults to False.
    :type cors: bool
    :param publish_to_broker: Flag to control automatic publishing of
        pacts to a pact broker. Defaults to False.
    :type publish_to_broker: bool
    :param broker_base_url: URL of the pact broker that pacts will be
        published to. Defaults to None.
    :type broker_base_url: str
    :param broker_username: Username to use when connecting to the pact
        broker if authentication is required. Defaults to None.
    :type broker_username: str
    :param broker_password: Password to use when connecting to the pact
        broker if authentication is required. Defaults to None.
    :type broker_password: str
    :param broker_token: Authentication token to use when connecting to
        the pact broker. Defaults to None.
    :type broker_token: str
    :param pact_dir: Directory where the resulting pact files will be
        written. Defaults to the current directory.
    :type pact_dir: str
    :param specification_version: The Pact Specification version to use.
        Defaults to '2.0.0'.
    :type version: str
    :param file_write_mode: How the mock service should apply multiple
        calls to .verify(). Pass 'overwrite' to overwrite the generated
        JSON file on every call to .verify() or pass 'merge' to merge all
        interactions into the same JSON file. When using 'merge', make
        sure to delete any existing JSON file before calling .verify()
        for the first time. Defaults to 'overwrite'.
    :type version: str
    :return: A Pact object which you can use to define the specific
        interactions your code will have with the provider.
    :rtype: pact.Pact
    """
    if not isinstance(provider, (Provider,)):
        raise ValueError(
            'provider must be an instance of the Provider class.')

    return self.service_cls(
        broker_base_url=broker_base_url,
        broker_username=broker_username,
        broker_password=broker_password,
        broker_token=broker_token,
        consumer=self,
        provider=provider,
        host_name=host_name,
        port=port,
        log_dir=log_dir,
        ssl=ssl,
        sslcert=sslcert,
        sslkey=sslkey,
        cors=cors,
        pact_dir=pact_dir,
        publish_to_broker=publish_to_broker,
        specification_version=specification_version,
        file_write_mode=file_write_mode)

EachLike(matcher, minimum=1)

Bases: Matcher

Expect the data to be a list of similar objects.

Example:

from pact import Consumer, Provider pact = Consumer('consumer').has_pact_with(Provider('provider')) (pact.given('there are three comments') ... .upon_receiving('a request for the most recent 2 comments') ... .with_request('get', '/comment', query={'limit': 2}) ... .will_respond_with(200, body={ ... 'comments': EachLike( ... {'name': SomethingLike('bob'), ... 'text': SomethingLike('Hello!')}, ... minimum=2) ... })) Would expect the response to be a JSON object, with a comments list. In that list should be at least 2 items, and each item should be a dict with the keys name and text,

:param matcher: The expected value that each item in a list should look like, this can be other matchers. :type matcher: None, list, dict, int, float, str, unicode, Matcher :param minimum: The minimum number of items expected. Must be greater than or equal to 1. :type minimum: int

Source code in src/pact/matchers.py
def __init__(self, matcher, minimum=1):
    """
    Create a new EachLike.

    :param matcher: The expected value that each item in a list should
        look like, this can be other matchers.
    :type matcher: None, list, dict, int, float, str, unicode, Matcher
    :param minimum: The minimum number of items expected.
        Must be greater than or equal to 1.
    :type minimum: int
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.matcher = matcher
    assert minimum >= 1, 'Minimum must be greater than or equal to 1'
    self.minimum = minimum

Attributes

matcher = matcher instance-attribute
minimum = minimum instance-attribute

Functions

generate()

Generate the value the mock service will return.

:return: A dict containing the information about the contents of the list and the provided minimum number of items for that list. :rtype: dict

Source code in src/pact/matchers.py
def generate(self):
    """
    Generate the value the mock service will return.

    :return: A dict containing the information about the contents of the
        list and the provided minimum number of items for that list.
    :rtype: dict
    """
    return {
        'json_class': 'Pact::ArrayLike',
        'contents': from_term(self.matcher),
        'min': self.minimum}

Format()

Class of regular expressions for common formats.

Example:

from pact import Consumer, Provider from pact.matchers import Format pact = Consumer('consumer').has_pact_with(Provider('provider')) (pact.given('the current user is logged in as tester') ... .upon_receiving('a request for the user profile') ... .with_request('get', '/profile') ... .will_respond_with(200, body={ ... 'id': Format().identifier, ... 'lastUpdated': Format().time ... }))

Would expect id to be any valid int and lastUpdated to be a valid time. When the consumer runs this contract, the value of that will be returned is the second value passed to Term in the given function, for the time example it would be datetime.datetime(2000, 2, 1, 12, 30, 0, 0).time()

Source code in src/pact/matchers.py
def __init__(self):
    """Create a new Formatter."""
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.identifier = self.integer_or_identifier()
    self.integer = self.integer_or_identifier()
    self.decimal = self.decimal()
    self.ip_address = self.ip_address()
    self.hexadecimal = self.hexadecimal()
    self.ipv6_address = self.ipv6_address()
    self.uuid = self.uuid()
    self.timestamp = self.timestamp()
    self.date = self.date()
    self.time = self.time()
    self.iso_datetime = self.iso_8601_datetime()
    self.iso_datetime_ms = self.iso_8601_datetime(with_ms=True)

Attributes

identifier = self.integer_or_identifier() instance-attribute
integer = self.integer_or_identifier() instance-attribute
iso_datetime = self.iso_8601_datetime() instance-attribute
iso_datetime_ms = self.iso_8601_datetime(with_ms=True) instance-attribute

Classes

Regexes

Bases: Enum

Regex Enum for common formats.

Attributes
date = '^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))?)' class-attribute instance-attribute
hexadecimal = '[0-9a-fA-F]+' class-attribute instance-attribute
ip_address = '(\\d{1,3}\\.)+\\d{1,3}' class-attribute instance-attribute
ipv6_address = '(\\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\\Z)|(\\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\\Z)|(\\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\\Z)|(\\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\\Z)|(\\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\\Z)|(\\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\\Z)|(\\A(([0-9a-f]{1,4}:){1,7}|:):\\Z)|(\\A:(:[0-9a-f]{1,4}){1,7}\\Z)|(\\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3})\\Z)|(\\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3})\\Z)|(\\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)' class-attribute instance-attribute
iso_8601_datetime = '^\\d{4}-[01]\\d-[0-3]\\d\\x54[0-2]\\d:[0-6]\\d:[0-6]\\d(?:\\.\\d+)?(?:(?:[+-]\\d\\d:\\d\\d)|\\x5A)?$' class-attribute instance-attribute
iso_8601_datetime_ms = '^\\d{4}-[01]\\d-[0-3]\\d\\x54[0-2]\\d:[0-6]\\d:[0-6]\\d\\.\\d+(?:(?:[+-]\\d\\d:\\d\\d)|\\x5A)?$' class-attribute instance-attribute
time_regex = '^(T\\d\\d:\\d\\d(:\\d\\d)?(\\.\\d+)?(([+-]\\d\\d:\\d\\d)|Z)?)?$' class-attribute instance-attribute
timestamp = '^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$' class-attribute instance-attribute
uuid = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' class-attribute instance-attribute

Functions

date()

Match any date.

:return: a Term object with a date regex. :rtype: Term

Source code in src/pact/matchers.py
def date(self):
    """
    Match any date.

    :return: a Term object with a date regex.
    :rtype: Term
    """
    return Term(
        self.Regexes.date.value, datetime.datetime(
            2000, 2, 1, 12, 30, 0, 0
        ).date().isoformat()
    )
decimal()

Match any decimal.

:return: a Like object with a decimal. :rtype: Like

Source code in src/pact/matchers.py
def decimal(self):
    """
    Match any decimal.

    :return: a Like object with a decimal.
    :rtype: Like
    """
    return Like(1.0)
hexadecimal()

Match any hexadecimal.

:return: a Term object with a hexdecimal regex. :rtype: Term

Source code in src/pact/matchers.py
def hexadecimal(self):
    """
    Match any hexadecimal.

    :return: a Term object with a hexdecimal regex.
    :rtype: Term
    """
    return Term(self.Regexes.hexadecimal.value, '3F')
integer_or_identifier()

Match any integer.

:return: a Like object with an integer. :rtype: Like

Source code in src/pact/matchers.py
def integer_or_identifier(self):
    """
    Match any integer.

    :return: a Like object with an integer.
    :rtype: Like
    """
    return Like(1)
ip_address()

Match any ip address.

:return: a Term object with an ip address regex. :rtype: Term

Source code in src/pact/matchers.py
def ip_address(self):
    """
    Match any ip address.

    :return: a Term object with an ip address regex.
    :rtype: Term
    """
    return Term(self.Regexes.ip_address.value, '127.0.0.1')
ipv6_address()

Match any ipv6 address.

:return: a Term object with an ipv6 address regex. :rtype: Term

Source code in src/pact/matchers.py
def ipv6_address(self):
    """
    Match any ipv6 address.

    :return: a Term object with an ipv6 address regex.
    :rtype: Term
    """
    return Term(self.Regexes.ipv6_address.value, '::ffff:192.0.2.128')
iso_8601_datetime(with_ms=False)

Match a string for a full ISO 8601 Date.

Does not do any sort of date validation, only checks if the string is according to the ISO 8601 spec.

This method differs from :func:~pact.Format.timestamp, :func:~pact.Format.date and :func:~pact.Format.time implementations in that it is more stringent and tests the string for exact match to the ISO 8601 dates format.

Without with_ms will match string containing ISO 8601 formatted dates as stated bellow:

  • 2016-12-15T20:16:01
  • 2010-05-01T01:14:31.876
  • 2016-05-24T15:54:14.00000Z
  • 1994-11-05T08:15:30-05:00
  • 2002-01-31T23:00:00.1234-02:00
  • 1991-02-20T06:35:26.079043+00:00

Otherwise, ONLY dates with milliseconds will match the pattern:

  • 2010-05-01T01:14:31.876
  • 2016-05-24T15:54:14.00000Z
  • 2002-01-31T23:00:00.1234-02:00
  • 1991-02-20T06:35:26.079043+00:00

:param with_ms: Enforcing millisecond precision. :type with_ms: bool :return: a Term object with a date regex. :rtype: Term

Source code in src/pact/matchers.py
def iso_8601_datetime(self, with_ms=False):
    """
    Match a string for a full ISO 8601 Date.

    Does not do any sort of date validation, only checks if the string is
    according to the ISO 8601 spec.

    This method differs from :func:`~pact.Format.timestamp`,
    :func:`~pact.Format.date` and :func:`~pact.Format.time` implementations
    in that it is more stringent and tests the string for exact match to
    the ISO 8601 dates format.

    Without `with_ms` will match string containing ISO 8601 formatted dates
    as stated bellow:

    * 2016-12-15T20:16:01
    * 2010-05-01T01:14:31.876
    * 2016-05-24T15:54:14.00000Z
    * 1994-11-05T08:15:30-05:00
    * 2002-01-31T23:00:00.1234-02:00
    * 1991-02-20T06:35:26.079043+00:00

    Otherwise, ONLY dates with milliseconds will match the pattern:

    * 2010-05-01T01:14:31.876
    * 2016-05-24T15:54:14.00000Z
    * 2002-01-31T23:00:00.1234-02:00
    * 1991-02-20T06:35:26.079043+00:00

    :param with_ms: Enforcing millisecond precision.
    :type with_ms: bool
    :return: a Term object with a date regex.
    :rtype: Term
    """
    date = [1991, 2, 20, 6, 35, 26]
    if with_ms:
        matcher = self.Regexes.iso_8601_datetime_ms.value
        date.append(79043)
    else:
        matcher = self.Regexes.iso_8601_datetime.value

    return Term(
        matcher,
        datetime.datetime(*date, tzinfo=datetime.timezone.utc).isoformat()
    )
time()

Match any time.

:return: a Term object with a time regex. :rtype: Term

Source code in src/pact/matchers.py
def time(self):
    """
    Match any time.

    :return: a Term object with a time regex.
    :rtype: Term
    """
    return Term(
        self.Regexes.time_regex.value, datetime.datetime(
            2000, 2, 1, 12, 30, 0, 0
        ).time().isoformat()
    )
timestamp()

Match any timestamp.

:return: a Term object with a timestamp regex. :rtype: Term

Source code in src/pact/matchers.py
def timestamp(self):
    """
    Match any timestamp.

    :return: a Term object with a timestamp regex.
    :rtype: Term
    """
    return Term(
        self.Regexes.timestamp.value, datetime.datetime(
            2000, 2, 1, 12, 30, 0, 0
        ).isoformat()
    )
uuid()

Match any uuid.

:return: a Term object with a uuid regex. :rtype: Term

Source code in src/pact/matchers.py
def uuid(self):
    """
    Match any uuid.

    :return: a Term object with a uuid regex.
    :rtype: Term
    """
    return Term(
        self.Regexes.uuid.value, 'fc763eba-0905-41c5-a27f-3934ab26786c'
    )

Like(matcher)

Bases: Matcher

Expect the type of the value to be the same as matcher.

Example:

from pact import Consumer, Provider pact = Consumer('consumer').has_pact_with(Provider('provider')) (pact ... .given('there is a random number generator') ... .upon_receiving('a request for a random number') ... .with_request('get', '/generate-number') ... .will_respond_with(200, body={ ... 'number': Like(1111222233334444) ... }))

Would expect the response body to be a JSON object, containing the key number, which would contain an integer. When the consumer runs this contract, the value 1111222233334444 will be returned by the mock service, instead of a randomly generated value.

:param matcher: The object that should be expected. The mock service will return this value. When verified against the provider, the type of this value will be asserted, while the value will be ignored. :type matcher: None, list, dict, int, float, str, unicode, Matcher

Source code in src/pact/matchers.py
def __init__(self, matcher):
    """
    Create a new SomethingLike.

    :param matcher: The object that should be expected. The mock service
        will return this value. When verified against the provider, the
        type of this value will be asserted, while the value will be
        ignored.
    :type matcher: None, list, dict, int, float, str, unicode, Matcher
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    valid_types = (
        type(None), list, dict, int, float, six.string_types, Matcher)

    assert isinstance(matcher, valid_types), (
        "matcher must be one of '{}', got '{}'".format(
            valid_types, type(matcher)))

    self.matcher = matcher

Attributes

matcher = matcher instance-attribute

Functions

generate()

Return the value that should be used in the request/response.

:return: A dict containing the information about what the contents of the response should be. :rtype: dict

Source code in src/pact/matchers.py
def generate(self):
    """
    Return the value that should be used in the request/response.

    :return: A dict containing the information about what the contents of
        the response should be.
    :rtype: dict
    """
    return {
        'json_class': 'Pact::SomethingLike',
        'contents': from_term(self.matcher)}

MessageConsumer(name, service_cls=MessagePact, tags=None, tag_with_git_branch=False, version='0.0.0', branch=None, build_url=None, auto_detect_version_properties=False)

Bases: object

A Pact message consumer.

Use this class to describe the service making requests to the provider and then use has_pact_with to create a contract with a specific service:

from pact import MessageConsumer, Provider message_consumer = MessageConsumer('my-web-front-end') message_consumer.has_pact_with(Provider('my-backend-serivce'))

:param name: The name of this Consumer. This will be shown in the Pact when it is published. :type name: str :param service_cls: Pact, or a sub-class of it, to use when creating the contracts. This is useful when you have a custom URL or port for your mock service and want to use the same value on all of your contracts. :type service_cls: pact.Pact :param tags: A list of strings to use as tags to use when publishing to a pact broker. Defaults to None. :type tags: list :param tag_with_git_branch: A flag to determine whether to automatically tag a pact with the current git branch name. Defaults to False. :type tag_with_git_branch: bool :param version: The version of this Consumer. This will be used when publishing pacts to a pact broker. Defaults to '0.0.0' :param branch: The branch of this Consumer. :type branch: str :param build_url: The build URL that created the pact. :type build_url: str :param auto_detect_version_properties: Automatically detect the repository branch from known CI, environment variables or git CLI. Supports Buildkite, Circle CI, Travis CI, GitHub Actions, Jenkins, Hudson, AppVeyor, GitLab, CodeShip, Bitbucket and Azure DevOps.'. Defaults to False. :type auto_detect_version_properties: bool

Source code in src/pact/message_consumer.py
def __init__(
    self,
    name,
    service_cls=MessagePact,
    tags=None,
    tag_with_git_branch=False,
    version="0.0.0",
    branch=None,
    build_url=None,
    auto_detect_version_properties=False
):
    """
    Create the Message Consumer class.

    :param name: The name of this Consumer. This will be shown in the Pact
        when it is published.
    :type name: str
    :param service_cls: Pact, or a sub-class of it, to use when creating
        the contracts. This is useful when you have a custom URL or port
        for your mock service and want to use the same value on all of
        your contracts.
    :type service_cls: pact.Pact
    :param tags: A list of strings to use as tags to use when publishing
        to a pact broker. Defaults to None.
    :type tags: list
    :param tag_with_git_branch: A flag to determine whether to
        automatically tag a pact with the current git branch name.
        Defaults to False.
    :type tag_with_git_branch: bool
    :param version: The version of this Consumer. This will be used when
        publishing pacts to a pact broker. Defaults to '0.0.0'
    :param branch: The branch of this Consumer.
    :type branch: str
    :param build_url: The build URL that created the pact.
    :type build_url: str
    :param auto_detect_version_properties: Automatically detect the repository branch from known CI,
        environment variables or git CLI. Supports Buildkite, Circle CI, Travis CI, GitHub Actions,
        Jenkins, Hudson, AppVeyor, GitLab, CodeShip, Bitbucket and Azure DevOps.'.
        Defaults to False.
    :type auto_detect_version_properties: bool
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.name = name
    self.service_cls = service_cls
    self.tags = tags
    self.tag_with_git_branch = tag_with_git_branch
    self.version = version
    self.branch = branch
    self.build_url = build_url
    self.auto_detect_version_properties = auto_detect_version_properties

Attributes

auto_detect_version_properties = auto_detect_version_properties instance-attribute
branch = branch instance-attribute
build_url = build_url instance-attribute
name = name instance-attribute
service_cls = service_cls instance-attribute
tag_with_git_branch = tag_with_git_branch instance-attribute
tags = tags instance-attribute
version = version instance-attribute

Functions

has_pact_with(provider, publish_to_broker=False, broker_base_url=None, broker_username=None, broker_password=None, broker_token=None, pact_dir=None, version='3.0.0', file_write_mode='merge')

Create a contract between the provider and this consumer.

If you are running the Pact mock service in a non-default location, you can provide the host name and port here:

from pact import Consumer, Provider consumer = Consumer('my-web-front-end') consumer.has_pact_with( ... Provider('my-backend-serivce'), ... host_name='192.168.1.1', ... port=8000)

:param provider: The provider service for this contract. :type provider: pact.Provider :param host_name: An optional host name to use when contacting the Pact mock service. This will need to be the same host name used by your code under test to contact the mock service. It defaults to: localhost. :type host_name: str :param publish_to_broker: Flag to control automatic publishing of pacts to a pact broker. Defaults to False. :type publish_to_broker: bool :param broker_base_url: URL of the pact broker that pacts will be published to. Defaults to None. :type broker_base_url: str :param broker_username: Username to use when connecting to the pact broker if authentication is required. Defaults to None. :type broker_username: str :param broker_password: Password to use when connecting to the pact broker if authentication is required. Defaults to None. :type broker_password: str :param broker_token: Authentication token to use when connecting to the pact broker. Defaults to None. :type broker_token: str :param pact_dir: Directory where the resulting pact files will be written. Defaults to the current directory. :type pact_dir: str :param version: The Pact Specification version to use, defaults to '3.0.0'. :type version: str :param file_write_mode: How the mock service should apply multiple calls to .verify(). Pass 'overwrite' to overwrite the generated JSON file on every call to .verify() or pass 'merge' to merge all interactions into the same JSON file. When using 'merge', make sure to delete any existing JSON file before calling .verify() for the first time. Defaults to 'merge'. :type version: str :return: A Pact object which you can use to define the specific interactions your code will have with the provider. :rtype: pact.Pact

Source code in src/pact/message_consumer.py
def has_pact_with(
    self,
    provider,
    publish_to_broker=False,
    broker_base_url=None,
    broker_username=None,
    broker_password=None,
    broker_token=None,
    pact_dir=None,
    version="3.0.0",
    file_write_mode="merge",
):
    """
    Create a contract between the `provider` and this consumer.

    If you are running the Pact mock service in a non-default location,
    you can provide the host name and port here:

    >>> from pact import Consumer, Provider
    >>> consumer = Consumer('my-web-front-end')
    >>> consumer.has_pact_with(
    ...   Provider('my-backend-serivce'),
    ...   host_name='192.168.1.1',
    ...   port=8000)

    :param provider: The provider service for this contract.
    :type provider: pact.Provider
    :param host_name: An optional host name to use when contacting the
        Pact mock service. This will need to be the same host name used by
        your code under test to contact the mock service. It defaults to:
        `localhost`.
    :type host_name: str
    :param publish_to_broker: Flag to control automatic publishing of
        pacts to a pact broker. Defaults to False.
    :type publish_to_broker: bool
    :param broker_base_url: URL of the pact broker that pacts will be
        published to. Defaults to None.
    :type broker_base_url: str
    :param broker_username: Username to use when connecting to the pact
        broker if authentication is required. Defaults to None.
    :type broker_username: str
    :param broker_password: Password to use when connecting to the pact
        broker if authentication is required. Defaults to None.
    :type broker_password: str
    :param broker_token: Authentication token to use when connecting to
        the pact broker. Defaults to None.
    :type broker_token: str
    :param pact_dir: Directory where the resulting pact files will be
        written. Defaults to the current directory.
    :type pact_dir: str
    :param version: The Pact Specification version to use, defaults to
        '3.0.0'.
    :type version: str
    :param file_write_mode: How the mock service should apply multiple
        calls to .verify(). Pass 'overwrite' to overwrite the generated
        JSON file on every call to .verify() or pass 'merge' to merge all
        interactions into the same JSON file. When using 'merge', make
        sure to delete any existing JSON file before calling .verify()
        for the first time. Defaults to 'merge'.
    :type version: str
    :return: A Pact object which you can use to define the specific
        interactions your code will have with the provider.
    :rtype: pact.Pact
    """
    if not isinstance(provider, (Provider,)):
        raise ValueError("provider must be an instance of the Provider class.")

    return self.service_cls(
        broker_base_url=broker_base_url,
        broker_username=broker_username,
        broker_password=broker_password,
        broker_token=broker_token,
        consumer=self,
        provider=provider,
        pact_dir=pact_dir,
        publish_to_broker=publish_to_broker,
        version=version,
        file_write_mode=file_write_mode,
    )

MessagePact(consumer, provider, publish_to_broker=False, broker_base_url=None, broker_username=None, broker_password=None, broker_token=None, pact_dir=None, version='3.0.0', file_write_mode='merge')

Bases: Broker

Represents a contract between a consumer and provider using messages.

Provides Python context handler to perform tests on a Python consumer. For example:

from pact import MessageConsumer, Provider pact = MessageConsumer('MyMessageConsumer').has_pact_with(Provider('provider')) (pact ... .given({"name": "Test provider"}]) ... .expects_to_receive('Test description') ... .with_content({'name': 'John', 'document_name': 'sample_document.doc'}) ... .with_metadata({'contentType': 'application/json'})) with pact: ... handler(event, context)

:param consumer: A consumer for this contract that uses messages. :type consumer: pact.MessageConsumer :param provider: The generic provider for this contract. :type provider: pact.Provider :param publish_to_broker: Flag to control automatic publishing of pacts to a pact broker. Defaults to False. :type publish_to_broker: bool :param broker_base_url: URL of the pact broker that pacts will be published to. Can also be supplied through the PACT_BROKER_BASE_URL environment variable. Defaults to None. :type broker_base_url: str :param broker_username: Username to use when connecting to the pact broker if authentication is required. Can also be supplied through the PACT_BROKER_USERNAME environment variable. Defaults to None. :type broker_username: str :param broker_password: Password to use when connecting to the pact broker if authentication is required. Strongly recommend supplying this value through the PACT_BROKER_PASSWORD environment variable instead. Defaults to None. :type broker_password: str :param broker_token: Authentication token to use when connecting to the pact broker. Strongly recommend supplying this value through the PACT_BROKER_TOKEN environment variable instead. Defaults to None. :type broker_token: str :param pact_dir: Directory where the resulting pact files will be written. Defaults to the current directory. :type pact_dir: str :param version: The Pact Specification version to use, defaults to '3.0.0'. :type version: str :param file_write_mode: overwrite or merge. Use merge when running multiple mock service instances in parallel for the same consumer/provider pair. Ensure the pact file is deleted before running tests when using this option so that interactions deleted from the code are not maintained in the file. Defaults to merge. :type file_write_mode: str

Source code in src/pact/message_pact.py
def __init__(
    self,
    consumer,
    provider,
    publish_to_broker=False,
    broker_base_url=None,
    broker_username=None,
    broker_password=None,
    broker_token=None,
    pact_dir=None,
    version='3.0.0',
    file_write_mode="merge",
):
    """
    Create a Pact instance using messages.

    :param consumer: A consumer for this contract that uses messages.
    :type consumer: pact.MessageConsumer
    :param provider: The generic provider for this contract.
    :type provider: pact.Provider
    :param publish_to_broker: Flag to control automatic publishing of
        pacts to a pact broker. Defaults to False.
    :type publish_to_broker: bool
    :param broker_base_url: URL of the pact broker that pacts will be
        published to. Can also be supplied through the PACT_BROKER_BASE_URL
        environment variable. Defaults to None.
    :type broker_base_url: str
    :param broker_username: Username to use when connecting to the pact
        broker if authentication is required. Can also be supplied through
        the PACT_BROKER_USERNAME environment variable. Defaults to None.
    :type broker_username: str
    :param broker_password: Password to use when connecting to the pact
        broker if authentication is required. Strongly recommend supplying
        this value through the PACT_BROKER_PASSWORD environment variable
        instead. Defaults to None.
    :type broker_password: str
    :param broker_token: Authentication token to use when connecting to
        the pact broker. Strongly recommend supplying this value through
        the PACT_BROKER_TOKEN environment variable instead.
        Defaults to None.
    :type broker_token: str
    :param pact_dir: Directory where the resulting pact files will be
        written. Defaults to the current directory.
    :type pact_dir: str
    :param version: The Pact Specification version to use, defaults to
        '3.0.0'.
    :type version: str
    :param file_write_mode: `overwrite` or `merge`. Use `merge` when
        running multiple mock service instances in parallel for the same
        consumer/provider pair. Ensure the pact file is deleted before
        running tests when using this option so that interactions deleted
        from the code are not maintained in the file. Defaults to
        `merge`.
    :type file_write_mode: str
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    super().__init__(
        broker_base_url, broker_username, broker_password, broker_token
    )

    self.consumer = consumer
    self.file_write_mode = file_write_mode
    self.pact_dir = pact_dir or os.getcwd()
    self.provider = provider
    self.publish_to_broker = publish_to_broker
    self.version = version
    self._process = None
    self._messages = []
    self._message_process = None

Attributes

MANDATORY_FIELDS = {'providerStates', 'description', 'contents', 'metaData'} class-attribute instance-attribute
consumer = consumer instance-attribute
file_write_mode = file_write_mode instance-attribute
pact_dir = pact_dir or os.getcwd() instance-attribute
provider = provider instance-attribute
publish_to_broker = publish_to_broker instance-attribute
version = version instance-attribute

Functions

expects_to_receive(description)

Define the name of this contract (Same as upon_receiving in http pact implementation).

:param scenario: A unique name for this contract. :type scenario: basestring :rtype: Pact

Source code in src/pact/message_pact.py
def expects_to_receive(self, description):
    """
    Define the name of this contract (Same as upon_receiving in http pact implementation).

    :param scenario: A unique name for this contract.
    :type scenario: basestring
    :rtype: Pact
    """
    self._insert_message_if_complete()
    self._messages[0]['description'] = description
    return self
given(name, params=None)

Define the provider state for this pact.

When the provider verifies this contract, they will use this field to setup pre-defined data that will satisfy the response expectations.

:param name: The short sentence that is unique to describe the provider state for this contract. :type name: basestring :param params: Additional arguments necessary to set the provider state :type params: dict :rtype: Pact

Source code in src/pact/message_pact.py
def given(self, name, params=None):
    """
    Define the provider state for this pact.

    When the provider verifies this contract, they will use this field to
    setup pre-defined data that will satisfy the response expectations.

    :param name: The short sentence that is unique to describe the provider
    state for this contract.
    :type name: basestring
    :param params: Additional arguments necessary to set the provider state
    :type params: dict
    :rtype: Pact
    """
    self._insert_message_if_complete()

    provider_state = {'name': "{}".format(name)}
    if params:
        provider_state['params'] = params

    if 'providerStates' not in self._messages[0]:
        self._messages[0]['providerStates'] = [provider_state]
    else:
        self._messages[0]['providerStates'].append(provider_state)

    return self
with_content(contents)

Define message content (event) that will be use in the message.

:param contents: dictionary of dictionary used in the message. :type metadata: dict :rtype: Pact

Source code in src/pact/message_pact.py
def with_content(self, contents):
    """
    Define message content (event) that will be use in the message.

    :param contents: dictionary of dictionary used in the message.
    :type metadata: dict
    :rtype: Pact
    """
    self._insert_message_if_complete()
    self._messages[0]['contents'] = from_term(contents)
    return self
with_metadata(metadata)

Define metadata attached to the message.

:param metadata: dictionary of metadata attached to the message. :type metadata: dict or None :rtype: Pact

Source code in src/pact/message_pact.py
def with_metadata(self, metadata):
    """
    Define metadata attached to the message.

    :param metadata: dictionary of metadata attached to the message.
    :type metadata: dict or None
    :rtype: Pact
    """
    self._insert_message_if_complete()
    self._messages[0]['metaData'] = from_term(metadata)
    return self
write_to_pact_file()

Create a pact file based on provided attributes in DSL.

Return 0 if success, 1 otherwise.

:rtype: int

Source code in src/pact/message_pact.py
def write_to_pact_file(self):
    """
    Create a pact file based on provided attributes in DSL.

    Return 0 if success, 1 otherwise.

    :rtype: int
    """
    command = [
        MESSAGE_PATH,
        "update",
        json.dumps(self._messages[0]),
        "--pact-dir", self.pact_dir,
        f"--pact-specification-version={self.version}",
        "--consumer", f"{self.consumer.name}",
        "--provider", f"{self.provider.name}",
    ]

    self._message_process = Popen(command)
    self._message_process.wait()

MessageProvider(message_providers, provider, consumer, pact_dir=os.getcwd(), version='3.0.0', proxy_host='localhost', proxy_port='1234')

Bases: object

A Pact message provider.

provider = MessageProvider( message_providers = { "a document created successfully": handler }, provider='DocumentService', pact_dir='pacts', version='3.0.0' )

Source code in src/pact/message_provider.py
def __init__(
    self,
    message_providers,
    provider,
    consumer,
    pact_dir=os.getcwd(),
    version="3.0.0",
    proxy_host='localhost',
    proxy_port='1234'
):
    """Create a Message Provider instance."""
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.message_providers = message_providers
    self.provider = provider
    self.consumer = consumer
    self.version = version
    self.pact_dir = pact_dir
    self.proxy_host = proxy_host
    self.proxy_port = proxy_port
    self._process = None

Attributes

consumer = consumer instance-attribute
message_providers = message_providers instance-attribute
pact_dir = pact_dir instance-attribute
provider = provider instance-attribute
proxy_host = proxy_host instance-attribute
proxy_port = proxy_port instance-attribute
version = version instance-attribute

Functions

verify()

Verify pact files with executable verifier.

Source code in src/pact/message_provider.py
def verify(self):
    """Verify pact files with executable verifier."""
    pact_files = f'{self.pact_dir}/{self._pact_file()}'
    verifier = Verifier(provider=self.provider,
                        provider_base_url=self._proxy_url())
    return_code, _ = verifier.verify_pacts(pact_files, verbose=False)
    assert (return_code == 0), f'Expected returned_code = 0, actual = {return_code}'
verify_with_broker(enable_pending=False, include_wip_pacts_since=None, **kwargs)

Use Broker to verify.

PARAMETER DESCRIPTION
broker_username

broker username

TYPE: [String]

broker_password

broker password

TYPE: [String]

broker_url

url of broker

TYPE: [String]

Source code in src/pact/message_provider.py
def verify_with_broker(self, enable_pending=False, include_wip_pacts_since=None, **kwargs):
    """Use Broker to verify.

    Args:
        broker_username ([String]): broker username
        broker_password ([String]): broker password
        broker_url ([String]): url of broker
        enable_pending ([Boolean])
        include_wip_pacts_since ([String])
        publish_version ([String])

    """
    verifier = Verifier(provider=self.provider,
                        provider_base_url=self._proxy_url())

    return_code, _ = verifier.verify_with_broker(enable_pending, include_wip_pacts_since, **kwargs)

    assert (return_code == 0), f'Expected returned_code = 0, actual = {return_code}'

Pact(consumer, provider, host_name='localhost', port=1234, log_dir=None, ssl=False, sslcert=None, sslkey=None, cors=False, publish_to_broker=False, broker_base_url=None, broker_username=None, broker_password=None, broker_token=None, pact_dir=None, specification_version='2.0.0', file_write_mode='overwrite')

Bases: Broker

Represents a contract between a consumer and provider.

Provides Python context handlers to configure the Pact mock service to perform tests on a Python consumer. For example:

from pact import Consumer, Provider pact = Consumer('consumer').has_pact_with(Provider('provider')) (pact.given('the echo service is available') ... .upon_receiving('a request is made to the echo service') ... .with_request('get', '/echo', query={'text': 'Hello!'}) ... .will_respond_with(200, body='Hello!')) with pact: ... requests.get(pact.uri + '/echo?text=Hello!')

The GET request is made to the mock service, which will verify that it was a GET to /echo with a query string with a key named text and its value is Hello!. If the request does not match an error is raised, if it does match the defined interaction, it will respond with the text Hello!.

:param consumer: The consumer for this contract. :type consumer: pact.Consumer :param provider: The provider for this contract. :type provider: pact.Provider :param host_name: The host name where the mock service is running. :type host_name: str :param port: The port number where the mock service is running. :type port: int :param log_dir: The directory where logs should be written. Defaults to the current directory. :type log_dir: str :param ssl: Flag to control the use of a self-signed SSL cert to run the server over HTTPS , defaults to False. :type ssl: bool :param sslcert: Path to a custom self-signed SSL cert file, 'ssl' option must be set to True to use this option. Defaults to None. :type sslcert: str :param sslkey: Path to a custom key and self-signed SSL cert key file, 'ssl' option must be set to True to use this option. Defaults to None. :type sslkey: str :param cors: Allow CORS OPTION requests to be accepted, defaults to False. :type cors: bool :param publish_to_broker: Flag to control automatic publishing of pacts to a pact broker. Defaults to False. :type publish_to_broker: bool :param broker_base_url: URL of the pact broker that pacts will be published to. Can also be supplied through the PACT_BROKER_BASE_URL environment variable. Defaults to None. :type broker_base_url: str :param broker_username: Username to use when connecting to the pact broker if authentication is required. Can also be supplied through the PACT_BROKER_USERNAME environment variable. Defaults to None. :type broker_username: str :param broker_password: Password to use when connecting to the pact broker if authentication is required. Strongly recommend supplying this value through the PACT_BROKER_PASSWORD environment variable instead. Defaults to None. :type broker_password: str :param broker_token: Authentication token to use when connecting to the pact broker. Strongly recommend supplying this value through the PACT_BROKER_TOKEN environment variable instead. Defaults to None. :type broker_token: str :param pact_dir: Directory where the resulting pact files will be written. Defaults to the current directory. :type pact_dir: str :param specification_version: The Pact Specification version to use, defaults to '2.0.0'. :type version: str of the consumer version. :param file_write_mode: overwrite or merge. Use merge when running multiple mock service instances in parallel for the same consumer/provider pair. Ensure the pact file is deleted before running tests when using this option so that interactions deleted from the code are not maintained in the file. Defaults to overwrite. :type file_write_mode: str

Source code in src/pact/pact.py
def __init__(
    self,
    consumer,
    provider,
    host_name='localhost',
    port=1234,
    log_dir=None,
    ssl=False,
    sslcert=None,
    sslkey=None,
    cors=False,
    publish_to_broker=False,
    broker_base_url=None,
    broker_username=None,
    broker_password=None,
    broker_token=None,
    pact_dir=None,
    specification_version='2.0.0',
    file_write_mode='overwrite',
):
    """
    Create a Pact instance.

    :param consumer: The consumer for this contract.
    :type consumer: pact.Consumer
    :param provider: The provider for this contract.
    :type provider: pact.Provider
    :param host_name: The host name where the mock service is running.
    :type host_name: str
    :param port: The port number where the mock service is running.
    :type port: int
    :param log_dir: The directory where logs should be written. Defaults to
        the current directory.
    :type log_dir: str
    :param ssl: Flag to control the use of a self-signed SSL cert to run
        the server over HTTPS , defaults to False.
    :type ssl: bool
    :param sslcert: Path to a custom self-signed SSL cert file, 'ssl'
        option must be set to True to use this option. Defaults to None.
    :type sslcert: str
    :param sslkey: Path to a custom key and self-signed SSL cert key file,
        'ssl' option must be set to True to use this option.
        Defaults to None.
    :type sslkey: str
    :param cors: Allow CORS OPTION requests to be accepted,
        defaults to False.
    :type cors: bool
    :param publish_to_broker: Flag to control automatic publishing of
        pacts to a pact broker. Defaults to False.
    :type publish_to_broker: bool
    :param broker_base_url: URL of the pact broker that pacts will be
        published to. Can also be supplied through the PACT_BROKER_BASE_URL
        environment variable. Defaults to None.
    :type broker_base_url: str
    :param broker_username: Username to use when connecting to the pact
        broker if authentication is required. Can also be supplied through
        the PACT_BROKER_USERNAME environment variable. Defaults to None.
    :type broker_username: str
    :param broker_password: Password to use when connecting to the pact
        broker if authentication is required. Strongly recommend supplying
        this value through the PACT_BROKER_PASSWORD environment variable
        instead. Defaults to None.
    :type broker_password: str
    :param broker_token: Authentication token to use when connecting to
        the pact broker. Strongly recommend supplying this value through
        the PACT_BROKER_TOKEN environment variable instead.
        Defaults to None.
    :type broker_token: str
    :param pact_dir: Directory where the resulting pact files will be
        written. Defaults to the current directory.
    :type pact_dir: str
    :param specification_version: The Pact Specification version to use, defaults to
        '2.0.0'.
    :type version: str of the consumer version.
    :param file_write_mode: `overwrite` or `merge`. Use `merge` when
        running multiple mock service instances in parallel for the same
        consumer/provider pair. Ensure the pact file is deleted before
        running tests when using this option so that interactions deleted
        from the code are not maintained in the file. Defaults to
        `overwrite`.
    :type file_write_mode: str
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    super().__init__(
        broker_base_url, broker_username, broker_password, broker_token
    )

    scheme = 'https' if ssl else 'http'
    self.uri = '{scheme}://{host_name}:{port}'.format(
        host_name=host_name, port=port, scheme=scheme)
    self.consumer = consumer
    self.cors = cors
    self.file_write_mode = file_write_mode
    self.host_name = host_name
    self.log_dir = log_dir or os.getcwd()
    self.pact_dir = pact_dir or os.getcwd()
    self.port = port
    self.provider = provider
    self.publish_to_broker = publish_to_broker
    self.ssl = ssl
    self.sslcert = sslcert
    self.sslkey = sslkey
    self.specification_version = specification_version
    self._interactions = []
    self._process = None

Attributes

HEADERS = {'X-Pact-Mock-Service': 'true'} class-attribute instance-attribute
MANDATORY_FIELDS = {'response', 'description', 'request'} class-attribute instance-attribute
consumer = consumer instance-attribute
cors = cors instance-attribute
file_write_mode = file_write_mode instance-attribute
host_name = host_name instance-attribute
log_dir = log_dir or os.getcwd() instance-attribute
pact_dir = pact_dir or os.getcwd() instance-attribute
port = port instance-attribute
provider = provider instance-attribute
publish_to_broker = publish_to_broker instance-attribute
specification_version = specification_version instance-attribute
ssl = ssl instance-attribute
sslcert = sslcert instance-attribute
sslkey = sslkey instance-attribute
uri = '{scheme}://{host_name}:{port}'.format(host_name=host_name, port=port, scheme=scheme) instance-attribute

Functions

given(provider_state)

Define the provider state for this pact.

When the provider verifies this contract, they will use this field to setup pre-defined data that will satisfy the response expectations.

:param provider_state: The short sentence that is unique to describe the provider state for this contract. :type provider_state: basestring :rtype: Pact

Source code in src/pact/pact.py
def given(self, provider_state):
    """
    Define the provider state for this pact.

    When the provider verifies this contract, they will use this field to
    setup pre-defined data that will satisfy the response expectations.

    :param provider_state: The short sentence that is unique to describe
        the provider state for this contract.
    :type provider_state: basestring
    :rtype: Pact
    """
    self._insert_interaction_if_complete()
    self._interactions[0]['provider_state'] = provider_state
    return self
setup()

Configure the Mock Service to ready it for a test.

Source code in src/pact/pact.py
def setup(self):
    """Configure the Mock Service to ready it for a test."""
    try:
        # First, check that the interactions are all complete
        for interaction in self._interactions:
            missing_fields = [f for f in self.MANDATORY_FIELDS if f not in interaction]
            if missing_fields:
                raise PactException(f"Interaction incomplete, missing field(s): {', '.join(missing_fields)}")

        interactions_uri = f"{self.uri}/interactions"
        resp = requests.delete(
            interactions_uri, headers=self.HEADERS, verify=False
        )

        assert resp.status_code == 200, resp.text
        resp = requests.put(
            interactions_uri,
            headers=self.HEADERS,
            verify=False,
            json={"interactions": self._interactions},
        )

        assert resp.status_code == 200, resp.text
    except AssertionError:
        raise
start_service()

Start the external Mock Service.

:raises RuntimeError: if there is a problem starting the mock service.

Source code in src/pact/pact.py
def start_service(self):
    """
    Start the external Mock Service.

    :raises RuntimeError: if there is a problem starting the mock service.
    """
    command = [
        MOCK_SERVICE_PATH,
        "service",
        f"--host={self.host_name}",
        f"--port={format(self.port)}",
        "--log", f"{self.log_dir}/pact-mock-service.log",
        "--pact-dir", self.pact_dir,
        "--pact-file-write-mode", self.file_write_mode,
        f"--pact-specification-version={self.specification_version}",
        "--consumer", self.consumer.name,
        "--provider", self.provider.name,
    ]

    if self.ssl:
        command.append('--ssl')
    if self.sslcert:
        command.extend(['--sslcert', self.sslcert])
    if self.sslkey:
        command.extend(['--sslkey', self.sslkey])
    if self.cors:
        command.extend(['--cors'])

    self._process = Popen(command)
    self._wait_for_server_start()
stop_service()

Stop the external Mock Service.

Source code in src/pact/pact.py
def stop_service(self):
    """Stop the external Mock Service."""
    is_windows = 'windows' in platform.platform().lower()
    if is_windows:
        # Send the signal to ruby.exe, not the *.bat process
        p = psutil.Process(self._process.pid)
        for child in p.children(recursive=True):
            child.terminate()
        p.wait()
        if psutil.pid_exists(self._process.pid):
            raise RuntimeError(
                'There was an error when stopping the Pact mock service.')

    else:
        self._process.terminate()

        self._process.communicate()
        if self._process.returncode != 0:
            raise RuntimeError(
                'There was an error when stopping the Pact mock service.'
            )
    if self.publish_to_broker:
        self.publish(
            self.consumer.name,
            self.consumer.version,
            tag_with_git_branch=self.consumer.tag_with_git_branch,
            consumer_tags=self.consumer.tags,
            branch=self.consumer.branch,
            pact_dir=self.pact_dir,
            build_url=self.consumer.build_url,
            auto_detect_version_properties=self.consumer.auto_detect_version_properties
        )
upon_receiving(scenario)

Define the name of this contract.

:param scenario: A unique name for this contract. :type scenario: basestring :rtype: Pact

Source code in src/pact/pact.py
def upon_receiving(self, scenario):
    """
    Define the name of this contract.

    :param scenario: A unique name for this contract.
    :type scenario: basestring
    :rtype: Pact
    """
    self._insert_interaction_if_complete()
    self._interactions[0]['description'] = scenario
    return self
verify()

Have the mock service verify all interactions occurred.

Calls the mock service to verify that all interactions occurred as expected, and has it write out the contracts to disk.

:raises AssertionError: When not all interactions are found.

Source code in src/pact/pact.py
def verify(self):
    """
    Have the mock service verify all interactions occurred.

    Calls the mock service to verify that all interactions occurred as
    expected, and has it write out the contracts to disk.

    :raises AssertionError: When not all interactions are found.
    """
    self._interactions = []
    resp = requests.get(
        self.uri + "/interactions/verification", headers=self.HEADERS, verify=False
    )
    assert resp.status_code == 200, resp.text
    resp = requests.post(self.uri + "/pact", headers=self.HEADERS, verify=False)
    assert resp.status_code == 200, resp.text
will_respond_with(status, headers=None, body=None)

Define the response the server is expected to create.

:param status: The HTTP status code. :type status: int :param headers: All required headers. Defaults to None. :type headers: dict or None :param body: The response body, or a collection of Matcher objects to allow for pattern matching. Defaults to None. :type body: Matcher, dict, list, basestring, or None :rtype: Pact

Source code in src/pact/pact.py
def will_respond_with(self, status, headers=None, body=None):
    """
    Define the response the server is expected to create.

    :param status: The HTTP status code.
    :type status: int
    :param headers: All required headers. Defaults to None.
    :type headers: dict or None
    :param body: The response body, or a collection of Matcher objects to
        allow for pattern matching. Defaults to None.
    :type body: Matcher, dict, list, basestring, or None
    :rtype: Pact
    """
    self._insert_interaction_if_complete()
    self._interactions[0]['response'] = Response(
        status, headers=headers, body=body
    ).json()
    return self
with_request(method, path, body=None, headers=None, query=None)

Define the request that the client is expected to perform.

:param method: The HTTP method. :type method: str :param path: The path portion of the URI the client will access. :type path: str, Matcher :param body: The request body, can be a string or an object that will serialize to JSON, like list or dict, defaults to None. :type body: list, dict or None :param headers: The headers the client is expected to include on with this request. Defaults to None. :type headers: dict or None :param query: The query options the client is expected to send. Can be a dict of keys and values, or a URL encoded string. Defaults to None. :type query: dict, basestring, or None :rtype: Pact

Source code in src/pact/pact.py
def with_request(self, method, path, body=None, headers=None, query=None):
    """
    Define the request that the client is expected to perform.

    :param method: The HTTP method.
    :type method: str
    :param path: The path portion of the URI the client will access.
    :type path: str, Matcher
    :param body: The request body, can be a string or an object that will
        serialize to JSON, like list or dict, defaults to None.
    :type body: list, dict or None
    :param headers: The headers the client is expected to include on with
        this request. Defaults to None.
    :type headers: dict or None
    :param query: The query options the client is expected to send. Can be
        a dict of keys and values, or a URL encoded string.
        Defaults to None.
    :type query: dict, basestring, or None
    :rtype: Pact
    """
    self._insert_interaction_if_complete()
    self._interactions[0]['request'] = Request(
        method, path, body=body, headers=headers, query=query
    ).json()
    return self

Provider(name)

Bases: object

A Pact provider.

:param name: The name of this provider. This will be shown in the Pact when it is published. :type name: str

Source code in src/pact/provider.py
def __init__(self, name):
    """
    Create a new Provider.

    :param name: The name of this provider. This will be shown in the Pact
        when it is published.
    :type name: str
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.name = name

Attributes

name = name instance-attribute

Term(matcher, generate)

Bases: Matcher

Expect the response to match a specified regular expression.

Example:

from pact import Consumer, Provider pact = Consumer('consumer').has_pact_with(Provider('provider')) (pact.given('the current user is logged in as tester') ... .upon_receiving('a request for the user profile') ... .with_request('get', '/profile') ... .will_respond_with(200, body={ ... 'name': 'tester', ... 'theme': Term('light|dark|legacy', 'dark') ... }))

Would expect the response body to be a JSON object, containing the key name, which will contain the value tester, and theme which must be one of the values: light, dark, or legacy. When the consumer runs this contract, the value dark will be returned by the mock service.

:param matcher: A regular expression to find. :type matcher: basestring :param generate: A value to be returned by the mock service when generating the response to the consumer. :type generate: basestring

Source code in src/pact/matchers.py
def __init__(self, matcher, generate):
    """
    Create a new Term.

    :param matcher: A regular expression to find.
    :type matcher: basestring
    :param generate: A value to be returned by the mock service when
        generating the response to the consumer.
    :type generate: basestring
    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.matcher = matcher
    self._generate = generate

Attributes

matcher = matcher instance-attribute

Functions

generate()

Return the value that should be used in the request/response.

:return: A dict containing the information about what the contents of the response should be, and what should match for the requests. :rtype: dict

Source code in src/pact/matchers.py
def generate(self):
    """
    Return the value that should be used in the request/response.

    :return: A dict containing the information about what the contents of
        the response should be, and what should match for the requests.
    :rtype: dict
    """
    return {
        'json_class': 'Pact::Term',
        'data': {
            'generate': self._generate,
            'matcher': {
                'json_class': 'Regexp',
                'o': 0,
                's': self.matcher}}}

Verifier(provider, provider_base_url, **kwargs)

Bases: object

A Pact Verifier.

PARAMETER DESCRIPTION
provider

provider name

TYPE: [String]

provider_base_url

provider url

TYPE: [String]

Source code in src/pact/verifier.py
def __init__(self, provider, provider_base_url, **kwargs):
    """Create a new Verifier.

    Args:
        provider ([String]): provider name
        provider_base_url ([String]): provider url

    """
    warnings.warn(
        "This class will be deprecated Pact Python v3 "
        "(see pact-foundation/pact-python#396)",
        PendingDeprecationWarning,
        stacklevel=2,
    )
    self.provider = provider
    self.provider_base_url = provider_base_url

Attributes

provider = provider instance-attribute
provider_base_url = provider_base_url instance-attribute

Functions

extract_params(**kwargs)

Extract params.

Source code in src/pact/verifier.py
def extract_params(self, **kwargs):
    """Extract params."""
    log_dir = kwargs.get('log_dir', None)
    log_level = kwargs.get('log_level', 'INFO')
    headers = kwargs.get('headers', [])
    timeout = kwargs.get('timeout', None)
    consumer_tags = kwargs.get('consumer_tags', [])
    provider_tags = kwargs.get('provider_tags', [])
    states_setup_url = kwargs.get('provider_states_setup_url', None)
    verbose = kwargs.get('verbose', False)
    provider_app_version = kwargs.get('publish_version', None)
    publish_verification_results = kwargs.get('publish_verification_results', None)
    raw_consumer_selectors = kwargs.get('consumer_version_selectors', [])
    consumer_selectors = self._build_consumer_selectors(raw_consumer_selectors)
    provider_version_branch = kwargs.get('provider_version_branch')

    options = {
        'log_dir': log_dir,
        'log_level': log_level,
        'provider_app_version': provider_app_version,
        'custom_provider_headers': list(headers),
        'timeout': timeout,
        'consumer_tags': list(consumer_tags),
        'provider_tags': list(provider_tags),
        'provider_states_setup_url': states_setup_url,
        'verbose': verbose,
        'consumer_selectors': consumer_selectors,
        'publish_verification_results': publish_verification_results,
        'provider_version_branch': provider_version_branch
    }
    return self.filter_empty_options(**options)
filter_empty_options(**kwargs)

Filter out empty options.

Source code in src/pact/verifier.py
def filter_empty_options(self, **kwargs):
    """Filter out empty options."""
    kwargs = dict(filter(lambda item: item[1] is not None, kwargs.items()))
    kwargs = dict(filter(lambda item: item[1] != '', kwargs.items()))
    kwargs = dict(filter(lambda item: self.is_empty_list(item), kwargs.items()))
    return kwargs
is_empty_list(item)

Util for is empty lists.

Source code in src/pact/verifier.py
def is_empty_list(self, item):
    """Util for is empty lists."""
    return (not isinstance(item[1], list)) or (len(item[1]) != 0)
validate_publish(**kwargs)

Validate publish has a version.

Source code in src/pact/verifier.py
def validate_publish(self, **kwargs):
    """Validate publish has a version."""
    if (kwargs.get('publish') is not None) and (kwargs.get('publish_version') is None):
        # do something
        raise Exception()
verify_pacts(*pacts, enable_pending=False, include_wip_pacts_since=None, **kwargs)

Verify our pacts from the provider.

RETURNS DESCRIPTION
success

True if no failures

logs

some tbd output of logs

Source code in src/pact/verifier.py
def verify_pacts(self, *pacts, enable_pending=False, include_wip_pacts_since=None, **kwargs):
    """Verify our pacts from the provider.

    Returns:
      success: True if no failures
      logs: some tbd output of logs

    """
    self.validate_publish(**kwargs)

    missing_files = [path for path in pacts if not path_exists(path)]
    if missing_files:
        raise Exception("Missing pact files {}".format(missing_files))

    pacts = expand_directories(pacts)

    options = self.extract_params(**kwargs)
    success, logs = VerifyWrapper().call_verify(*pacts,
                                                provider=self.provider,
                                                provider_base_url=self.provider_base_url,
                                                enable_pending=enable_pending,
                                                include_wip_pacts_since=include_wip_pacts_since,
                                                **options)

    return success, logs
verify_with_broker(enable_pending=False, include_wip_pacts_since=None, **kwargs)

Use Broker to verify.

PARAMETER DESCRIPTION
broker_username

broker username

TYPE: [String]

broker_password

broker password

TYPE: [String]

broker_url

url of broker

TYPE: [String]

Source code in src/pact/verifier.py
def verify_with_broker(self, enable_pending=False, include_wip_pacts_since=None, **kwargs):
    """Use Broker to verify.

    Args:
        broker_username ([String]): broker username
        broker_password ([String]): broker password
        broker_url ([String]): url of broker
        enable_pending ([Boolean])
        include_wip_pacts_since ([String])
        publish_version ([String])

    """
    broker_username = kwargs.get('broker_username', None)
    broker_password = kwargs.get('broker_password', None)
    broker_url = kwargs.get('broker_url', None)
    broker_token = kwargs.get('broker_token', None)

    options = {
        'broker_password': broker_password,
        'broker_username': broker_username,
        'broker_token': broker_token,
        'broker_url': broker_url
    }
    options.update(self.extract_params(**kwargs))

    success, logs = VerifyWrapper().call_verify(provider=self.provider,
                                                provider_base_url=self.provider_base_url,
                                                enable_pending=enable_pending,
                                                include_wip_pacts_since=include_wip_pacts_since,
                                                **options)
    return success, logs