Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
contract-testing
description
Consumer-Driven Contract Testing (CDC) using Pact framework and OpenAPI-based contract validation. Covers microservice-to-microservice contract verification, provider contract testing, consumer contract testing, contract publishing pipelines, and contract breaking-change detection.
USE WHEN: designing microservice APIs, establishing service boundaries, verifying service-to-service contract compatibility, integrating with Pact framework, preventing contract-breaking changes, or setting up a contract testing pipeline in CI/CD. Triggers on "contract test", "Pact", "consumer- driven contract", "CDC", "service contract", "API contract", "breaking change".
Contract Testing (Consumer-Driven Contracts)
Source: Pact framework + Martin Fowler + real-world microservice architectures
at Google, ThoughtWorks, and ByteDance
Core Philosophy: Integration tests are slow and brittle. Contract tests
are fast, isolated, and the only practical way to verify microservice
compatibility without deploying everything.
Why Contract Testing Matters
Without contract tests:
❌ Services A and B pass all unit tests but fail together on Sunday night
❌ "It worked in staging!" — because staging has different data/config
❌ Integration test suites take 45+ minutes and flake constantly
❌ API changes break consumers who were "supposed to be notified"
With contract tests:
✅ Each service is verified independently against its contracts
✅ Providers know exactly who depends on what
✅ CI fails in 30 seconds, not 45 minutes
✅ Breaking changes are caught before deployment, not after
Core Concepts
Three Roles
┌──────────────────────────────────────────────────────────────┐
│ │
│ Consumer: The service that calls an API │
│ → Writes contract tests that document its expectations │
│ → "I expect POST /orders to return 201 with order ID" │
│ │
│ Provider: The service that serves the API │
│ → Verifies that it satisfies all consumer contracts │
│ → "Can I still satisfy all my consumers after this change?"│
│ │
│ Broker: The central repository of contracts │
│ → Stores all pacts from all consumers │
│ → Enables can-i-deploy checks │
│ → Shows dependency graph between services │
│ │
└──────────────────────────────────────────────────────────────┘
The Contract Testing Flow
Consumer writes test
┌──────────┐ ┌──────────┐
│ Consumer │────→│ Pact │ Consumer defines expectations
│ Service │ │ File │ (what it expects from the API)
└──────────┘ └──────────┘
│
▼
┌──────────┐
│ Broker │ Pact file is published to broker
└──────────┘
│
▼
┌──────────┐ Provider downloads ALL consumer pacts
│ Provider │ and verifies each one against its
│ Service │ actual implementation
└──────────┘
│
▼
✅ All contracts pass → Safe to deploy
❌ Any contract fails → Must fix before deploy
// test/contract/order-service-verification.test.tsimport { Verifier } from'@pact-foundation/pact';
import { startServer, stopServer } from'../src/server';
describe('Order Service — Pact Provider Verification', () => {
beforeAll(async () => {
awaitstartServer(4001); // Start real service on test port
});
afterAll(async () => {
awaitstopServer();
});
it('satisfies all consumer contracts', async () => {
const opts = {
provider: 'order-service',
providerBaseUrl: 'http://localhost:4001',
// Option A: Verify against broker (preferred)pactBrokerUrl: process.env.PACT_BROKER_URL || 'https://pact-broker.example.com',
pactBrokerToken: process.env.PACT_BROKER_TOKEN,
// Option B: Verify against local pact files (for dev)// pactUrls: [path.resolve(__dirname, '../../pacts/payment-service-order-service.json')],// Provider states (setup data for test scenarios)stateHandlers: {
'order 123 exists': async () => {
// Seed database with order ID 123awaitseedOrder({ id: '123', status: 'confirmed' });
},
'no orders exist': async () => {
// Clear the orders tableawaitclearOrders();
},
},
// Custom verifications beyond defaultrequestFilter: (req, res, next) => {
// Add any custom headers needed
req.headers['x-request-id'] = 'pact-test';
next();
},
};
awaitnewVerifier(opts).verifyProvider();
});
});
2.2 CI Integration (Provider Side)
# .github/workflows/verify-contracts.yml (provider side)name:VerifyConsumerContractson:push:schedule:-cron:'0 */4 * * *'# Every 4 hours — catch new contracts from consumersjobs:verify:runs-on:ubuntu-latestservices:postgres:image:postgres:16-alpineenv:POSTGRES_PASSWORD:testoptions:>-
--health-cmd pg_isready
--health-interval 10s
steps:-uses:actions/checkout@v4-run:npmci-run:npmruntest:provider-verificationenv:PACT_BROKER_URL:${{vars.PACT_BROKER_URL}}PACT_BROKER_TOKEN:${{secrets.PACT_BROKER_TOKEN}}DB_URL:postgres://postgres:test@localhost:5432/test
3. Can-I-Deploy — The Safety Gate
3.1 What is Can-I-Deploy?
The broker tracks which consumer versions have been verified against which provider versions. Can-I-Deploy checks this matrix:
# Before deploying a new provider version:
pact-broker can-i-deploy \
--pacticipant order-service \
--version $(git rev-parse HEAD) \
--to-environment production
# Before deploying a new consumer version:
pact-broker can-i-deploy \
--pacticipant payment-service \
--version $(git rev-parse HEAD) \
--to-environment production
3.2 The Matrix
Provider: order-service
┌────────────────────────────────────┐
│ v1.0 │ v1.1 │ v2.0 (proposed) │
┌─────────────────┼───────┼───────┼───────────────────┤
│ payment v2.1 │ ✅ │ ✅ │ ❌ │
│ notification v1.0 │ ✅ │ ❌ │ ❌ │
│ analytics v3.0 │ ✅ │ ⚠️ │ ✅ │
└─────────────────┴───────┴───────┴───────────────────┘
Result: payment v2.1 is NOT verified against order v2.0
→ Block deployment until contract is resolved
3.3 GitLab CI / GitHub Actions Gate
# Add to deployment workflowdeploy:stage:deployscript:-pact-brokercan-i-deploy--pacticipantorder-service--version$CI_COMMIT_SHA--to-environmentproduction-./deploy.shonly:-main
DO:
✓ Test realistic data shapes (use matchers for flexible fields)
✓ Keep pact files version-controlled
✓ Verify provider contracts in CI on every push
✓ Use Pact Broker's webhooks to trigger provider verification
✓ Add can-i-deploy to deployment pipeline
DON'T:
✗ Test exhaustive responses — test the contract shape, not all data
✗ Forget to manage provider states — they are essential for meaningful testing
✗ Hardcode exact values unless they're contractually required
✗ Use contract tests for performance or load testing
✗ Let contract tests replace unit/integration tests — they are complementary
8. Contract Testing vs Integration Testing
┌─────────────────────┬─────────────────────┬─────────────────┐
│ Aspect │ Contract Test │ Integration │
├─────────────────────┼─────────────────────┼─────────────────┤
│ Speed │ ~100ms per pact │ 5-60 min │
│ Isolation │ Full (mock provider)│ Partial (real) │
│ Network required │ No │ Yes │
│ Real data │ No │ Yes │
│ Deployment blocking │ Yes (with broker) │ No │
│ Flaky? │ Rarely │ Often │
│ Best for │ API compatibility │ Behavior & perf │
└─────────────────────┴─────────────────────┴─────────────────┘
References
See references/pact-patterns.md for advanced Pact patterns (webhooks, multi-provider verification, version compatibility strategies).