{
    "slug": "api_contract_testing",
    "term": "API Contract Testing",
    "category": "api_design",
    "difficulty": "advanced",
    "short": "Consumer-driven contract tests verify that a provider API matches what consumers expect — catching breaking changes before deployment, without end-to-end tests.",
    "long": "Consumer-driven contract testing (Pact): the consumer defines a contract (the requests it makes and responses it expects), the provider verifies it can fulfil those contracts independently. Unlike integration tests, both sides run independently — no shared environment needed. The Pact Broker stores and shares contracts between teams. Benefits: catches breaking API changes in CI without a shared staging environment, enables independent service deployments, and documents the actual consumer expectations. PHP: pact-foundation/pact-php, pest-pact.",
    "aliases": [
        "Pact",
        "consumer-driven contracts",
        "contract test",
        "API verification"
    ],
    "tags": [
        "api-design",
        "testing",
        "microservices"
    ],
    "misconception": "End-to-end tests are better than contract tests — E2E tests require a full environment and are slow and flaky; contract tests run in isolation, are fast, and give specific failure messages about which contract was violated.",
    "why_it_matters": "A provider team changing a field name from user_email to email breaks a consumer that was never told about the change — contract tests catch this in the provider's CI pipeline before deployment.",
    "common_mistakes": [
        "Provider-driven contracts — the provider dictates what it sends, not what consumers need.",
        "Not running contract tests in CI — contracts only help if violations are caught automatically.",
        "Overly specific contracts — test the fields you use, not the entire response structure.",
        "No Pact Broker — contracts stored locally cannot be shared between teams."
    ],
    "when_to_use": [
        "Services owned by different teams or deployed independently — contract tests catch provider changes before they reach staging.",
        "Public or partner APIs where breaking changes have downstream cost and manual coordination is slow.",
        "CI pipelines between microservices to get fast feedback without spinning up the full environment."
    ],
    "avoid_when": [
        "A single team owns both consumer and provider and deploys them together — integration tests are simpler.",
        "The API surface changes so frequently that maintaining contracts costs more than the bugs they prevent.",
        "Simple internal SDKs where the provider and consumer share the same codebase and test suite."
    ],
    "related": [
        "api_documentation",
        "api_versioning",
        "api_backwards_compatibility",
        "integration_testing"
    ],
    "prerequisites": [
        "api_backwards_compatibility",
        "integration_testing",
        "api_documentation"
    ],
    "refs": [
        "https://docs.pact.io/"
    ],
    "bad_code": "// No contract testing — breaking changes discovered in staging:\n// Provider renames 'user_email' to 'email' in v2\n// Consumer teams never notified\n// Integration test catches it... in a 2-hour E2E test run\n// Fix: roll back provider deployment, coordinate change\n// Cost: 4 hours of engineer time",
    "good_code": "// Pact consumer test:\n$builder->given('user 42 exists')\n    ->uponReceiving('a request for user 42')\n    ->with(['method' => 'GET', 'path' => '/users/42'])\n    ->willRespondWith([\n        'status' => 200,\n        'body'   => ['id' => 42, 'email' => 'alice@example.com'],\n    ]);\n\n// Provider verification runs against actual implementation:\n$verifier->verify(); // Fails if provider returns user_email not email\n// Caught in provider's CI — before deployment\n// Fix: coordinate field rename with consumer teams first",
    "example_note": "The Pact consumer test defines exactly what fields and status codes the consumer depends on — the provider can add fields freely but cannot rename or remove what the contract specifies.",
    "quick_fix": "Use Pact for consumer-driven contract testing — the consumer defines what it expects, the provider verifies it satisfies those expectations without running the full stack",
    "severity": "medium",
    "effort": "high",
    "created": "2026-03-16",
    "updated": "2026-03-31",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/api_contract_testing",
        "html_url": "https://codeclaritylab.com/glossary/api_contract_testing",
        "json_url": "https://codeclaritylab.com/glossary/api_contract_testing.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[API Contract Testing](https://codeclaritylab.com/glossary/api_contract_testing) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/api_contract_testing"
            }
        }
    }
}