ProduktyUsługiSektory SQLCCase studiesAcademyBlogO nas Porozmawiajmy
Artykuł · API

Testy kontraktowe API w praktyce — jak wyłapywać błędy integracji, zanim trafią na produkcję

Dwa zespoły, dwa zielone pipeline'y, jedna awaria u klienta. Testy kontraktowe zamieniają milczące założenia o sąsiednim systemie w jawną, wersjonowaną i weryfikowaną umowę — i przenoszą pierwszy czerwony sygnał z produkcji do CI.

APISmartware· ok. 8 min czytania

Zespół sprzedaży kredytów zmienił format jednego pola w odpowiedzi API. U siebie przetestował wszystko — zielono. Zespół uruchomienia testował na mocku, który wciąż zwracał stary format — też zielono. Kontrakt między systemami złamał się bezgłośnie, a pierwszy czerwony sygnał zobaczył klient na produkcji. Testy kontraktowe API istnieją dokładnie po to, żeby ten sygnał pojawił się w CI: kilka tygodni wcześniej i o rząd wielkości taniej.

Mock kłamie grzecznie

Zacznijmy od uczciwej diagnozy. W organizacji po transformacji shift-left każdy zespół testuje swój komponent szybko i blisko kodu — a sąsiednie systemy zaślepia. Mock robi dokładnie to, co mu kazano: zwraca odpowiedź, którą autor testu założył, że sąsiad zwróci. I tu jest problem — mock nie jest złośliwy, jest grzeczny. Nigdy nie zaprotestuje, że sąsiedni system od trzech sprintów zwraca inną strukturę. Będzie uprzejmie potwierdzał założenia sprzed pół roku, a test na nim będzie równie uprzejmie zielony.

Efekt znamy wszyscy: każdy moduł osobno działa, a proces biznesowy pęka na styku. Defekt na granicy dwóch systemów nie ma właściciela, nie ma testu i nie ma czerwonego sygnału — obie strony testowały własne wyobrażenie tej samej granicy. Anatomię tego zjawiska rozkładamy szczegółowo w schemacie problemu; tutaj skupimy się na najskuteczniejszym pojedynczym narzędziu, które tę lukę zamyka.

Mock koduje założenia jednego zespołu o zachowaniu drugiego. Kontrakt koduje uzgodnienie obu zespołów — i jest weryfikowany po obu stronach. To cała różnica, ale zmienia wszystko.

Czym jest kontrakt danych — i dlaczego schema to za mało

Kontrakt danych to jawna, wersjonowana umowa między konsumentem a dostawcą API. „Jawna" znaczy: zapisana w repozytorium jako artefakt, nie ukryta w kodzie dwóch zespołów i pamięci trzech osób. „Wersjonowana" znaczy: każda zmiana jest widoczna, porównywalna i świadomie zaakceptowana. Umowa obejmuje co najmniej cztery warstwy:

Konkret z procesu kredytowego — głównej ścieżki sprzedaż → uruchomienie → spłata → zamknięcie. System sprzedaży tworzy wniosek_id i kwotę; system uruchomienia wymaga obu tych pól i zwraca umowa_id. Schema powie nam, że kwota to liczba dziesiętna. Nie powie, czy to kwota brutto z prowizją, czy netto do wypłaty; czy w przypadku kredytu konsolidacyjnego — który jest gałęzią grafu procesu, z własnym kontraktem na tej gałęzi — obejmuje ona spłacane zobowiązania, czy tylko nową gotówkę. Oba systemy mogą przejść walidację schemy i policzyć klientowi dwa różne harmonogramy. Dlatego dobry kontrakt opisuje również znaczenie pól i przykładowe pary żądanie–odpowiedź dla wariantów procesu, nie tylko kształt JSON-a.

Consumer-driven contracts w praktyce

Najlepiej sprawdzającym się modelem pracy jest kontrakt sterowany konsumentem (consumer-driven contract). Logika jest prosta: to konsument wie, czego naprawdę używa. Dostawca API może udostępniać czterdzieści pól, ale jeśli system uruchomienia konsumuje trzy, kontrakt powinien chronić te trzy — precyzyjnie i bez szumu.

Jak to wygląda operacyjnie:

To ostatnie zdanie jest sednem metody: dostawca dowiaduje się, że psuje konsumenta, we własnym CI, kilka minut po zmianie — a nie na testach integracyjnych za dwa tygodnie ani na produkcji za miesiąc.

