Automatyzacja testów API
Automatyzacja testów API z agentami AI polega na generowaniu testów endpointów z kontraktu API i kryteriów akceptacji, a nie z kodu handlerów, i na udowodnieniu, że zestaw potrafi wykryć błąd. Podstawą jest zestaw testów statusów i schematów dla każdej operacji, macierz autoryzacji rola × zasób, a przy wielu niezależnie wdrażanych konsumentach także kontrakty Pact sprawdzane przez can-i-deploy.
Ta strona jest dla programistów, którzy proszą agenta o „testy do wszystkich endpointów”, i dla tech leadów, którzy muszą zdecydować, czy takie testy mogą blokować merge. Typowa porażka: agent czyta src/routes/orders.ts, pisze 60 zielonych testów, a każdy z nich potwierdza to, co handler już robi, łącznie z brakującym sprawdzeniem właściciela, przez które użytkownik A widzi zamówienia użytkownika B.
Co wyniesiesz z automatyzacji testów API
Dział zatytułowany „Co wyniesiesz z automatyzacji testów API”- Prompt, który zamienia
openapi.yamli kryteria akceptacji w tabelę planu testów do przejrzenia, zanim powstanie jakikolwiek kod testu. - Prompt generujący testy jednej operacji: sukces, walidacja, reguły biznesowe, uwierzytelnianie i przypadki brzegowe.
- Wzorzec macierzy autoryzacji dla sprawdzeń autoryzacji na poziomie obiektu, które mogą pominąć zarówno handler, jak i test napisany na podstawie tego handlera.
- Konfigurację Pact z bramką
can-i-deployi serwer MCP, przez który agent odpytuje brokera. - Cztery kontrole, które mówią, czy wygenerowany zestaw łapie błędy, bez czytania go linijka po linijce.
Które testy API należą do tej strony, a które bramki są gdzie indziej?
Dział zatytułowany „Które testy API należą do tej strony, a które bramki są gdzie indziej?”Testy API częściowo pokrywają się z trzema sąsiednimi obszarami. Każdą kwestię trzymaj w jednym miejscu, żeby agent nie pisał tej samej kontroli trzy razy.
| Warstwa | Na jakie pytanie odpowiada | Gdzie jest opisana |
|---|---|---|
| Bramki kontraktu | Czy kontrakt jest poprawny i wstecznie zgodny, i czy serwer zgadza się z nim pod fuzzingiem? | Spectral, oasdiff, Schemathesis na stronie tworzenie API |
| Zachowanie endpointów | Czy każda operacja egzekwuje reguły ze specyfikacji: statusy, walidację, reguły biznesowe, kto może co zrobić? | Ta strona |
| Kontrakty konsumentów | Czy ta wersja dostawcy zepsuje konsumenta, który już działa na produkcji? | Ta strona (Pact) |
| Cały stos usługi | Czy baza, kolejka i wywołania zewnętrzne działają razem? | Testy integracyjne |
| Powierzchnia ataku | Injection, SSRF, sekrety, CVE w zależnościach | Testy bezpieczeństwa |
Bramki kontraktu dowodzą, że kod zgadza się z kontraktem. Nie dowodzą, że kontrakt zgadza się z produktem: schemat mówi, że total jest liczbą, a nie że zawiera podatek. Do tego służą testy endpointów pisane z kryteriów akceptacji.
Generuj testy API z kontraktu, a nie z handlerów
Dział zatytułowany „Generuj testy API z kontraktu, a nie z handlerów”Agent, który czyta handler przed napisaniem testu, przenosi założenia handlera do asercji. Daj mu kontrakt i kryteria akceptacji jako wyrocznię, a handler niech czyta tylko po to, żeby wiedzieć, jak go wywołać. Jak pisać kryteria, których agent nie odczyta źle, opisuje strona o kryteriach akceptacji.
-
Poproś o plan testów, nie o testy. Agent tworzy tabelę: operacja, scenariusz, oczekiwany status, reguła dla body, odwołanie do specyfikacji. To jedyny artefakt, który człowiek czyta w całości, i zajmuje to minuty, a nie godzinę przeglądania kodu testów.
-
Porównaj plan z produktem. Dopisz reguły, o których zapomniała specyfikacja (idempotencja, własność zasobu, limity), i usuń scenariusze testujące framework zamiast twojego kodu. Zatwierdzony plan zacommituj obok testów, na przykład jako
tests/api/plans/orders.md. -
Wygeneruj testy z zatwierdzonego planu, jedna operacja lub jeden zasób na sesję. Mniejsze porcje trzymają kontekst agenta przy jednym kontrakcie i ułatwiają przypisanie porażek.
-
Każdy test musi choć raz nie przejść. Agent psuje zachowanie, które test pokrywa (usuwa walidację, zmienia kod statusu), uruchamia zestaw, pokazuje czerwony test i cofa zmianę. Test, który zostaje zielony przy zepsutym handlerze, usuwasz albo piszesz od nowa.
-
Zablokuj zestaw przed kolejną sesją implementacji. Ścieżki testów są tylko do odczytu dla agenta implementującego, a CI uruchamia zestaw spoza diffu. Jak to zrobić w każdym narzędziu, opisuje strona o ochronie wyroczni.
Najcenniejszym wynikiem jest lista „Open questions”. Każda pozycja to decyzja produktowa, którą agent w przeciwnym razie podjąłby po cichu, i to w handlerze, a nie w specyfikacji.
Wygeneruj testy dla jednej operacji
Dział zatytułowany „Wygeneruj testy dla jednej operacji”Gdy plan jest zatwierdzony, prompt generujący jest taki sam w każdym narzędziu. Różni się sposób, w jaki powstrzymujesz agenta przed poprawianiem handlera tak, żeby przeszły jego własne testy.
Następnie udowodnij, że każdy test potrafi nie przejść. Ten krok celowo psuje handler, więc uruchom go w sesji bez ograniczenia na src/ albo na gałęzi do wyrzucenia, nigdy w sesji generowania.
Krok planu uruchom z dozwolonym odczytem i zablokowanym zapisem źródeł, tym samym poleceniem z --disallowedTools, które pokazujemy niżej: sesja może czytać kontrakt i zapisać tests/api/plans/orders.md, a prompt trzyma ją z dala od src/. Możesz też użyć claude --permission-mode plan i zapisać plan samodzielnie, gdy Claude go przedstawi, bo tryb planu blokuje zapis plików. Sesję generowania uruchom z katalogu głównego repozytorium z zablokowaną edycją źródeł, żeby narzędzia edycji nie mogły zmienić src/:
claude --disallowedTools "Edit(src/**)" "Write(src/**)"Reguły odmowy obejmują tylko narzędzia Edit i Write (sprawdzone w 2.1.283). Polecenie Bash, takie jak sed -i albo przekierowanie w powłoce, nadal może zapisać coś w src/, a tryb auto może je zatwierdzić. Dlatego zakończ sesję poleceniem git diff --stat -- src/: jeśli coś wypisze, odrzuć przebieg.
Prompt sprawdzający, czy testy potrafią nie przejść, musi zepsuć handler, więc uruchom go w drugiej sesji bez tego ograniczenia albo na gałęzi do wyrzucenia. Konfigurację pracy z API opisuje strona budowanie API z Claude Code.
Polecenia testów i zasadę „nie modyfikuj src/ podczas pisania testów” zapisz w AGENTS.md, który Codex czyta przed każdym zadaniem. Generowanie uruchom nieinteraktywnie z czystej gałęzi przez codex exec --sandbox workspace-write "<prompt>" i najpierw przejrzyj diff poleceniem git diff --stat: każdy plik spoza tests/ to powód, żeby odrzucić przebieg. Wariant contract-first dla Codeksa opisuje strona API contract-first w Codeksie.
Plan testów przygotuj w Plan Mode, a potem przełącz się na agenta do generowania, z tests/api/plans/orders.md i api/openapi.yaml dołączonymi jako kontekst. Dodaj regułę projektu, że zadania pisania testów nie edytują src/, i przed akceptacją sprawdź listę zmienionych plików. Na pull requeście Bugbot szuka błędów, ale nie zastępuje kroku 4: recenzent nie zobaczy testu, który nigdy nie kończy się porażką.
Jak testować autoryzację API, żeby agent nie pominął kontroli na poziomie obiektu?
Dział zatytułowany „Jak testować autoryzację API, żeby agent nie pominął kontroli na poziomie obiektu?”Błędna autoryzacja na poziomie obiektu (BOLA) to błąd API, który mogą pominąć zarówno handler, jak i test napisany na podstawie tego handlera. Handler sprawdza, czy wywołujący jest zalogowany, test sprawdza, czy zalogowany dostaje 200, a nikt nie sprawdza, czy zamówienie należy do wywołującego. Jeden test 403 na endpoint tego nie złapie. Macierz złapie.
Zdefiniuj macierz raz, jako dane: role, zasoby, których właścicielem jest każda rola, i oczekiwany wynik każdej kombinacji. Test przechodzi po wszystkich operacjach z kontraktu, więc nowa operacja bez wpisu w macierzy powoduje porażkę zestawu, zamiast przejść niezauważona.
// tests/api/authz-matrix.test.ts (sam kształt; wiersze uzupełnia agent)const matrix = [ { op: 'GET /orders/{id}', actor: 'owner', expect: 200 }, { op: 'GET /orders/{id}', actor: 'other-user', expect: 404 }, { op: 'GET /orders/{id}', actor: 'support', expect: 200 }, { op: 'DELETE /orders/{id}', actor: 'support', expect: 403 }, { op: 'DELETE /orders/{id}', actor: 'anonymous', expect: 401 },] as const;// Test towarzyszący wczytuje api/openapi.yaml i kończy się porażką, gdy któraś// operacja nie ma wiersza dla każdego aktora.Blok TODO trafia do właściciela produktu, a nie z powrotem do agenta. To, czy support może anulować zamówienie, jest decyzją, a macierz ją uwidacznia.
Kiedy użyć testów kontraktowych Pact zamiast diffu schematu?
Dział zatytułowany „Kiedy użyć testów kontraktowych Pact zamiast diffu schematu?”Diff zmian łamiących w oasdiff chroni konsumentów przed zmianami opublikowanego kontraktu. Nie wie jednak, które pola konsument naprawdę czyta, i nie powie ci, czy wersja dostawcy, którą zaraz wdrożysz, działa z wersjami konsumentów już obecnymi na produkcji. Na to odpowiadają kontrakty sterowane przez konsumenta.
| Sytuacja | Wystarczy | Dodać Pact? |
|---|---|---|
| Jeden zespół ma API i jego jedynego klienta, wdrażane razem | oasdiff w CI | Nie |
| Publiczne API z nieznanymi konsumentami | oasdiff, polityka wersjonowania | Nie, nie zbierzesz ich paktów |
| Kilku wewnętrznych konsumentów (web, mobile, inne usługi) wdrażanych we własnym rytmie | oasdiff | Tak |
| Aplikacje mobilne, których stare wersje zostają zainstalowane miesiącami | oasdiff | Tak, ze starymi wersjami aplikacji zapisanymi jako wdrożone |
Przed każdym wdrożeniem CI pyta brokera, czy ta wersja jest zgodna ze wszystkim, co już działa w docelowym środowisku. Polecenie kończy się kodem różnym od zera, gdy brakuje weryfikacji albo się nie powiodła, więc samo w sobie działa jako bramka:
# CI, przed krokiem wdrożenia. PACT_BROKER_BASE_URL oraz PACT_BROKER_TOKEN (PactFlow)# albo PACT_BROKER_USERNAME/PACT_BROKER_PASSWORD (własny broker) pochodzą z magazynu sekretów CI.npx -p @pact-foundation/pact-cli pact-broker can-i-deploy \ --pacticipant order-service --version "$GIT_SHA" \ --to-environment production \ --retry-while-unknown 10 --retry-interval 30Po wdrożeniu zapisz je poleceniem pact-broker record-deployment --pacticipant order-service --version "$GIT_SHA" --environment production, żeby kolejne can-i-deploy sprawdzało to, co naprawdę działa. Wersje sprawdzone 2026-09-26: @pact-foundation/pact 17.1.4 i @pact-foundation/pact-cli 18.1.2 w npm.
Pozwól agentowi odpytywać Pact Broker przez MCP
Dział zatytułowany „Pozwól agentowi odpytywać Pact Broker przez MCP”Gdy weryfikacja się nie powiedzie, agent potrzebuje nieudanej interakcji i stanu dostawcy, a nie zrzutu ekranu z brokera. Serwer MCP od SmartBear (@smartbear/mcp, 0.41.3 w npm na 2026-09-26) udostępnia agentowi brokera, m.in. narzędziami Can I Deploy, Matrix, Get Provider States i Get Pacts for Verification. Zawiera też Generate Pact Tests i Review Pact Tests, które uzależnia od uprawnienia PactFlow AI w twoim planie. Działa z PactFlow i z samodzielnie hostowanym Pact Brokerem, ale każdy z nich uwierzytelnia inaczej: serwer wysyła PACT_BROKER_TOKEN jako token typu bearer, czego oczekuje PactFlow, a parę PACT_BROKER_USERNAME i PACT_BROKER_PASSWORD jako basic auth, czego oczekuje własny broker z włączonym uwierzytelnianiem. Poniższe konfiguracje dotyczą PactFlow, wariant dla własnego brokera jest pod nimi. Przypinają tę wersję, bo serwer działa z danymi dostępowymi brokera w swoim środowisku: podnoś ją świadomie, po przeczytaniu informacji o wydaniu, zamiast pobierać @latest.
Dodaj serwer do projektowego .mcp.json. Claude Code rozwija ${VAR} ze zmiennych środowiskowych, więc token nigdy nie trafia do pliku:
{ "mcpServers": { "smartbear": { "command": "npx", "args": ["-y", "@smartbear/mcp@0.41.3"], "env": { "PACT_BROKER_BASE_URL": "${PACT_BROKER_BASE_URL}", "PACT_BROKER_TOKEN": "${PACT_BROKER_TOKEN}" } } }}Dodaj serwer do ~/.codex/config.toml. env_vars przekazuje wskazane zmienne z twojej powłoki zamiast zapisywać ich wartości (sprawdzone przez codex mcp get w 0.157.1):
[mcp_servers.smartbear]command = "npx"args = ["-y", "@smartbear/mcp@0.41.3"]env_vars = ["PACT_BROKER_BASE_URL", "PACT_BROKER_TOKEN"]Dodaj ten sam wpis command i args w sekcji mcpServers pliku .cursor/mcp.json. Sposobu, w jaki Cursor przekazuje zmienne środowiskowe do serwera stdio, nie zweryfikowaliśmy na potrzeby tej strony (cursor.com był niedostępny 2026-09-26). Zanim wpiszesz token do pliku, sprawdź dokumentację MCP w Cursorze, i nigdy go nie commituj.
Przy samodzielnie hostowanym Pact Brokerze zastąp token dwiema zmiennymi basic auth, inaczej broker odrzuci nagłówek bearer kodem 401. W .mcp.json blok env wygląda wtedy tak:
"env": { "PACT_BROKER_BASE_URL": "${PACT_BROKER_BASE_URL}", "PACT_BROKER_USERNAME": "${PACT_BROKER_USERNAME}", "PACT_BROKER_PASSWORD": "${PACT_BROKER_PASSWORD}"}a w Codeksie env_vars = ["PACT_BROKER_BASE_URL", "PACT_BROKER_USERNAME", "PACT_BROKER_PASSWORD"]. Ustaw tylko jeden schemat: gdy obecny jest PACT_BROKER_TOKEN, serwer używa go i pomija nazwę użytkownika oraz hasło (sprawdzone w kodzie klienta @smartbear/mcp 0.41.3).
Daj agentowi dane dostępowe tylko do odczytu: token tylko do odczytu w PactFlow albo użytkownika basic auth tylko do odczytu we własnym brokerze (konfiguruje się go po stronie brokera, np. przez PACT_BROKER_BASIC_AUTH_READ_ONLY_USERNAME w obrazie pactfoundation/pact-broker). Publikowanie paktów, zapisywanie wdrożeń i zmiany uczestników należą do CI.
Co się zmienia przy testowaniu API GraphQL?
Dział zatytułowany „Co się zmienia przy testowaniu API GraphQL?”Wzorce planu i macierzy przenoszą się bez zmian; rolę openapi.yaml przejmuje schemat. Różnice są trzy. Większość serwerów odpowiada 200 nawet wtedy, gdy resolver zawiedzie, więc sprawdzaj errors[].extensions.code, a nie status; błędy na poziomie żądania (parsowanie, walidacja, limity głębokości) mogą wrócić jako 4xx, zależnie od serwera. Autoryzację egzekwuje się na poziomie pól i resolverów, więc macierz obejmuje pola, a nie trasy. Jedno zapytanie może być dowolnie kosztowne, więc limity głębokości i złożoności potrzebują własnych testów. Zmiany łamiące w schemacie wyłapuje graphql-inspector diff, opisany na stronie tworzenie API.
Skąd wiesz, że wygenerowane testy API są dobre, jeśli ich nie czytasz?
Dział zatytułowany „Skąd wiesz, że wygenerowane testy API są dobre, jeśli ich nie czytasz?”Przeczytanie 60 wygenerowanych testów nie powie ci, czy łapią błędy; powie tylko, czy wyglądają rozsądnie. Cztery kontrole dają zamiast tego dowody i wszystkie działają w CI.
| Kontrola | Czego dowodzi | Jak |
|---|---|---|
| Potwierdzona porażka | Każdy test potrafi nie przejść | Krok 4 powyżej; raport agenta dołącz do pull requesta |
| Wynik mutacyjny handlerów | Zestaw wykrywa drobne zmiany w prawdziwej logice | Po npm init stryker (instaluje plugin test runnera i zapisuje konfigurację): npx stryker run --mutate "src/routes/orders.ts" (@stryker-mutator/core 10.0.0 w npm, 2026-09-26) |
| Pokrycie operacji | Każda operacja i każdy udokumentowany status mają test | Test, który wczytuje api/openapi.yaml i kończy się porażką na każdej parze operacja–status bez testu, jak test pokrycia macierzy |
| Ścisła walidacja schematu | Odpowiedzi nie niosą nieudokumentowanych pól | Walidacja z semantyką additionalProperties: false w każdym teście |
Pokrycie linii to tu zła miara: handler może mieć 100% pokrycia testami, które nic nie mówią o własności zasobu. Wynik mutacyjny mierzy, co asercje zauważają. Jak ustawić próg i czytać raport, opisuje strona o sile wyroczni.
Podział odpowiedzialności jest prosty. Człowiek zatwierdza kontrakt, plan testów i macierz autoryzacji, bo one zapisują decyzje produktowe. Wszystko potem należy do CI: zestaw testów, próg mutacyjny, can-i-deploy i bramki kontraktu. Pull request niesie plan, raport „potwierdzonych porażek” i wynik mutacyjny jako pakiet dowodów, więc recenzent sprawdza dowody, a nie linie.
Kiedy testy API pisane przez agenta zawodzą
Dział zatytułowany „Kiedy testy API pisane przez agenta zawodzą”Testy przechodzą, a błąd, który miały złapać, jest na produkcji. Agent wziął oczekiwania z handlera. Co zrobić: wygeneruj testy ponownie z planu, z ukrytym src/ na etapie planowania, a potem przeprowadź krok „potwierdzonej porażki” dla pominiętego zachowania. Dopisz przypadek do planu, żeby kolejna sesja go zachowała.
Agent poluzował asercję, żeby było zielono. Typowe objawy to expect([200, 500]).toContain(res.status), toBeDefined() na body albo usunięty test. Co zrobić: zablokuj edycję istniejących plików testów w sesjach implementacyjnych i niech CI oznacza każdy diff, który zmniejsza liczbę asercji lub testów w tests/api/. Detektory opisuje strona o ochronie wyroczni.
Testy są niestabilne, bo dzielą stan bazy. Równoległe pliki testów widzą nawzajem swoje wiersze, a testy zależne od kolejności przechodzą lokalnie i padają w CI. Co zrobić: jedna transakcja na test z rollbackiem albo świeży schemat na workera; poproś agenta, żeby przed zgłoszeniem końca uruchomił zestaw trzy razy w losowej kolejności. Wzorce fixture’ów opisuje strona o zarządzaniu danymi testowymi.
Każda odpowiedź ma snapshot i każda zmiana psuje 40 testów. Snapshoty całego body testują kolejność pól i znaczniki czasu, a nie zachowanie. Co zrobić: zastąp snapshoty walidacją schematu i jawnymi asercjami na polach, których dotyczy scenariusz.
Weryfikacja Pact pada po zamierzonej zmianie dostawcy. To bramka, która działa. Co zrobić: wypuść zmianę jako dodatkowe pole albo nową wersję, pozwól konsumentom zaktualizować pakty i wdróż dostawcę dopiero, gdy can-i-deploy przejdzie. Nie proś agenta, żeby „naprawił weryfikację”: poprawi stan dostawcy albo matcher.
Stany dostawcy rozjeżdżają się z paktami. Konsument dodaje „order 42 is cancelled”, dostawca nie ma takiego stanu i weryfikacja pada z błędem brakującego stanu. Co zrobić: przekaż agentowi nazwę brakującego stanu przez serwer MCP brokera i poproś o dodanie tylko przygotowania tego stanu w teście dostawcy.
Testy przechodzą w CI, a API na produkcji zachowuje się inaczej. Rate limiting, cache, feature flagi albo middleware różnią się między środowiskami. Co zrobić: wypisz middleware działające tylko na produkcji w „Open questions” planu testów, a resztę pokryj smoke testem po wdrożeniu i stopniowym wdrażaniem.