contract-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Contract Testing

契约测试

<default_to_action> When testing API contracts or microservices:
  1. DEFINE consumer expectations (what consumers actually need)
  2. VERIFY provider fulfills contracts (Pact verification)
  3. DETECT breaking changes before deployment (CI/CD integration)
  4. VERSION APIs semantically (breaking = major bump)
  5. MAINTAIN backward compatibility for supported versions
Quick Contract Testing Steps:
  • Consumer: Define expected request/response pairs
  • Provider: Verify against all consumer contracts
  • CI/CD: Block deploys that break contracts
  • Versioning: Document supported versions and deprecation
Critical Success Factors:
  • Consumers own the contract (they define what they need)
  • Provider must pass all consumer contracts before deploy
  • Breaking changes require coordination, not surprise </default_to_action>
<default_to_action> 在测试API契约或微服务时:
  1. 定义消费者期望(即消费者实际的需求)
  2. 验证提供者是否满足契约(Pact验证)
  3. 在部署前检测破坏性变更(CI/CD集成)
  4. 对API进行语义化版本控制(破坏性变更=主版本号升级)
  5. 为受支持的版本维护向后兼容性
快速契约测试步骤:
  • 消费者:定义预期的请求/响应对
  • 提供者:针对所有消费者契约进行验证
  • CI/CD:阻止会破坏契约的部署
  • 版本控制:记录受支持的版本和弃用信息
关键成功因素:
  • 消费者主导契约(由他们定义自身需求)
  • 提供者在部署前必须通过所有消费者契约验证
  • 破坏性变更需要提前协调,而非突然实施 </default_to_action>

Quick Reference Card

快速参考卡片

When to Use

适用场景

  • Microservices communication
  • Third-party API integrations
  • Distributed team coordination
  • Preventing breaking changes
  • 微服务通信
  • 第三方API集成
  • 分布式团队协调
  • 预防破坏性变更

Consumer-Driven Contract Flow

消费者驱动契约流程

Consumer → Defines Expectations → Contract
Provider → Verifies Contract → Pass/Fail
CI/CD → Blocks Breaking Changes
Consumer → Defines Expectations → Contract
Provider → Verifies Contract → Pass/Fail
CI/CD → Blocks Breaking Changes

Breaking vs Non-Breaking Changes

破坏性与非破坏性变更对比

Change TypeBreaking?Semver
Remove field✅ YesMajor
Rename field✅ YesMajor
Change type✅ YesMajor
Add optional field❌ NoMinor
Add new endpoint❌ NoMinor
Bug fix❌ NoPatch
变更类型是否具有破坏性?语义化版本(Semver)
删除字段✅ 是主版本
重名字段✅ 是主版本
变更类型✅ 是主版本
添加可选字段❌ 否次版本
添加新端点❌ 否次版本
Bug修复❌ 否修订版本

Tools

工具推荐

ToolBest For
PactConsumer-driven contracts
OpenAPI/SwaggerAPI-first design
JSON SchemaSchema validation
GraphQLSchema-first contracts

工具最佳适用场景
Pact消费者驱动契约
OpenAPI/SwaggerAPI优先设计
JSON Schema模式验证
GraphQL模式优先契约

Consumer Contract (Pact)

消费者契约(Pact)

javascript
// Consumer defines what it needs
const { Pact } = require('@pact-foundation/pact');

describe('Order API Consumer', () => {
  const provider = new Pact({
    consumer: 'CheckoutUI',
    provider: 'OrderService'
  });

  beforeAll(() => provider.setup());
  afterAll(() => provider.finalize());

  it('creates an order', async () => {
    await provider.addInteraction({
      state: 'products exist',
      uponReceiving: 'a create order request',
      withRequest: {
        method: 'POST',
        path: '/orders',
        body: { productId: 'abc', quantity: 2 }
      },
      willRespondWith: {
        status: 201,
        body: {
          orderId: like('order-123'),  // Any string matching pattern
          total: like(19.99)           // Any number
        }
      }
    });

    const response = await orderClient.create({ productId: 'abc', quantity: 2 });
    expect(response.orderId).toBeDefined();
  });
});

javascript
// Consumer defines what it needs
const { Pact } = require('@pact-foundation/pact');

describe('Order API Consumer', () => {
  const provider = new Pact({
    consumer: 'CheckoutUI',
    provider: 'OrderService'
  });

  beforeAll(() => provider.setup());
  afterAll(() => provider.finalize());

  it('creates an order', async () => {
    await provider.addInteraction({
      state: 'products exist',
      uponReceiving: 'a create order request',
      withRequest: {
        method: 'POST',
        path: '/orders',
        body: { productId: 'abc', quantity: 2 }
      },
      willRespondWith: {
        status: 201,
        body: {
          orderId: like('order-123'),  // Any string matching pattern
          total: like(19.99)           // Any number
        }
      }
    });

    const response = await orderClient.create({ productId: 'abc', quantity: 2 });
    expect(response.orderId).toBeDefined();
  });
});

Provider Verification

提供者验证

javascript
// Provider verifies it fulfills all consumer contracts
const { Verifier } = require('@pact-foundation/pact');

