用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill contract-testing命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
正在显示 SKILL.md
基于 SOC 职业分类
| name | contract-testing |
| description | Consumer-driven contract testing with Pact, schema validation, and API compatibility verification. |
| layer | domain |
| category | testing |
| triggers | ["contract test","pact","consumer driven","api contract","schema validation"] |
| inputs | ["API contract testing requirements","Consumer-driven testing setup","Schema validation strategies","API compatibility verification"] |
| outputs | ["Pact consumer and provider tests","Schema validation configurations","Contract verification workflows","CI/CD integration for contract tests"] |
| linksTo | ["api-testing","testing-patterns","openapi","microservices"] |
| linkedFrom | [] |
| preferredNextSkills | ["api-testing","testing-patterns","microservices"] |
| fallbackSkills | ["openapi"] |
| riskLevel | low |
| memoryReadPolicy | selective |
| memoryWritePolicy | none |
| sideEffects | [] |
Provide expert guidance on consumer-driven contract testing (CDCT) with Pact, schema validation with Zod/JSON Schema, API compatibility verification, and CI integration. Ensures APIs evolve without breaking consumers in microservice architectures.
┌────────────────────────────────────────────────┐
│ Testing Pyramid for APIs │
│ │
│ ┌──────────┐ │
│ │ E2E │ Slow, brittle │
│ ┌─┴──────────┴─┐ │
│ │ Integration │ Needs live deps │
│ ┌─┴──────────────┴─┐ │
│ │ Contract Tests │ Fast, isolated │ ← This skill
│ ┌─┴──────────────────┴─┐ │
│ │ Unit Tests │ │
│ └───────────────────────┘ │
└────────────────────────────────────────────────┘
Contract tests verify that a provider API meets the expectations of its consumers without requiring both services to be running simultaneously.
The consumer defines what it expects from the provider:
// consumer/tests/user-service.pact.test.ts
import { PactV4, MatchersV3 } from '@pact-foundation/pact';
import { UserApiClient } from '../src/user-api-client';
const { like, eachLike, string, integer, datetime } = MatchersV3;
const provider = new PactV4({
consumer: 'OrderService',
provider: 'UserService',
dir: './pacts', // output directory for contract files
});
describe('User Service API', () => {
(, {
(, () => {
provider
.()
.()
.()
.(, , {
builder.({ : });
})
.(, {
builder
.({ : })
.({
: (),
: (),
: (),
: (, ),
: ({
: (),
: (),
}),
});
})
.( (mockServer) => {
client = (mockServer.);
user = client.();
(user.).();
(user.).();
(user.).();
});
});
(, () => {
provider
.()
.()
.()
.(, )
.(, {
builder.({
: (),
: (),
});
})
.( (mockServer) => {
client = (mockServer.);
(client.())..();
});
});
});
(, {
(, () => {
provider
.()
.()
.(, , {
builder
.({ : })
.({
: ,
: ,
});
})
.(, {
builder.({
: (),
: (),
: (),
});
})
.( (mockServer) => {
client = (mockServer.);
user = client.({
: ,
: ,
});
(user.).();
});
});
});
});
The provider verifies it meets consumer expectations:
// provider/tests/pact-verification.test.ts
import { Verifier } from '@pact-foundation/pact';
import { app } from '../src/app';
describe('Pact Provider Verification', () => {
let server: any;
beforeAll(async () => {
// Start the real provider service
server = app.listen(0);
});
afterAll(() => server.close());
it('validates the expectations of OrderService', async () => {
const port = server.address().port;
await new Verifier({
providerBaseUrl: `http://localhost:${port}`,
provider: 'UserService',
// Load pact files (local or from broker)
pactUrls: ['../consumer/pacts/OrderService-UserService.json'],
// OR from Pact Broker:
// pactBrokerUrl: process.env.PACT_BROKER_URL,
// pactBrokerToken: process.env.PACT_BROKER_TOKEN,
// publishVerificationResult: true,
// providerVersion: process.env.GIT_SHA,
// Setup provider states
stateHandlers: {
'user 123 exists': async () => {
await seedDatabase({
id: 123,
email: 'user@example.com',
name: 'Jane Doe',
});
},
'user 999 does not exist': async () => {
await clearDatabase();
},
},
}).verifyProvider();
});
});
For simpler contract validation without Pact:
// shared/contracts/user-contract.ts
import { z } from 'zod';
// Shared schema — defines the contract
export const UserResponseSchema = z.object({
id: z.number().int().positive(),
email: z.string().email(),
name: z.string().min(1),
createdAt: z.string().datetime(),
orders: z.array(
z.object({
id: z.string(),
total: z.number().nonnegative(),
}),
).optional(),
});
export type UserResponse = z.infer<typeof UserResponseSchema>;
// Consumer test — validate against schema
describe('User API Client', () => {
it('response matches contract schema', async () => {
const response = await fetch('/users/123');
const data = await response.json();
// This throws if the response doesn't match
const user = UserResponseSchema.parse(data);
expect(user.id).toBe(123);
});
});
// Provider test — validate output against schema
describe('GET /users/:id', () => {
it('response conforms to contract', async () => {
const response = await request(app).get('/users/123');
expect(() => UserResponseSchema.parse(response.body)).not.toThrow();
});
});
// tests/openapi-contract.test.ts
import { createDocument } from 'openapi-backend';
import SwaggerParser from '@apidevtools/swagger-parser';
describe('API Contract Compliance', () => {
let api: any;
beforeAll(async () => {
api = await SwaggerParser.validate('./openapi.yaml');
});
it('GET /users/:id response matches OpenAPI spec', async () => {
const response = await request(app).get('/users/123');
// Validate response against the OpenAPI schema
const schema = api.paths['/users/{id}'].get.responses['200'].content['application/json'].schema;
const ajv = new Ajv();
const validate = ajv.compile(schema);
const valid = validate(response.body);
expect(valid).toBe(true);
if (!valid) console.error(validate.errors);
});
});
Publish contracts from consumer CI:
# consumer/.github/workflows/contract.yml
name: Consumer Contract Tests
on: [push]
jobs:
contract:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm ci
- run: npm run test:pact
- name: Publish Pact to Broker
run: |
npx pact-broker publish ./pacts \
--consumer-app-version=${{ github.sha }} \
--branch=${{ github.ref_name }} \
--broker-base-url=${{ secrets.PACT_BROKER_URL }} \
--broker-token=${{ secrets.PACT_BROKER_TOKEN }}
Verify contracts in provider CI:
# provider/.github/workflows/contract.yml
name: Provider Contract Verification
on:
push:
# Webhook from Pact Broker when new contracts are published
repository_dispatch:
types: [pact-changed]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm ci
- run: npm run test:pact:verify
env:
PACT_BROKER_URL: ${{ secrets.PACT_BROKER_URL }}
PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
GIT_SHA: ${{ github.sha }}
Can-I-Deploy check before deploying:
- name: Can I Deploy?
run: |
npx pact-broker can-i-deploy \
--pacticipant=UserService \
--version=${{ github.sha }} \
--to-environment=production \
--broker-base-url=${{ secrets.PACT_BROKER_URL }} \
--broker-token=${{ secrets.PACT_BROKER_TOKEN }}
Safe changes (non-breaking):
Breaking changes (require consumer updates):
like, eachLike, integer) validate shape, not data.stateHandlers to seed specific scenarios.can-i-deploy before releases — Verify compatibility before deploying to production.| Pitfall | Problem | Fix |
|---|---|---|
| Testing exact response values | Brittle tests that break on data changes | Use Pact matchers for shape, not exact values |
| Consumer tests too much | Contract covers fields consumer does not use | Only include fields the consumer actually consumes |
| No provider states | Provider verification fails due to missing test data | Implement stateHandlers for each given() clause |
| Skipping error contracts | Only happy path tested, 4xx/5xx breaks consumer | Add contract tests for error responses |
| Manual contract sharing | Pact JSON files emailed or committed | Use Pact Broker for automated contract exchange |
| Treating contracts as E2E tests | Slow, flaky, overloaded | Contracts verify schema and shape only; E2E tests verify behavior |