Match
Matching functionality.
This module defines flexible matching rules for use in Pact contracts. These rules specify the expected content of exchanged data, allowing for more robust contract testing than simple equality checks.
For example, a contract may specify how a new record is created via a POST request. The consumer defines the data to send and the expected response. The response may include additional fields from the provider, such as an ID or creation timestamp. The contract can require the ID to match a specific format (e.g., integer or UUID) and the timestamp to be ISO 8601.
Warning
Do not import functions directly from this module. Instead, import the
match
module and use its functions:
Many functions in this module are named after the types they match (e.g., int
,
str
, bool
). Importing directly from this module may shadow Python built-in
types, so always use the match
module.
Matching rules are often combined with generators, which allow Pact to produce
values dynamically during contract tests. If a value
is not provided, a
generator is used; if a value
is provided, a generator is not used. This is
not advised, as leads to non-deterministic tests.
Note
You do not need to specify everything that will be returned from the provider in a JSON response. Any extra data that is received will be ignored and the tests will still pass, as long as the expected fields match the defined patterns.
For more information about the Pact matching specification, see Matching.
Type Matching¶
The most common matchers validate that values are of a specific type. These matchers can optionally accept example values:
from pact import match
response = {
"id": match.int(123), # Any integer (example: 123)
"name": match.str("Alice"), # Any string (example: "Alice")
"score": match.float(98.5), # Any float (example: 98.5)
"active": match.bool(True), # Any boolean (example: True)
"tags": match.each_like("admin"), # Array of strings (example: ["admin"])
}
When no example value is provided, Pact will generate appropriate values automatically, but this is not advised, as it leads to non-deterministic tests.
Regular Expression Matching¶
For values that must match a specific pattern, use match.regex()
with a
regular expression:
response = {
"reference": match.regex("X1234-456def", regex=r"[A-Z]\d{3,6}-[0-9a-f]{6}"),
"phone": match.regex("+1-555-123-4567", regex=r"\+1-\d{3}-\d{3}-\d{4}"),
}
Note that the regular expression should be provided as a raw string (using the
r"..."
syntax) to avoid issues with escape sequences. Advanced regex features
like lookaheads and lookbehinds should be avoided, as they may not be supported
by all Pact implementations.
Complex Objects¶
For complex nested objects, matchers can be combined to create sophisticated matching rules:
from pact import match
user_response = {
"id": match.int(123),
"name": match.str("Alice"),
"email": match.regex(
"alice@example.com",
regex=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
),
"confirmed": match.bool(True),
"address": {
"street": match.str("123 Main St"),
"city": match.str("Anytown"),
"postal_code": match.regex("12345", regex=r"\d{5}"),
},
"roles": match.each_like(match.str("admin")), # Array of strings
}
The match.type()
(or its alias match.like()
) function provides generic type
matching for any value:
# These are equivalent to the specific type matchers
response = {
"id": match.type(123), # Same as match.int(123)
"name": match.like("Alice"), # Same as match.str("Alice")
}
Array Matching¶
For arrays where each element should match a specific pattern, use
match.each_like()
:
from pact import match
# Simple arrays
response = {
"tags": match.each_like(match.str("admin")), # Array of strings
"scores": match.each_like(match.int(95)), # Array of integers
"active": match.each_like(match.bool(True)), # Array of booleans
}
# Complex nested objects in arrays
users_response = {
"users": match.each_like({
"id": match.int(123),
"username": match.regex("alice123", regex=r"[a-zA-Z]+\d*"),
"roles": match.each_like(match.str("user")), # Nested array
})
}
You can also control the minimum and maximum number of array elements:
For arrays that must contain specific elements regardless of order, use
match.array_containing()
. For example, to ensure an array includes certain
permissions:
response = {
"permissions": match.array_containing([
match.str("read"),
match.str("write"),
match.regex("admin-edit", regex=r"admin-\w+"),
])
}
Note that additional elements may be present in the array; the matcher only ensures the specified elements are included.
Date and Time Matching¶
The match
module provides specialized matchers for date and time values:
from pact import match
from datetime import date, time, datetime
response = {
# Date matching (YYYY-MM-DD format by default)
"birth_date": match.date("2024-07-20"),
"birth_date_obj": match.date(date(2024, 7, 20)),
# Time matching (HH:MM:SS format by default)
"start_time": match.time("14:30:00"),
"start_time_obj": match.time(time(14, 30, 0)),
# DateTime matching (ISO 8601 format by default)
"created_at": match.datetime("2024-07-20T14:30:00+00:00"),
"updated_at": match.datetime(datetime(2024, 7, 20, 14, 30, 0)),
# Custom formats using Python strftime patterns
"custom_date": match.date("07/20/2024", format="%m/%d/%Y"),
"custom_time": match.time("2:30 PM", format="%I:%M %p"),
}
Specialized Matchers¶
Other commonly used matchers include:
from pact import match
response = {
# UUID matching with different formats
"id": match.uuid("550e8400-e29b-41d4-a716-446655440000"),
"simple_id": match.uuid(format="simple"), # No hyphens
"uppercase_id": match.uuid(format="uppercase"), # Uppercase letters
# Number matching with constraints
"age": match.int(25, min=18, max=99),
"price": match.float(19.99, precision=2),
"count": match.number(42), # Generic number matcher
# String matching with constraints
"username": match.str("alice123", size=8),
"description": match.str(), # Any string
# Null values
"optional_field": match.none(), # or match.null()
# String inclusion matching
"message": match.includes("success"), # Must contain "success"
}
Advanced Dictionary Matching¶
For dynamic dictionary structures, you can match keys and values separately:
# Match each key against a pattern
user_permissions = match.each_key_matches(
{"admin-read": True, "admin-write": False},
rules=match.regex("admin-read", regex=r"admin-\w+"),
)
# Match each value against a pattern
user_scores = match.each_value_matches(
{"math": 95, "science": 87}, rules=match.int(85, min=0, max=100)
)
Attributes¶
Classes¶
AbstractMatcher
¶
Abstract matcher.
In Pact, a matcher is used to define how a value should be compared. This allows for more flexible matching of data, especially when the provider returns dynamically generated data.
This class is abstract and should not be used directly. Instead, use one of the concrete matcher classes. Alternatively, you can create your own matcher by subclassing this class.
The matcher provides methods to convert into an integration JSON object and a matching rule. These methods are used internally by the Pact library when communicating with the FFI and generating the Pact file.
Functions¶
to_integration_json() -> dict[str, Any]
abstractmethod
¶
Convert the matcher to an integration JSON object.
This method is used internally to convert the matcher to a JSON object which can be embedded directly in a number of places in the Pact FFI.
For more information about this format, see the integration JSON docs.
RETURNS | DESCRIPTION |
---|---|
dict[str, Any]
|
The matcher as an integration JSON object. |
Source code in src/pact/match/matcher.py
to_matching_rule() -> dict[str, Any]
abstractmethod
¶
Convert the matcher to a matching rule.
This method is used internally to convert the matcher to a matching rule which can be embedded directly in a Pact file.
For more information about this format, refer to the Pact specification and the matchers section
RETURNS | DESCRIPTION |
---|---|
dict[str, Any]
|
The matcher as a matching rule. |
Source code in src/pact/match/matcher.py
Functions¶
array_containing(variants: Sequence[_T | AbstractMatcher[_T]]) -> AbstractMatcher[Sequence[_T]]
¶
Match an array containing the given variants.
Each variant must occur at least once. Variants may be matchers or objects.
PARAMETER | DESCRIPTION |
---|---|
variants
|
List of variants to match against.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[Sequence[_T]]
|
Matcher for arrays containing the given variants. |
Source code in src/pact/match/__init__.py
bool(value: builtins.bool | Unset = UNSET) -> AbstractMatcher[builtins.bool]
¶
Match a boolean value.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[bool]
|
Matcher for boolean values. |
Source code in src/pact/match/__init__.py
boolean(value: builtins.bool | Unset = UNSET) -> AbstractMatcher[builtins.bool]
¶
date(value: dt.date | builtins.str | Unset = UNSET, /, format: builtins.str | None = None, *, disable_conversion: builtins.bool = False) -> AbstractMatcher[builtins.str]
¶
Match a date value (string, no time component).
Uses Python's
strftime
format, converted to Java
SimpleDateFormat
for Pact compatibility.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
format
|
Date format string. Defaults to ISO 8601 (
TYPE:
|
disable_conversion
|
If True, the conversion from Python's
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[str]
|
Matcher for date strings. |
Source code in src/pact/match/__init__.py
datetime(value: dt.datetime | builtins.str | Unset = UNSET, /, format: builtins.str | None = None, *, disable_conversion: builtins.bool = False) -> AbstractMatcher[builtins.str]
¶
Match a datetime value (string, date and time).
Uses Python's
strftime
format, converted to Java
SimpleDateFormat
for Pact compatibility.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
format
|
Datetime format string. Defaults to ISO 8601 (
TYPE:
|
disable_conversion
|
If True, disables conversion and expects Java format. Value must be a string.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[str]
|
Matcher for datetime strings. |
Source code in src/pact/match/__init__.py
decimal(value: _NumberT | Unset = UNSET, /, *, precision: builtins.int | None = None) -> AbstractMatcher[_NumberT]
¶
Alias for match.float
.
each_key_matches(value: Mapping[_T, Any], /, *, rules: AbstractMatcher[_T] | list[AbstractMatcher[_T]]) -> AbstractMatcher[Mapping[_T, Matchable]]
¶
Match each key in a dictionary against rules.
PARAMETER | DESCRIPTION |
---|---|
value
|
Dictionary to match against. |
rules
|
Matching rules for each key.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[Mapping[_T, Matchable]]
|
Matcher for dictionaries where each key matches the rules. |
Source code in src/pact/match/__init__.py
each_like(value: _T, /, *, min: builtins.int | None = None, max: builtins.int | None = None) -> AbstractMatcher[Sequence[_T]]
¶
Match each item in an array against a value (can be a matcher).
PARAMETER | DESCRIPTION |
---|---|
value
|
Value to match against (can be a matcher).
TYPE:
|
min
|
Minimum number of items to match (minimum is always 1).
TYPE:
|
max
|
Maximum number of items to match.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[Sequence[_T]]
|
Matcher for arrays where each item matches the value. |
Source code in src/pact/match/__init__.py
each_value_matches(value: Mapping[Any, _T], /, *, rules: AbstractMatcher[_T] | list[AbstractMatcher[_T]]) -> AbstractMatcher[Mapping[Matchable, _T]]
¶
Match each value in a dictionary against rules.
PARAMETER | DESCRIPTION |
---|---|
value
|
Dictionary to match against. |
rules
|
Matching rules for each value.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[Mapping[Matchable, _T]]
|
Matcher for dictionaries where each value matches the rules. |
Source code in src/pact/match/__init__.py
float(value: _NumberT | Unset = UNSET, /, *, precision: builtins.int | None = None) -> AbstractMatcher[_NumberT]
¶
Match a floating-point number.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
precision
|
Number of decimal places to generate.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[_NumberT]
|
Matcher for floating-point numbers. |
Source code in src/pact/match/__init__.py
includes(value: builtins.str, /, *, generator: AbstractGenerator | None = None) -> AbstractMatcher[builtins.str]
¶
Match a string that includes a given value.
PARAMETER | DESCRIPTION |
---|---|
value
|
Value to match against.
TYPE:
|
generator
|
Generator to use for value generation.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[str]
|
Matcher for strings that include the given value. |
Source code in src/pact/match/__init__.py
int(value: builtins.int | Unset = UNSET, /, *, min: builtins.int | None = None, max: builtins.int | None = None) -> AbstractMatcher[builtins.int]
¶
Match an integer value.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
min
|
Minimum value to generate, if set.
TYPE:
|
max
|
Maximum value to generate, if set.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[int]
|
Matcher for integer values. |
Source code in src/pact/match/__init__.py
integer(value: builtins.int | Unset = UNSET, /, *, min: builtins.int | None = None, max: builtins.int | None = None) -> AbstractMatcher[builtins.int]
¶
Alias for match.int
.
Source code in src/pact/match/__init__.py
like(value: _T, /, *, min: builtins.int | None = None, max: builtins.int | None = None, generator: AbstractGenerator | None = None) -> AbstractMatcher[_T]
¶
Alias for match.type
.
Source code in src/pact/match/__init__.py
none() -> AbstractMatcher[None]
¶
null() -> AbstractMatcher[None]
¶
number(value: builtins.int | builtins.float | Decimal | Unset = UNSET, /, *, min: builtins.int | None = None, max: builtins.int | None = None, precision: builtins.int | None = None) -> AbstractMatcher[builtins.int] | AbstractMatcher[builtins.float] | AbstractMatcher[Decimal]
¶
number(
value: builtins.int,
/,
*,
min: builtins.int | None = None,
max: builtins.int | None = None,
) -> AbstractMatcher[builtins.int]
Match any number (integer, float, or Decimal).
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
min
|
Minimum value to generate (for integers).
TYPE:
|
max
|
Maximum value to generate (for integers).
TYPE:
|
precision
|
Number of decimal digits to generate (for floats).
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[int] | AbstractMatcher[float] | AbstractMatcher[Decimal]
|
Matcher for numbers (integer, float, or Decimal). |
Source code in src/pact/match/__init__.py
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
|
regex(value: builtins.str | Unset = UNSET, /, *, regex: builtins.str | None = None) -> AbstractMatcher[builtins.str]
¶
Match a string against a regular expression.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
regex
|
Regular expression pattern to match.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[str]
|
Matcher for strings matching the given regular expression. |
Source code in src/pact/match/__init__.py
str(value: builtins.str | Unset = UNSET, /, *, size: builtins.int | None = None, generator: AbstractGenerator | None = None) -> AbstractMatcher[builtins.str]
¶
Match a string value, optionally with a specific length.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
size
|
Length of string to generate for consumer test.
TYPE:
|
generator
|
Alternative generator for consumer test. If set, ignores
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[str]
|
Matcher for string values. |
Source code in src/pact/match/__init__.py
string(value: builtins.str | Unset = UNSET, /, *, size: builtins.int | None = None, generator: AbstractGenerator | None = None) -> AbstractMatcher[builtins.str]
¶
Alias for match.str
.
Source code in src/pact/match/__init__.py
time(value: dt.time | builtins.str | Unset = UNSET, /, format: builtins.str | None = None, *, disable_conversion: builtins.bool = False) -> AbstractMatcher[builtins.str]
¶
Match a time value (string, no date component).
Uses Python's
strftime
format, converted to Java
SimpleDateFormat
for Pact compatibility.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
format
|
Time format string. Defaults to ISO 8601 (
TYPE:
|
disable_conversion
|
If True, disables conversion and expects Java format. Value must be a string.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[str]
|
Matcher for time strings. |
Source code in src/pact/match/__init__.py
timestamp(value: dt.datetime | builtins.str | Unset = UNSET, /, format: builtins.str | None = None, *, disable_conversion: builtins.bool = False) -> AbstractMatcher[builtins.str]
¶
Alias for match.datetime
.
Source code in src/pact/match/__init__.py
type(value: _T, /, *, min: builtins.int | None = None, max: builtins.int | None = None, generator: AbstractGenerator | None = None) -> AbstractMatcher[_T]
¶
Match a value by type (primitive or complex).
PARAMETER | DESCRIPTION |
---|---|
value
|
Value to match (primitive or complex).
TYPE:
|
min
|
Minimum number of items to match.
TYPE:
|
max
|
Maximum number of items to match.
TYPE:
|
generator
|
Generator to use for value generation.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[_T]
|
Matcher for the given value type. |
Source code in src/pact/match/__init__.py
uuid(value: builtins.str | Unset = UNSET, /, *, format: _UUID_FORMAT_NAMES | None = None) -> AbstractMatcher[builtins.str]
¶
Match a UUID value.
See RFC 4122 for details about the UUID format. Some common, albeit non-compliant, alternative formats are also supported.
PARAMETER | DESCRIPTION |
---|---|
value
|
Example value for consumer test generation. |
format
|
Specify UUID format:
If not set, matches any case.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
AbstractMatcher[str]
|
Matcher for UUID strings. |