Contract Testing

SkillDev tools

Consumer-driven contract testing for microservices using Pact, schema validation, API versioning, and backward compatibility testing. Use when testing API contracts or coordinating distributed teams.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Contract Testing skill

What this skill tells your AI

The instructions your AI receives, as published by proffesor-for-testing/agentic-qe in .claude/skills/contract-testing/SKILL.md and read by ahel’s review.

<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>

Quick Reference Card

When to Use

  • Microservices communication
  • Third-party API integrations
  • Distributed team coordination
  • Preventing breaking changes

Consumer-Driven Contract Flow

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

Tools

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

Consumer Contract (Pact)

// 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

// 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

// 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

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

Memory Namespace

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

Fleet Coordination

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'
});

Agent CLI & Advanced Patterns

For v3 agent-specific commands (aqe contract ...), GraphQL contracts, event contracts, and Pact Broker integration, see references/agent-commands.md.

Related Skills


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.

Gotchas

  • Pact broker URL must be configured before running — agent will generate tests that silently skip verification without it
  • Consumer tests pass locally but fail in CI when provider states aren't set up — always verify both sides
  • Adding a required field to a response is a BREAKING change even though provider tests pass — consumer didn't expect it
  • Agent may generate contracts from API docs instead of actual consumer usage — contracts must reflect real consumer needs
  • GraphQL contract testing requires schema stitching awareness — fragments may reference types from other services

Signals

GitHub stars
475
Forks
91
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
contract-testing-proffesor-for-testing
Source
github.com/proffesor-for-testing/agentic-qe