agentsclimarketplace

Api contract testing

Skill almasumdev/awesome-mobile-testing-agent-skills/.github/skills/integration/api-contract-testing

Agent skills for unit, widget, UI, and end-to-end testing of mobile apps across platforms.

Install
npx -y skills add almasumdev/awesome-mobile-testing-agent-skills --skill api-contract-testing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Expert guidance on consumer-driven contract tests for mobile apps using Pact. Use when mobile clients depend on backend APIs that evolve independently and staging smoke tests are slow or flaky.

SKILL.md

5.8 KB, as published. Nobody here has run it

API Contract Testing for Mobile Clients

Instructions

Mobile apps ship asynchronously from their backend. A response-shape change the server team considers "non-breaking" can crash 4 % of installed apps a week later. Consumer-driven contract testing replaces fragile "run the app against staging" checks with fast, deterministic contracts that both sides verify in CI.

1. The Model

  • The consumer (mobile app) declares what it needs from each endpoint: request shape, expected response shape, status codes.
  • Those expectations are serialized as a pact file (JSON) and published to a broker.
  • The provider (backend) replays each interaction against its real service in its own CI and fails if it cannot satisfy the contract.

Pact is the de-facto tool. This skill focuses on the consumer side (mobile).

2. Kotlin (Android / KMP) — Pact-JVM Consumer

@ExtendWith(PactConsumerTestExt::class)
@PactTestFor(providerName = "orders-api", pactVersion = PactSpecVersion.V4)
class OrdersApiPactTest {

    @Pact(consumer = "android-app")
    fun getOrderPact(builder: PactDslWithProvider): RequestResponsePact =
        builder
            .given("order 42 exists")
            .uponReceiving("get order 42")
                .path("/orders/42")
                .method("GET")
            .willRespondWith()
                .status(200)
                .headers(mapOf("Content-Type" to "application/json"))
                .body(newJsonBody { o ->
                    o.numberType("id", 42)
                    o.stringType("status", "PAID")
                    o.numberType("totalCents", 1999)
                }.build())
            .toPact()

    @Test
    fun `client parses order`(mockServer: MockServer) = runTest {
        val client = OrdersClient(baseUrl = mockServer.getUrl())
        val order  = client.getOrder(42)
        assertEquals(Order(id = 42, status = PAID, total = Money.cents(1999)), order)
    }
}

Publish the resulting pact file to a Pact Broker (pact_broker, Pactflow) from CI.

3. Swift (iOS) — PactSwift

final class OrdersApiPactTests: XCTestCase {
    var mockService: MockService!

    override func setUp() {
        mockService = MockService(consumer: "ios-app", provider: "orders-api")
    }

    func test_getOrder_parsesBody() throws {
        mockService
          .uponReceiving("a request for order 42")
          .given("order 42 exists")
          .withRequest(method: .GET, path: "/orders/42")
          .willRespondWith(status: 200, body: [
            "id": Matcher.SomethingLike(42),
            "status": Matcher.SomethingLike("PAID"),
            "totalCents": Matcher.SomethingLike(1999),
          ])

        mockService.run { baseURL, done in
            Task {
                let client = OrdersClient(baseURL: baseURL)
                let order  = try await client.getOrder(id: 42)
                XCTAssertEqual(order, .init(id: 42, status: .paid, totalCents: 1999))
                done()
            }
        }
    }
}

4. Dart (Flutter) — pact_dart

void main() {
  final pact = PactMockService('flutter-app', 'orders-api');

  setUpAll(pact.setup);
  tearDownAll(pact.tearDown);

  test('client parses order', () async {
    pact
      .newInteraction()
      .given('order 42 exists')
      .uponReceiving('get order 42')
      .withRequest(method: 'GET', path: '/orders/42')
      .willRespondWith(status: 200, body: {
        'id': 42, 'status': 'PAID', 'totalCents': 1999,
      });

    final client = OrdersClient(baseUrl: pact.mockServerUrl);
    expect(await client.getOrder(42),
           Order(id: 42, status: OrderStatus.paid, totalCents: 1999));
  });
}

5. TypeScript (React Native) — @pact-foundation/pact

import { PactV3, MatchersV3 } from '@pact-foundation/pact';
const { like } = MatchersV3;

const provider = new PactV3({ consumer: 'rn-app', provider: 'orders-api' });

test('client parses order', async () => {
  provider
    .given('order 42 exists')
    .uponReceiving('get order 42')
    .withRequest({ method: 'GET', path: '/orders/42' })
    .willRespondWith({
      status: 200,
      body: { id: like(42), status: like('PAID'), totalCents: like(1999) },
    });

  await provider.executeTest(async (mock) => {
    const client = new OrdersClient(mock.url);
    expect(await client.getOrder(42)).toEqual({ id: 42, status: 'PAID', totalCents: 1999 });
  });
});

6. Matchers

Match on types and presence, not exact values, or the contract becomes a wire-format diff. Use like(...), eachLike(...), iso8601Date(), uuid(). Reserve exact matches for enums and stable identifiers.

7. Publishing & Versioning

  • Publish pact files tagged with the consumer's git SHA and branch.
  • The provider's CI uses can-i-deploy to refuse deploying if it breaks a pact a deployed consumer still needs.
  • Match pact branches to app release branches so hotfix branches verify against matching provider versions.

8. What Contracts Do NOT Cover

  • End-to-end flows across multiple services (use a thin E2E suite).
  • Performance, auth, or rate limits (separate tooling).
  • UI correctness (snapshot / UI tests).

9. Checklist

  • Every screen-level API call used by the mobile client has at least one consumer pact.
  • Matchers describe types and structure, not hard-coded values, except for enums and IDs.
  • Pact files are published to a broker from CI with version tags.
  • Provider CI runs pact-verify and can-i-deploy on every merge.
  • Contract tests replace — not duplicate — broad staging integration smoke tests.
  • Legacy endpoints that have been retired are removed from the consumer pact.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.