Wirtualizacja usług — z tego samego kontraktu co produkcja

Skoro kontrakt jest jawny i maszynowo czytelny, można z niego zrobić coś więcej niż test: można z niego wygenerować zaślepkę. To fundamentalna różnica względem ręcznie pisanych mocków. Stub zbudowany z kontraktu zachowuje się tak, jak dostawca zobowiązał się zachowywać — a ponieważ dostawca jest w swoim CI weryfikowany względem tego samego kontraktu, dryf między zaślepką a rzeczywistością przestaje być cichy. Gdy dostawca zmieni API, najpierw pęknie jego weryfikacja kontraktu, a nie test konsumenta na nieaktualnym mocku. Zaślepka i produkcja mają wspólne źródło prawdy.

I tu uczciwe zastrzeżenie, bo bez niego ten artykuł byłby marketingiem: wirtualizacja nie zastępuje testu na realnym połączeniu wszędzie. Kontrakt weryfikuje strukturę, niezmienniki i uzgodnioną semantykę — ale nie wykryje problemów wydajnościowych styku, niespójności danych między środowiskami ani zachowań, których nikt nie przewidział w umowie. Tam, gdzie styk jest głównym źródłem ryzyka procesu — np. przekazanie uruchomionej umowy do modułu spłat — testujemy na realnej integracji, a wirtualizujemy styki tańsze w ryzyku. To świadoma decyzja podejmowana per styk, nie domyślny skrót; jak dobieramy tę granicę, opisujemy w materiale „Jak to działa naprawdę".

Narzędzia i osadzenie w procesie

Warstwa wykonania jest dziś dojrzała i nie trzeba tu niczego wymyślać. W projektach naszych klientów testy kontraktowe i API uruchamiamy najczęściej na trzech narzędziach: REST Assured (asercje na żądaniach i odpowiedziach HTTP w ekosystemie JVM, naturalny wybór, gdy testy żyją blisko kodu backendu), Karate (czytelne scenariusze API z wbudowanymi dopasowaniami struktur — niski próg wejścia dla całego zespołu) oraz SoapUI tam, gdzie integracje obejmują usługi SOAP i starsze systemy, co w bankowości jest normą, nie wyjątkiem.

Samo narzędzie to jednak mniejsza połowa sukcesu. Test kontraktowy, który żyje w prywatnym repozytorium jednego zespołu, chroni jeden styk z perspektywy jednej strony. Żeby kontrakty chroniły proces, muszą być reużywalne i widoczne: w naszym podejściu kroki kontraktowe trafiają do wspólnej biblioteki kroków BDD (utrzymywanej w Smart.Edytor), gdzie „zweryfikuj kontrakt sprzedaż→uruchomienie" jest tym samym klockiem dla każdego scenariusza, który przez ten styk przechodzi. Wykonaniem steruje Smart.Runner — te same kroki są uruchamiane w pipeline przy każdej zmianie i na żądanie przed wydaniem, a ich wyniki zasilają metryki styków wspierające Business Journey Coverage. Więcej o modułach platformy: produkty STS.

Typowe błędy wdrożeń contract testingu

Cztery sposoby, żeby mieć testy kontraktowe i nie mieć z nich nic

Wspólny mianownik tych błędów: traktowanie contract testingu jako narzędzia do wdrożenia zamiast praktyki do utrzymania. Narzędzie instaluje się w tydzień. Praktyka — uzgadnianie, recenzowanie i egzekwowanie umów między zespołami — wymaga procesu i właściciela.

Od czego zacząć

Nie od narzędzia i nie od wszystkich API naraz. Sekwencja, która działa u naszych klientów:

Po miesiącu takiej pracy organizacja ma coś, czego wcześniej nie miała: pierwsze styki, o których wiadomo — a nie tylko się zakłada — że dotrzymują umowy. A pierwsza zmiana API zatrzymana w CI zamiast na produkcji jest zwykle najlepszym argumentem za rozszerzeniem praktyki na kolejne procesy.

Chcesz zobaczyć mapę styków własnego procesu zamiast czytać o cudzych? Zacznij od diagnozy problemu: dlaczego zielone testy nie chronią procesów →

Zmapujmy styki Twojego procesu

Jeden krytyczny proces, mapa styków, pierwsze kontrakty wpięte w CI — i pomiar efektu zamiast obietnic. Porozmawiajmy o tym, gdzie Twoje integracje pękają dziś po cichu.