# Contract Test

> When two components/services talk (API client+server, producer+consumer, module boundary), pin the contract they share and test BOTH sides against it, instead of only unit-testing each in isolation. Use on integration boundaries, API changes, microservices, public interfaces. Trigger with /contract-test or "contract test", "will this break the consumer", "test the API boundary".

- Skill: `zavelinski/contract-test` (Agent Skill)
- Install (CLI): `npx skillmds@latest add zavelinski/contract-test`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zavelinski/contract-test/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: zavelinski (https://skillmd.com/u/zavelinski)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/zavelinski/contract-test

---


# contract-test

Unit tests pass on both sides and integration still breaks, because nothing tested the SHARED contract. This pins the interface two parties rely on and tests both against it.

## Why this exists (evidence)

- Consumer-driven contract testing (the Pact pattern) is the established fix for integration breakage in distributed/microservice systems: catch a breaking interface change at the boundary, before deploy, without a full end-to-end environment.
- The failure it targets: provider changes a field/type/status code; provider's own unit tests stay green; the consumer breaks in production. A contract test fails the moment the provider violates what the consumer expects.

## When to use

- Any client+server / producer+consumer / module boundary, especially across repos or teams (compose with multi-repo-context).
- Before changing a public API, schema, event shape, or shared type.
- NOT for purely internal logic with no cross-boundary consumer (unit tests / testsmith cover that).

## The method

1. **Name the contract:** the exact shape both sides depend on, request + response fields and types, status/error codes, event schema, required vs optional, ordering/idempotency assumptions.
2. **Consumer expectations:** write what the consumer actually needs (not the provider's full surface). This is the contract.
3. **Test the provider against it:** assert the provider produces responses that satisfy the contract (every required field, correct types, documented error codes).
4. **Test the consumer against it:** assert the consumer works against a stub/mock that returns exactly the contract (no reliance on undocumented behavior).
5. **Run on both, on change:** a provider change that breaks the contract fails here; a consumer that needs more must update the contract first.

## How to run it

- If a contract tool exists (Pact, schema/OpenAPI validation, JSON Schema), use it: validate responses against the schema both sides agree on.
- Lightweight: encode the contract as a shared fixture/schema; provider test asserts output matches it, consumer test runs against it as a stub.
- Compose with structured-output (the contract IS a schema) and testsmith (mutation-test the boundary handling).

## Composes with

- `structured-output`: the contract expressed as an enforceable schema.
- `multi-repo-context`: contracts are where cross-repo boundaries live; the manifest names them.
- `testsmith`: unit/mutation within a side; contract-test across the boundary.

## Honest limits

- A contract test verifies conformance to the AGREED contract, not that the contract is the right design. Wrong contract, wrong test.
- It does not replace some end-to-end checks (timing, auth, infra); it removes the large class of shape/type/status breakages.