describe('Order Service Provider', () => {
  it('fulfills all consumer contracts', async () => {
    await new Verifier({
      provider: 'OrderService',
      providerBaseUrl: 'http://localhost:3000',
      pactUrls: ['./pacts/checkoutui-orderservice.json'],
      stateHandlers: {
        'products exist': async () => {
          await db.products.create({ id: 'abc', price: 9.99 });
        }
      }
    }).verifyProvider();
  });
});

javascript
// Provider verifies it fulfills all consumer contracts
const { Verifier } = require('@pact-foundation/pact');

describe('Order Service Provider', () => {
  it('fulfills all consumer contracts', async () => {
    await new Verifier({
      provider: 'OrderService',
      providerBaseUrl: 'http://localhost:3000',
      pactUrls: ['./pacts/checkoutui-orderservice.json'],
      stateHandlers: {
        'products exist': async () => {
          await db.products.create({ id: 'abc', price: 9.99 });
        }
      }
    }).verifyProvider();
  });
});

Breaking Change Detection

破坏性变更检测

typescript
// Agent detects breaking changes
await Task("Contract Validation", {
  currentContract: 'openapi-v2.yaml',
  previousContract: 'openapi-v1.yaml',
  detectBreaking: true,
  calculateSemver: true,
  generateMigrationGuide: true
}, "qe-api-contract-validator");

// Output:
// Breaking changes found: 2
// - Removed field: order.discount
// - Type change: order.total (number → string)
// Recommended version: 3.0.0 (major bump)

typescript
// Agent detects breaking changes
await Task("Contract Validation", {
  currentContract: 'openapi-v2.yaml',
  previousContract: 'openapi-v1.yaml',
  detectBreaking: true,
  calculateSemver: true,
  generateMigrationGuide: true
}, "qe-api-contract-validator");

// Output:
// Breaking changes found: 2
// - Removed field: order.discount
// - Type change: order.total (number → string)
// Recommended version: 3.0.0 (major bump)

CI/CD Integration

CI/CD集成

yaml
name: Contract Tests
on: [push]

jobs:
  consumer-tests:
    steps:
      - run: npm run test:contract
      - name: Publish Pacts
        run: npx pact-broker publish ./pacts --broker-base-url $PACT_BROKER

  provider-verification:
    needs: consumer-tests
    steps:
      - name: Verify Provider
        run: npm run verify:contracts
      - name: Can I Deploy?
        run: npx pact-broker can-i-deploy --pacticipant OrderService --version $VERSION

yaml
name: Contract Tests
on: [push]

jobs:
  consumer-tests:
    steps:
      - run: npm run test:contract
      - name: Publish Pacts
        run: npx pact-broker publish ./pacts --broker-base-url $PACT_BROKER

  provider-verification:
    needs: consumer-tests
    steps:
      - name: Verify Provider
        run: npm run verify:contracts
      - name: Can I Deploy?
        run: npx pact-broker can-i-deploy --pacticipant OrderService --version $VERSION

Agent Coordination Hints

Agent协调提示

Memory Namespace

内存命名空间

aqe/contract-testing/
├── contracts/*           - Current contracts
├── breaking-changes/*    - Detected breaking changes
├── versioning/*          - Version compatibility matrix
└── verification-results/* - Provider verification history
aqe/contract-testing/
├── contracts/*           - Current contracts
├── breaking-changes/*    - Detected breaking changes
├── versioning/*          - Version compatibility matrix
└── verification-results/* - Provider verification history

Fleet Coordination

集群协调

typescript
const contractFleet = await FleetManager.coordinate({
  strategy: 'contract-testing',
  agents: [
    'qe-api-contract-validator',  // Validation, breaking detection
    'qe-test-generator',          // Generate contract tests
    'qe-security-scanner'         // API security
  ],
  topology: 'sequential'
});

typescript
const contractFleet = await FleetManager.coordinate({
  strategy: 'contract-testing',
  agents: [
    'qe-api-contract-validator',  // Validation, breaking detection
    'qe-test-generator',          // Generate contract tests
    'qe-security-scanner'         // API security
  ],
  topology: 'sequential'
});

Related Skills

相关技能

  • api-testing-patterns - API testing strategies
  • shift-left-testing - Early contract validation
  • cicd-pipeline-qe-orchestrator - Pipeline integration

  • api-testing-patterns - API测试策略
  • shift-left-testing - 早期契约验证
  • cicd-pipeline-qe-orchestrator - 流水线集成

Remember

注意事项

Consumers own the contract. They define what they need; providers must fulfill it. Breaking changes require major version bumps and coordination. CI/CD blocks deploys that break contracts. Use Pact for consumer-driven, OpenAPI for API-first.
With Agents: Agents validate contracts, detect breaking changes with semver recommendations, and generate migration guides. Use agents to maintain contract compliance at scale.
消费者主导契约。由消费者定义自身需求,提供者必须满足这些需求。破坏性变更需要升级主版本号并提前协调。CI/CD会阻止破坏契约的部署。消费者驱动场景使用Pact,API优先场景使用OpenAPI。
借助Agent: Agent可验证契约、检测破坏性变更并提供语义化版本(Semver)建议,还能生成迁移指南。使用Agent可大规模维护契约合规性。