IT Systems Integration Consultant
Contract testing je metóda softvérového testovania, ktorá overuje, či spolu consumer a provider služba komunikujú v súlade so zdieľaným kontraktom – teda dohodou o formáte requestov a responses. Na rozdiel od integration testingu sa testy spúšťajú nezávisle na oboch stranách a nevyžadujú bežiace prostredie druhej služby.

V článku sa dozvieš:
Contract testing beží v dvoch krokoch. Consumer zapíše očakávania voči provider API do kontraktu, provider ho potom overí voči svojej implementácii.
Kontrakt je JSON alebo YAML dokument s očakávanými requestmi a responses. Namiesto spúšťania provider služby stačí táto zapísaná dohoda.
Rozlišujú sa dva typy testov. Consumer-side test overuje, či consumer vie pracovať s dátami podľa kontraktu. Provider-side test, tzv. verifikácia, overuje, či provider implementácia vracia to, čo kontrakt sľubuje.
Kontrakt zároveň definuje formát REST API odpovede vrátane štruktúry JSON tela, statusových kódov a hlavičiek, čo je jadro celého princípu.
Ak sa formát nezhoduje, test zlyhá pred nasadením a tím presne vidí, ktorá časť kontraktu nesedí, napríklad chýbajúce pole alebo iný dátový typ.
Contract testing sa v praxi často zamieňa s API testingom, integration testingom a component testingom. Rozdiely sú jemné, no rozhodujú o tom, čo presne test odhalí.
Nie. API testing overuje funkčnosť celého API zvonka, kým contract testing overuje len to, či sa consumer a provider zhodujú na formáte komunikácie.
API testing preveruje endpoint dôkladne: kontroluje business logiku, autentifikáciu aj chybové stavy. Contract testing sa sústreďuje len na štruktúru dát medzi stranami a beží nezávisle od toho, či je druhá služba spustená.
Predstav si mikroslužbu, ktorá vracia zoznam objednávok. API test overí, že endpoint vráti správne dáta aj pri chybnom vstupe. Contract test sa spýta iba na jedno: či pole s cenou je typu number, a nie reťazec.
| Kritérium | API testing | Contract testing |
|---|---|---|
| Čo overuje | funkčnosť a správanie celého API | zhodu formátu requestu/response medzi consumer a provider |
| Potrebuje bežiace prostredie | áno, oboch strán | nie, beží nezávisle na oboch stranách |
| Typický rozsah | celý endpoint, business logika | len štruktúra dát a kontrakt |
Integration testing overuje, či spolu fungujú reálne bežiace komponenty, kým contract testing to isté overí bez toho, aby druhá služba vôbec bežala.
Integration testing potrebuje bežiace prostredie oboch strán súčasne, je preto pomalší a krehkejší. Na rozdiel od neho beží contract testing izolovane a rýchlejšie, pretože sa spolieha len na zapísaný kontrakt.
V praxi sa oba prístupy dopĺňajú: contract testing zachytí nesúlad formátu skôr, ešte pred integračným testom. Ak napríklad provider zmení dátový typ poľa „status“, contract test to zachytí okamžite, integration test až pri behu systému.
Component testing overuje jednu službu izolovane od zvyšku systému. Naopak, contract testing sa zameriava presne na rozhranie medzi dvoma službami.
Component testing rieši vnútornú logiku jednej služby, napríklad spracovanie vstupu. Contract testing sa touto logikou nezaoberá, zaujíma ho len to, čo služba posiela von. Rovnaká funkcia môže prejsť component testami, a napriek tomu porušiť kontrakt zmenou formátu JSON objektu.
Pri consumer-driven prístupe consumer služba ako prvá napíše, čo od provider API očakáva. Provider potom svoju implementáciu overuje práve voči tomuto očakávaniu.
Tento smer nie je náhodný: consumer najlepšie vie, aké dáta a v akom tvare potrebuje, keďže ich priamo spracúva. Kontrakt tak vzniká z jeho reálnych požiadaviek, nie z odhadu provider tímu.
Skratka CDC (consumer-driven contract) sa v tíme často používa samostatne. CDC prístup je pri mikroslužbách bežnejší než provider-driven, pretože pri desiatkach consumer služieb je nepraktické manuálne dohadovať kontrakt pre každú z nich.
Existuje aj opačný smer, provider-driven contract testing, kde kontrakt definuje provider. Hodí sa pri malom počte consumerov, inak je ťažké udržať prehľad, preto je v praxi menej bežný.
Pact je open-source nástroj, ktorý je de facto štandardom pre consumer-driven contract testing a podporuje väčšinu bežných jazykov a frameworkov.
Pracuje s kontraktmi vo forme JSON súborov, tzv. pactov, ktoré vznikajú automaticky pri consumer testoch. Test nevolá reálny provider server, ale beží proti mock serveru. Tieto pacty potom provider tím použije na verifikáciu voči skutočnému API. Pact podporuje Java, JavaScript aj .NET.
Pre tímy s hotovou OpenAPI špecifikáciou existuje alternatíva: OpenAPI contract testing overuje kontrakt priamo voči nej. Spring Cloud Contract testing zase sedí Spring a Java ekosystému. Komerčná nadstavba Pactflow pridáva vizualizáciu kontraktov a správu verzií pre väčšie tímy.
Nasledujúci konceptuálny príklad ukazuje, ako vyzerá jednoduchý Pact consumer test v JavaScripte:
// Pact consumer test (JavaScript, koncept)
const provider = new Pact({ consumer: "WebApp", provider: "UserService" });
provider.addInteraction({
state: "user 123 existuje",
uponReceiving: "request na detail používateľa",
withRequest: { method: "GET", path: "/users/123" },
willRespondWith: {
status: 200,
body: { id: 123, name: like("Ján Novák") }
}
});
Pact Broker je centrálne úložisko kontraktov, ktoré consumer aj provider tímy zdieľajú a kde broker automaticky overí, či nová verzia API neporušuje existujúci kontrakt.
Vždy, keď consumer alebo provider zmení verziu, publikuje nový pact do brokera, ktorý uchováva históriu všetkých verzií a vzťahov medzi službami.
Kľúčový mechanizmus sa volá can-i-deploy: pred nasadením broker skontroluje, či nová verzia neporuší kontrakt existujúcich consumerov alebo providerov, a dá jasnú odpoveď áno alebo nie.
Broker eviduje aj tagy a prostredia, takže vieš rozlíšiť, ktorá verzia kontraktu platí pre produkciu a ktorá pre staging.
… contract test spustíš aj lokálne bez bežiacej druhej služby, takže nesúlad formátu odhalíš ešte pred prvým integračným testom?
Contract testy nasadíš do CI/CD pipeline pred každým deployom. Broker overí can-i-deploy stav skôr, než sa nová verzia dostane do produkcie.
Typický flow: consumer tím spustí testy a vygeneruje pact, publikuje ho do brokera, provider spustí verifikáciu a výsledok sa zapíše späť. Až keď can-i-deploy vráti pozitívnu odpoveď, pipeline pokračuje k nasadeniu.
Vďaka tomuto gate sa problém so zhodou formátu odhalí ešte pred produkciou, nie až keď zákazník narazí na chybu. Contract testing sa tak stáva rýchlym a lacným poistným ventilom v mikroslužbovej architektúre.
Contract testing má zmysel, keď máš aspoň dve nezávisle nasadzované služby, ktoré medzi sebou komunikujú cez API. Pri monolite alebo jednej izolovanej službe ho nepotrebuješ.
Pri rozhodovaní pomôže jednoduché kritérium: ak sa API rozhranie mení často a služby nasadzujú rôzne tímy nezávisle, contract testing sa ti oplatí. Pri jednej aplikácii s jednou databázou by bol zbytočnou réžiou navyše.
Ak už robíš API testing napríklad cez Postman, contract testing je logický ďalší krok pri raste počtu mikroslužieb.
Zavedenie contract testingu si vyžaduje počiatočnú investíciu do brokera a CI kroku, preto sa oplatí, keď počet služieb a tímov rastie.
Pri prvom nasadení contract testingu začni s jedným kritickým consumer-provider párom, nie s celou mikroslužbovou mriežkou naraz. Overíš si proces skôr, než ho škáluješ.
Contract testing je metóda, ktorá overuje, či si consumer a provider služba rozumejú cez zdieľaný kontrakt o formáte komunikácie. Kontrakt je JSON alebo YAML dokument s očakávanými requestmi a responses. Na rozdiel od klasického API testingu neoveruje funkčnosť, len formát. Beží nezávisle na oboch stranách, pretože každá služba sa testuje voči zapísanému kontraktu, nie voči bežiacej druhej službe.
Nie. API testing overuje funkčnosť celého API, contract testing len zhodu formátu medzi consumer a provider. API testing zahŕňa aj business logiku, kým contract testing rieši len štruktúru dát. Je preto podmnožinou API testingu, nie jeho náhradou. Contract testy zachytia rozbitý formát skoro a lacno, správanie endpointov potom preveria API testy.
Integration testing potrebuje bežiace prostredie oboch služieb, contract testing beží izolovane bez neho. Integration testing je preto pomalší a krehkejší, závisí od infraštruktúry aj siete. Contract testing je rýchlejší a spustíš ho aj lokálne, lebo mu namiesto druhej služby stačí zapísaný kontrakt. Oba typy sa dopĺňajú, nenahrádzajú sa: contract testy overia formát komunikácie, integračné testy to, či služby spolu naozaj fungujú.
Component testing overuje jednu službu izolovane, contract testing sa zameriava na rozhranie medzi dvoma službami. Component testing rieši vnútornú logiku služby, napríklad spracovanie vstupu. Contract testing rieši len formát requestov a responses medzi službami. Služba preto môže kontrakt dodržať a napriek tomu vrátiť nesprávne vypočítanú hodnotu, čo odhalí až component test.
Pact Broker je centrálne úložisko kontraktov, ktoré automaticky overí, či je bezpečné nasadiť novú verziu API. Zdieľajú ho consumer aj provider tímy a uchováva históriu pactov. Kľúčový je mechanizmus can-i-deploy, ktorý pred nasadením odpovie, či nová verzia neporuší kontrakt inej služby. V CI/CD pipeline tak funguje ako brána, cez ktorú prejde len kompatibilná verzia.
Nie. Pact je najrozšírenejší nástroj s najväčšou komunitou, no existujú aj alternatívy ako OpenAPI-based contract testing alebo Spring Cloud Contract. OpenAPI-based prístup sedí tímom, ktoré už majú hotovú OpenAPI špecifikáciu a chcú kontrakt overovať priamo voči nej. Spring Cloud Contract je prirodzená voľba v Spring a Java ekosystéme. Rozhoduje teda najmä to, s akými technológiami tím už pracuje.
Contract testing dáva najväčší zmysel, keď tvoj systém rastie za hranicu jednej alebo dvoch služieb a API medzi nimi sa mení často. Zhodu formátu overíš rýchlo a izolovane, ešte pred pomalšími integračnými testami.
Nástroj Pact spolu s Pact Broker a mechanizmom can-i-deploy pokrýva väčšinu bežných scenárov. Začni s jedným kritickým párom, over si proces, a až potom ho škáluj na zvyšok systému.
Súvisiace články