POIT #250: Testy kontraktowe

Witam w dwieście pięćdziesiątym odcinku podcastu „Porozmawiajmy o IT”. Tematem dzisiejszej rozmowy są testy kontraktowe.

Dziś moim gościem jest Jacek Milewski – Trener, Architekt i programista, który modelując oprogramowanie ma świadomość jak zmienny jest software oraz jak ładny i bezpieczny może być, gdy tylko pragmatycznie podejść do projektowania, kodowania i testowania. Zadaje pytania aby wyłuskać to co istotne, a odfiltrować szum. Z tego buduje backend, frontend, infrastrukturę i… zespół. W ramach Bottega IT Minds uczy innych oraz dzieli się swoim doświadczeniem.

W tym odcinku o testach kontraktowych rozmawiamy w następujących kontekstach:

  • czym są testy kontraktowe i na jaki problem odpowiadają?
  • z jakich narzędzi możemy skorzystać?
  • jakie korzyści mogą przynieść zespołowi oraz biznesowi testy kontraktowe?
  • jaka jest zasada działania Pact i Spring Cloud Contract?
  • co zespół musi ustalić wewnętrznie aby wprowadzić testy kontraktowe i jak tą ideę “sprzedać” wyżej?
  • jaki jest minimalny pierwszy krok do implementacji testów kontraktowych?
  • czy testy kontraktowe mogą działać w ramach CI?
  • jak testy kontraktowe wpływają na współpracę między zespołami developerskimi a zespołami QA?

Subskrypcja podcastu:

Linki:

Wsparcie na Patronite:

Wierzę, że dobro wraca i że zawsze znajdą się osoby w bliższym lub dalszym gronie, którym przydaje się to co robię i które zechcą mnie wesprzeć w misji poszerzania horyzontów ludzi z branży IT.

Patronite to tak platforma, na której możesz wspierać twórców internetowych w ich działalności. Mnie możesz wesprzeć kwotą już od 5 zł miesięcznie. Chciałbym oddelegować kilka rzeczy, które wykonuję przy każdym podcaście a zaoszczędzony czas wykorzystać na przygotowanie jeszcze lepszych treści dla Ciebie. Sam jestem patronem kilku twórców internetowych i widzę, że taka pomoc daje dużą satysfakcję obu stronom.

👉Mój profil znajdziesz pod adresem: patronite.pl/porozmawiajmyoit

Pozostańmy w kontakcie:

 

Muzyka użyta w podcaście: „Endless Inspiration” Alex Stoner (posłuchaj)

Transkrypcja podcastu

To jest 250. odcinek podcastu Porozmawiajmy o IT, w którym z moim gościem rozmawiam o testach kontraktowych.

Wszystko, co potrzebujesz, notatka, linki, transkrypcja czekają na Ciebie na porozmawiajmyoit.pl/250.

Myślisz o zmianie pracy lub przebranżowieniu do IT? Zajrzyj na SOLID.Jobs, gdzie znajdziesz przejrzyste oferty z informacją co do zarobków, technologii i projektów.

Nazywam się Krzysztof Kempiński, prowadzę ten podcast oraz jestem autorem książki Marka osobista w branży IT. Mam misję polegającą na poszerzaniu horyzontów ludzi z branży IT. Tak się składa, że możesz bardzo mi pomóc w jej realizacji poprzez wystawienie oceny w aplikacji, w której tego słuchasz, lub podzielenie się odcinkiem w social mediach. A teraz zapraszam Cię już do odcinka.

Odpalamy!

 

Cześć! 

Mój dzisiejszy gość to trener, architekt i programista, który modelując oprogramowanie, ma świadomość, jak zmienny jest software oraz jak ładny i bezpieczny może być, gdy tylko pragmatycznie podejść do projektowania, kodowania i testowania. Zadaje pytania, aby wyłuskać to, co istotne, a odfiltrować szum. Z tego buduje backend, frontend, infrastrukturę i zespół. W ramach potęgi IT Minds uczy innych oraz dzieli się swoim doświadczeniem. Moim i Waszym gościem jest Jacek Milewski. 

Cześć, Jacku, bardzo miło mi gościć Cię w podcaście. 

 

Cześć, Krzysztof, witam. 

 

Dzisiaj będziemy rozmawiać z Jackiem o testach i to testach niebylejakich, bo takich opartych o kontrakty. I mam wrażenie, że się okaże, iż to nie tylko programiści powinni być zainteresowani tego typu testami, ale również powinniśmy angażować inne zespoły, bo tym bardziej dodadzą nam tutaj wartości do tych testów. 

Ale zanim do tego przejdziemy, to takie, wiesz Jacku, otwierające, standardowe u mnie pytanie. Czy słuchasz podcastów? Jeśli tak, to być może masz jakieś ciekawe audycje do polecenia?

 

Tak, słucham. To nie jest tak, że słucham 120 podcastów, jestem w stanie teraz wylistować wszystkie. Głównie, jeżeli mówimy o IT, to będzie Mariusz Gil i jego Better Software Design. To jest jeden z takich bardziej wartościowych dla mnie podcastów, jeżeli chodzi o cały świat IT, więc to bym pewnie polecił. 

Druga rzecz to jest taki podcast psychologiczny. To jest bardziej kanał zupełnie już miękki. Strefa Psyche Uniwersytetu SWPS. I tam prowadząca jest bardzo charyzmatyczna, tematy są bardzo ciekawe, te rozmowy, które prowadzi, są bardzo ciekawe. Tak że polecam. 

 

Fajnie, dzięki za te polecajki. Oczywiście z tego miejsca pozdrawiamy Mariusza. Dobrze, Jacku, to co? Warto byłoby pewnie na początku zdefiniować, czym właściwie te testy kontraktowe są i dlaczego powstały? W sensie, na jaki problem odpowiadają? 

 

Tak, problem pojawił się wtedy, kiedy musimy integrować dwa komponenty. W momencie, kiedy doszły mikroserwisy, to te dwa komponenty są rozproszone, tzn. po sieci celowo, bo chcemy mieć autonomię rozwijania tych mikroserwisów, autonomiczne zespoły, które wspólnie jednak składają się na wspólny system. Więc autonomia zespołu kończy się tam, gdzie zaczyna się autonomia drugiego zespołu. Nie chcemy się blokować, ale chcemy wiedzieć o sobie nawzajem, czy my będziemy jako cały system w stanie się dogadać. 

I ten kontrakt to jest właśnie to nasze API, po jakim będziemy rozmawiać. W mikroserwisach to najczęściej będzie HTTP, gRPC czy asynchroniczne wiadomości, więc kontraktem będzie ścieżka bądź nazwa topicu i będą parametry wejściowe, parametry żądania i parametry odpowiedzi. Ja chcę jakieś konkretne pole od Ciebie otrzymać, i to jest mój kontrakt, bo Ty mi zakontraktowałeś, że mi je dasz. 

Problem, jaki tu się pojawia, to pewnie przez skórę gdzieś tam już można wyczuć, bo to jest tak, że u mnie mój autonomiczny mikroserwis działa, ale jakimś sposobem na środowisko to już nie bardzo, bo tamci się nie wgrali, albo oni w ogóle nie wiedzieli, że mają się wgrać, albo nie wiedzieli, że ja oczekuję. Więc brakuje nam narzędzi do takiej komunikacji. Emulujemy to jakimiś kartkami papieru, jakbym to nazwał, bo dokumentacją na Confluence, dokumentacją na Swaggerze, w Wordzie, w Excelu, w czymkolwiek, czyli kartką papieru, nie chcemy się integrować kartką papieru. 

Więc nawet jeżeli ja u siebie napisałem testy, ale boję się deploymentu, bo muszę jeszcze przetestować na środowisku, to byłby taki znak, że być może brakuje Ci tego narzędzia. To jest ten problem, który rozwiązuje to narzędzie. Są dodatkowe benefity, które trochę te narzędzia przemycają pod spodem, a które są zaskakująco dobre. Tzn. ja chcę wiedzieć, jako ta strona serwerowa, czyli wystawiający API, czy ktoś jeszcze w ogóle z tego API korzysta. A czy ktoś korzysta z tego konkretnego jednego pola w tym JSON-ie 20-polowym, czy ja je mogę już usunąć. To dostajemy trochę za darmo.

Więc tak, to byłby ten problem i to nie jest nowy problem, bo jak prowadzę szkolenia i się pytam, czy testujecie kontraktowo, padają odpowiedzi: No tak obwąchiwaliśmy trochę te narzędzia, temat, trochę gadaliśmy, ale to grubsza rzecz, żeby to wdrożyć, a de facto testy kontraktowe są stare jak świat, dlatego że jeżeli ja mam w Javie, w .NET albo w dowolnym języku programowania metodę, która jest wywołana przez inną, inny fragment kodu, to spróbujcie w tej metodzie usunąć jeden z parametrów. Tylko tak bez ID, bez tego automatycznego refaktoringu. Zobaczcie, że właśnie złamaliście kontrakt i świeci się na czerwono. 

I takie coś chciałbym osiągnąć na poziomie mikroserwisowym. O ile na poziomie kompilatora to jest do ogarnięcia, bo kompilator to robił za nas, o tyle jak się wynosimy na poziom mikroserwisów, to już nie mamy jak tego zrobić inaczej niż na środowisku. A testy na środowisku są drogie, bo tam wszystko się rusza. 

 

Okej, czyli mamy ten problem dogadywania się, tu powiedziałaś mikroserwisów, ale możemy sobie jakieś tutaj przyjąć nazewnictwo jako systemy, w różnej konfiguracji może to działać. Mamy ten problem właśnie, żeby ta komunikacja była up-to-date, czy posługiwała się zrozumiałym językiem, zrozumiałym kontraktem dla obydwu stron. Jak się tak trochę poszuka, to mamy kilka narzędzi, kilka rozwiązań tego problemu. Kartka papieru jest z pewnością jednym z nich. Jak wiemy, wszystko przyjmie, niekoniecznie łatwo to aktualizować. Jest Spring Cloud Contract, jest PACT. Chciałbym Cię zapytać, czy to są jedyne narzędzia, jedyne możliwości, czy tylko w ten sposób możemy zapewnić kompatybilność kontraktu, a może znasz jakieś lepsze rozwiązania? 

 

Musimy mieć pełną świadomość tego, co jest na rynku, jakie mamy możliwości do rozwiązania problemu łamiących się kontraktów. Narzędzi jest kilka i te narzędzia, które tutaj faktycznie pierwsze się nasuwają, to są narzędzia specyficzne do tego i nimi będziemy się zajmować dalej, ale chciałbym, żebyśmy mieli pełen kontekst. 

Te narzędzia Spring Cloud Contract i PACT udają trochę kompilator na poziomie HTTP, tzn. build nam sfailuje w momencie, kiedy usunę parametr, który ktoś oczekuje. Tak jakbym to usunął w metodzie w Javie. Ale to nie jest jedyna metoda, żeby tę zgodność kontraktu zapewniać, monitorować czy zabezpieczać. Po pierwsze możemy nie zmieniać kontraktu, to zawsze będzie dobra metoda, nie zmieniamy nic. Z jednej strony to jest niedorzeczne, ale z drugiej strony, gdyby na to popatrzeć pod kątem stabilizowania interfejsu, tzn. jestem platformowym narzędziem generycznym, które ma na tyle ustabilizowany i dojrzały kontrakt, że po prostu nie potrzebuje go tak często zmieniać. A w momencie, kiedy go zmieniam, potrzebuję wprowadzić zmianę, która byłaby niekompatybilna, publikuję nową wersję, czyli zupełnie oddzielny endpoint. Więc to jest jedna ze strategii. 

Inna to jest usunięcie integracji, czyli w ogóle się nie integrujmy. To nie znaczy, że mamy rezygnować z jakiejś funkcjonalności, ale może jeżeli komponenty są blisko siebie, to może one powinny być jednym komponentem. I wtedy kontrakt nam testuje kompilator, tak jak wcześniej wspomnieliśmy. 

Mamy jeszcze możliwość sprawdzania schematu JSON, czy schematu XML, JSON Schema, XML Schema, czy na Kafce możemy też sprawdzać format wiadomości. To oznacza, że po prostu nie dasz rady wyprodukować jako provider czy jako consumer wiadomości, która jest niezgodna z tym schematem. I tu jest delikatna różnica, znaczy znacząca różnica, ponieważ przy JSON Schema muszę dopasować się do całego schematu. Natomiast w testach kontraktowych zakładam, że ja nie muszę używać wszystkich pól z tego schematu. To są przykładowe requesty, na które ja się umawiam. To nie znaczy, że musisz dopilnować każdego pola w tym schemacie. Jeżeli mnie jako konsumenta interesuje tylko jedno. 

I mamy jeszcze możliwość wypuszczenia SDK. Czyli znowu przenosimy kontrakt na poziom kompilatora Javy. Bo jeżeli wypuszczę SDK i zmienię nagłówek metody w tym SDK, to się po prostu komuś przestanie kompilować. Więc build mu nie przejdzie, więc osiągamy podobny wynik. Problem jest taki, że musimy tym SDK zarządzać, ale korzyści są takie, że to inni się do nas dopasowują, a my część zmian w API HTTP jesteśmy w stanie przemycić w tym SDK, nawet nie zmieniając tego API jobowego, więc daje to trochę plusów, poza tym SDK generuje się, no umówmy się, automatycznie z niektórych specyfikacji, więc to może być mniej bolesne. 

Jeszcze spotkałem się z takimi momentami, że zespoły, jako że mamy Dockera, jeżeli mamy Dockera, to można go użyć, no i można de facto postawić sobie środowisko na lokalnym laptopie. Gdzieś tam 20 Dockerów i 19 zależności i ja tam 20, który chce się z nimi wszystkimi przetestować. Problem z tym zaczyna się już przy pierwszym de facto dockerze, bo muszę go skonfigurować. On ma też jakieś zależności, też ma jakąś konfigurację, jakiś ustawiony stan, a więc bardzo, bardzo duży coupling jest i muszę mieć świadomość tego, jak tam te serwisy działają, żeby ustawić im odpowiedni stan. Jakby każde z narzędzi daje nam jakiś zakres jakimś kosztem. 

Te narzędzia Spring Cloud Contract i PACT udają trochę kompilator na poziomie HTTP, tzn. build nam sfailuje w momencie, kiedy usunę parametr, który ktoś oczekuje. Tak jakbym to usunął w metodzie w Javie. Ale to nie jest jedyna metoda, żeby tę zgodność kontraktu zapewniać, monitorować czy zabezpieczać. Po pierwsze możemy nie zmieniać kontraktu, to zawsze będzie dobra metoda, nie zmieniamy nic. Z jednej strony to jest niedorzeczne, ale z drugiej strony, gdyby na to popatrzeć pod kątem stabilizowania interfejsu, tzn. jestem platformowym narzędziem generycznym, które ma na tyle ustabilizowany i dojrzały kontrakt, że po prostu nie potrzebuje go tak często zmieniać. A w momencie, kiedy go zmieniam, potrzebuję wprowadzić zmianę, która byłaby niekompatybilna, publikuję nową wersję, czyli zupełnie oddzielny endpoint. Więc to jest jedna ze strategii.

 

Rozumiem. Wiesz, tutaj opisałeś trochę te narzędzia, myślę, że do tego sobie jeszcze przejdziemy. Natomiast testy zawsze wymagają jakiegoś nakładu pracy związanego z ich wytworzeniem, ale też później z utrzymaniem, żeby po prostu oddawały w pełni sytuację. I ma to sens albo warto to robić wtedy, kiedy otrzymujemy jakieś korzyści, jakieś oczywiste benefity z tego wypływające. Na bazie Twoich doświadczeń, o jakich benefitach, o jakich korzyściach dla zespołu, dla produktu, dla biznesu, idąc szerzej, mógłbyś powiedzieć w kontekście testów kontraktowych? 

 

Mam cztery na myśli i nie wiem, od którego zacząć jako najważniejszego, więc powiedzmy, że kolejność jest przypadkowa. Przede wszystkim to jest bezpieczeństwo wdrożeń. Ja nie chcę iść na żadne środowisko, tym bardziej na produkcję, kiedy API innego systemu nie jest jeszcze gotowe na tym środowisku. Chcę mieć to sprawdzone, nie na papierze i nie na Slacku, tzn. nie pytając się, czy już jesteście. Jesteśmy. A tak naprawdę jesteście, czy? Trochę jeszcze nie. Różnie bywa. Chcę mieć pewność zautomatyzowaną. Chcę, żeby narzędzie powiedziało mi, czy ja mogę bezpiecznie wdrożyć na środowisko. Pod kątem zgodności kontraktu. 

Testujemy tylko zgodność kontraktu, czyli pola w JSON-ie, ścieżkę do zasobu, czy topic w Kafce. Nie testujemy, czy ten kontrakt robi to, co miał robić pod spodem. Czy ta metoda zachowuje się tak, jak powinna. Testujemy, czy my się umiemy dogadać o to, czy oni dobrze się zachowują. To już jest ich autonomia, ich testy w izolacji. 

Więc mamy też równoległą pracę zespołów, która jest nienaruszona. Startujemy od kontraktu, dowozimy ten kontrakt z dwóch stron, tzn. provider tego kontraktu, czyli strona wystawiająca API, implementuje swój kod, dopasowując się do kontraktu, konsument implementuje swoje funkcjonalności, gdzieś dopasowując się do tego uzgodnionego wspólnie kontraktu. Więc możemy pracować równolegle. To nie jest tak, że provider musi przez dwa sprinty developować swoje, a ja przez kolejne dwa sprinty będę developował swoje. Możemy to zrobić kalendarzowo w dwa sprinty, a nie w cztery sprinty. 

I to zabezpieczenie kompatybilności. Testy kontraktowe pozwalają mi lepiej zarządzać starymi wersjami API. Tzn. mamy zmiany, które są zdecydowanie niekompatybilne wstecz, albo zmiany, które są kompatybilne wstecz. Dodanie nowego pola teoretycznie jest kompatybilne wstecz, zakładając, że nie ma stricte walidacji u konsumentów, ale usunięcie pola nie jest kompatybilne wstecz, bo ktoś może z tego pola korzystać i ktoś może się z tego powodu wywalić. 

I testy kontraktowe potrafią pokazać nam, czy ktoś z tego pola korzysta. Jeżeli jestem providerem, mam kilku konsumentów, to ja w kontraktach widzę, czy ktoś z niego korzysta. Nie muszę patrzeć, bo to automat mi to przetestuje, ale widzę, że zgodność kontraktu została naruszona z tym i tym konsumentem, kiedy usunąłem to pole. Ale jeżeli nie została naruszona, jeżeli wszystko jest zielone i usunąłem pole, to okazuje się, że usunięcie pola jest zmianą kompatybilną wstecz dzięki narzędziu do testów kontraktowych. A wiadomo, jak dużo bólu jedno pole w JSON nie może powodować. Wypełnianie czasem jednego booleana to jest odpytanie trzech systemów, więc chcemy to oszczędzać. 

Więc mamy też dokumentację tego, jak używają nas nasi konsumenci, jak używają API Providera, jakie przykładowe requesty dają, i na co się umówiliśmy de facto w związku z tym. 

 

Wspomniałeś tutaj o PACT, o Spring Cloud Contract. Myślę sobie, że warto byłoby może w tym momencie nieco szerzej powiedzieć, czym one w ogóle są i na jakich zasadach działają.

 

Tak, myślę, że rozszerzmy ten temat i zawęźmy już problemy, korzyści i te wszystkie narzędzia. Skupmy się teraz na narzędziach, które są może trochę mniej znane niż takie rzeczy typu SDK, wersjonowanie, mniej zaadoptowane na pewno. PACT i Spring Cloud Contract są narzędzia podobnej klasy i rozwiązują ten sam problem trochę na inne sposoby, jeżeli chodzi o narzędziówkę, natomiast koncepcyjnie są bardzo podobne. 

Polegają na tym, że mamy dwie strony relacji, dwie strony kontraktu. Jeden to jest konsument API, a drugi to jest provider API. W Spring Cloud Contract nie nazywa się provider, tylko producer. Znowu zmiana jest kosmetyczna. I pomiędzy consumerem a providerem mamy pakt. W Spring Cloud Contract to jest kontrakt, w PACT to jest pakt, czyli właśnie tą umowę, jak wygląda ich interakcja ze sobą. 

Więc mamy consumer, po środku kontrakt, po prawej stronie provider, no i mamy broker. Mamy centralny komponent, to jest jakiś infrastrukturalny serwer. W przypadku PACT-a to jest dedykowany pakt broker, w przypadku Spring Cloud Contract nie ma dedykowanego brokera, jest tylko storage, gdzie przechowujemy kontrakt. Broker to jest to centralne miejsce, które trzyma wiedzę o tym kontrakcie, Jakie są kontrakty pomiędzy kim a kim? Jaki jest status weryfikacji tych kontraktów? 

Oba narzędzia są otwarte na technologię, to znaczy możemy tu testować API restowe, czy w środku jest JSON, czy HTML, to nie ma znaczenia. W każdym razie wywołanie HTTP. Możemy testować messaging, to znaczy publikowanie wiadomości oraz czytanie tych wiadomości, tzn. zweryfikowanie kontraktu, też mając brokera po środku, i są integracje ze frameworkami takimi typowymi. Ja jestem ze świata Javowego, więc będę tu mówił o JUnit, o Spocku, Springu. Jest na to wsparcie. 

Spring Cloud Contract to jest narzędzie mocno zintegrowane ze Springiem. ale pozwala też testować kontrakty z innymi technologiami, czy to frontendowymi, javascriptowymi, typescriptowymi. I podobnie PACT. To jest założenie, że nie mamy heterogenicznego środowiska, nie jest wszystko w Javie, mamy różne technologie w zależności od potrzeb, więc czy to frontend, czy backend, czy .NET, czy Ruby, dla takich języków jest wsparcie. 

 

Myślę sobie, że wszystko jest okej albo w miarę spokojnie, jeśli w naszym małym zespole, w naszym małym poletku sobie różne rzeczy związane z testami uzgadniamy. Ale tak jak tutaj powiedziałeś, jeśli chodzi o testy kontraktowe, to musimy wyjść poza, musimy jakoś uzgodnić ten kontrakt z innymi zespołami, i tutaj pewnie mogą się pojawić różnego typu schody. 

Właśnie, te ustalenia są potrzebne, jest potrzebna jakaś zgoda zespołu albo zespołów inżynieryjnych, nierzadko też biznes pewnie musi się wypowiedzieć i coś tam zaakceptować, więc co byś polecał takiemu zespołowi, co wewnętrznie musi on sobie ustalić, aby w ogóle taką ideę testów kontraktowych wprowadzić, a może i co istotniejsze, w jaki sposób wewnątrz organizacji w ogóle tą ideę testowania sprzedać?

 

Jesteśmy już jakby po pierwszym poziomie teraz w naszej rozmowie, po zrozumieniu narzędzi. Wiemy, jakie mogą być oczekiwane, jakie możemy mieć korzyści, spodziewane efekty. Sposób użycia zrozumiemy pewnie, eksperymentując, no i model litencyjny to zawsze jest jakiś koszt. PACT kosztuje w takim pełnym rozwiązaniu, w takim fully fleshed, natomiast można sobie to postawić też open source’owo. Będziemy mieli trochę więcej zarządzania, maintenance’u, ale będziemy mieli za free. PACT jako narzędzie jest darmowy. 

Więc te ustalenia organizacyjne to też jest właśnie m.in. koszt licencji. Ale przede wszystkim będziemy patrzeć na te korzyści. Tzn. jak bardzo jesteśmy w stanie dopasować to do naszego obecnego cyklu wytwarzania. A czy zespoły są gotowe? Czy ta kultura pracy faktycznie pomagałaby pisać kontrakty, pisać testy kontraktowe? Jak wygląda model współpracy zespołów? Jaka jest skala systemu i skala problemu? Jeżeli mamy wszędzie stabilne kontrakty i mało to się zmienia, to pewnie te narzędzia to będzie overkill, bo stabilne kontrakty, tak jak mówiliśmy, to może być publikowanie nowych wersji, SDK, więc mamy różne opcje, ale w momencie, kiedy system się rozrasta, mamy więcej zespołów i chcemy dać im autonomię i chcemy wspierać bezpieczne zmiany biznesowe, to wtedy to warto rozważyć, prawda? 

Zawsze jest tak, że każdy by chciał, ale czasu nie ma, a więc to wsparcie z góry jest potrzebne, bo to nie jest rzecz w obrębie zespołu, tylko pomiędzy zespołami. I tutaj potrzebowalibyśmy jasnego sygnału: tak, idziemy w to. Jeżeli on pójdzie oddolnie, zrobimy POC, ocenimy skalę, to tym lepiej. Natomiast zawsze to wsparcie z góry jest pomocne. Też takiego ewangelisty czy takiego anioła, który będzie chodził po zespołach i pomagał im to wdrażać. 

Znając korzyści i znając problemy, musimy ocenić, do jakiego poziomu chcemy dojść. Jesteśmy jak na razie na poziomie drugim, czyli na decyzjach zespołowych czy cross zespołowych. Które komponenty są dla nas najbardziej krytyczne, na których mamy najwięcej problemów, które nam dają ryzyka, gdzie wdrożenie da nam największe korzyści. 

 

Czyli mamy decyzję, wiemy już, jakie są korzyści, możemy mówić o decyzji takiej wewnątrz zespołu, ale też szerzej dotykającej całego zespołu inżynieryjnego. Wobec tego jeśli decyzja jest na tak, widzimy wartość, widzimy, że to się może nam przysłużyć, to chcemy postawić ten pierwszy krok związany z implementacją testów kontraktowych. Co według Ciebie mogłoby być tym pierwszym krokiem właśnie?

 

Baby step. Myślę o baby stepach. I najmniejszy krok, jaki można zrobić, to na razie nieangażowanie całej tej infrastruktury. Tzn. pakt brokera czy repozytorium kontraktów, to wszystko można zrobić lokalnie, ręcznie kopiując plik. To dużo ułatwia i nie potrzebuje infrastruktury. Więc jako proof of concept możemy zacząć od pierwszego testu konsumenta, I jako wynik będziemy mieli plik wygenerowany przez PACT. Zasada działania Spring Cloud Contract  jest troszkę inna. Tam najpierw piszemy plik, a potem obie strony używają tego do testowania kontraktu. 

Natomiast skupmy się na PACT. Ja z tych dwóch narzędzi zdecydowanie poleciałbym PACT. Więc konsument określi kontrakt, konsument implementuje swój kod i wynikiem działania jego logiki jest wywołanie API Providera. Tylko API jeszcze nie ma, ale mamy PACT Provider, który nagrywa wszystkie żądania, które by wyszły do tego Providera. To, co on nagra, zapisuje do pliku i mówi: to jest kontrakt, którego oczekujesz od providera. 

Teraz trzeba by było wziąć ten kontrakt, iść do providera, czyli wziąć plik, skopiować plik, wrzucić go do kodu providera i znowu narzędziami pactowymi przeczytać ten plik i zweryfikować, czy provider odpowiada w taki sposób, jak oczekiwano. 

To też jest ogarnięte przez PACTA, tzn. możemy napisać test jednostkowy, który wszystkie testy, wszystkie specyfikacje bierze z tego pliku z kontraktem i po prostu uderza w API providera, tak jak każdy inny test jednostkowy czy też integracyjny, zależy jakie nomenklatury używamy. No i mamy wynik, albo API odpowiedziało tak, jak konsument oczekiwał, albo nie odpowiedziało. Więc możemy wtedy podciągać kod providera, tak aby odpowiedzieć na żądania konsumenta. 

To by był taki pierwszy krok, myślę. Dużo ułatwia, bo nie ma infrastruktury, nie potrzebujemy tej infrastruktury, ale wiemy, jak napisać test po stronie konsumenta i wiemy, jak po stronie producenta. I nie ma tu żadnego waste’u, bo ten plik potem będziemy obsługiwać inaczej, nie kopiować, ale to, co już napisaliśmy teraz, to już jest obeznanie się z narzędziem, zarówno po stronie providera, jak i konsumenta. Więc już wiemy, jak pisać testy. 

Natomiast skupmy się na PACT. Ja z tych dwóch narzędzi zdecydowanie poleciałbym PACT. Więc konsument określi kontrakt, konsument implementuje swój kod i wynikiem działania jego logiki jest wywołanie API Providera. Tylko API jeszcze nie ma, ale mamy PACT Provider, który nagrywa wszystkie żądania, które by wyszły do tego Providera. To, co on nagra, zapisuje do pliku i mówi: to jest kontrakt, którego oczekujesz od providera. 

Teraz trzeba by było wziąć ten kontrakt, iść do providera, czyli wziąć plik, skopiować plik, wrzucić go do kodu providera i znowu narzędziami pactowymi przeczytać ten plik i zweryfikować, czy provider odpowiada w taki sposób, jak oczekiwano.

 

Dobrze, to zróbmy ten drugi krok. W pierwszym niejako próbowaliśmy, niejako testowaliśmy, kopiując plik ręcznie, zarządzając nim w taki sposób manualny, ale doskonale zdajemy sobie sprawę, że w dłuższej perspektywie to może być problematyczne, może się zdarzyć jakiś ludzki błąd i będziemy ten czas tutaj na sprawdzanie, co się właściwie stało zwyczajnie tracić. Więc co mogłoby być tym drugim krokiem? Co mogłoby spowodować, że zarządzanie tym plikiem będzie właśnie robione inaczej, w sposób bezpieczniejszy, wydajniejszy, niezależny od człowieka?

 

W poprzednim kroku po pierwsze bolące jest to, że musimy używać copy-paste i kopiować ten plik. Czy to robimy skryptem, czy ręcznie, nie ma znaczenia. Nie tego byśmy oczekiwali od dojrzałego narzędzia, więc to będziemy naprawiać. A druga rzecz jest taka, że co z tego, że provider się zweryfikował? My nie wiemy, jaki jest wynik tej weryfikacji. Znaczy mogą nam napisać na Slacku albo na kartce, albo powiedzieć: poczekajcie, my dociągamy swoje API i będziemy. Więc trzeba by było to podciągnąć. 

Więc tutaj już będziemy używać PACT Brokera. Skupmy się na przykładzie PACTA. W Spring Cloud Contract działa to troszkę inaczej, więc nie będziemy teraz rozważać dwóch narzędzi. To jest zbyt dużo jak na podcast, gdzie nie mamy tej formy wizualnej i rysunkowej. Więc zamiast kopiować plik, konsument wgra go na broker. Mamy do tego kilka narzędzi. Możemy to wrzucić requestem HTTP na brokera. Możemy to wrzucić pluginem do Gradle’a, czy pluginem do innego build toola, albo CLI, które PACT też dostarcza. 

Więc mamy kilka sposobów. Nadal możemy z lokalnej maszyny wrzucić ten plik na broker, zamiast wrzucić go do kodu repozytorium providera. I tutaj już musimy mieć broker. Czyli albo stawiamy sobie swój open source’owy PACT broker i na niego wrzucamy, nim zarządzamy itd., albo kupujemy narzędzie brokera od PACTA jako usługa. To jest PACT Flow wtedy. Nie ma to znaczenia. Oba brokery mają tą samą funkcjonalność. Więc tutaj jest decyzja o koszcie. 

Teraz provider może ten plik z kontraktem ściągnąć z brokera, więc nie musimy do nich chodzić. Jak plik się pojawi na brokerze, może pobrać kontrakt z brokera zamiast z pliku i zweryfikować tak jak dotychczas. PACT broker daje jeszcze jedną możliwość, tzn. provider może opublikować wynik tej weryfikacji. Więc tam na providerze będziemy mogli zobaczyć ten konsument, ten provider i czy jest czerwono, czy jest zielono, mówiąc wprost, czy on już spełnia, czy nie spełnia. I to by był taki enabler dla kolejnych kroków, po to aby potem iść krok dalej, bo coś z tym wynikiem weryfikacji będziemy musieli zrobić. 

Tutaj też pojawia się taka mała zagwozdka. Chciałbym, żeby to wybrzmiało. Konsument de facto w tym momencie napisał czerwony test dla providera. Tzn. ja jestem konsumentem i mogę wykrzaczyć build providerowi. Bo mogę mu napisać kontrakt, wrzucić go na brokera, on tego brokera zczyta i zaczyna mu failować build. W związku z tym mamy coś takiego jak pending pacts, czyli możemy powiedzieć, że ok, ten kontrakt jest i proszę testuj go, raportuj go, ale nie wywalaj bilda. Tzn. to jest taki pending pact i chcę, żeby on był pending do, załóżmy, jakiejś daty, sierpnia 2024. Po sierpniu 2024 on już musi być obowiązujący, bo już wtedy będę oczekiwał, żeby on był. Więc mamy tutaj de facto wrzucanie skwarek drugiemu zespołowi. To na to trzeba uważać, żebyśmy nie przegięli z ilością wyspecyfikowanych kontraktów. 

 

Czy jesteśmy w stanie to wszystko wpleść w proces CI? Czy moglibyśmy uzyskać niejako pokrycie czy też uruchomienie tylko tych podstawowych testów, które zazwyczaj wchodzą w skład właśnie pipeline’u CI, ale również tutaj tych testów kontraktowych, co pewnie byłoby już takim całościowym tutaj z badaniem czy czegoś przypadkiem na produkcji nie wysypiemy?

 

No właśnie. Czyli teraz wszystko, co robimy ręcznie z własnego laptopa, publikowanie kontraktu, publikowanie wyników weryfikacji, jesteśmy w stanie zrobić z czyjegoś laptopa, czyli z CI-a, z komputera tamtego, co nam robi robotę. I te kroki, które do tej pory robiliśmy, wciskając przycisk u siebie na laptopie, możemy przenieść na CI-a. Czyli chcę, żeby konsument, kiedy się buduje, żeby właśnie opublikował ten kontrakt, którego on teraz będzie oczekiwał. 

Z drugiej strony broker chciałbym, żeby kiedy się buduje, to sprawdził wszystkich konsumentów, czy on nie złamał kompatybilności kontraktu. I to wszystko. Jesteśmy w stanie uruchomić na CI. 

Ja mam też przykładowy projekt, to podlinkujemy, gdzie to jest wdrożone. Tam to jest projekt na GitHubie i CI-em jest GitHub Actions i te wszystkie kroki tam są, więc będzie można sobie podejrzeć. To jest projekt, na którym prowadzę szkolenia, więc tam jest trochę więcej tego kodu niż tylko kontrakty. W razie gdybyście mieli problem znawigować, to piszcie. 

I teraz, w którym momencie chcemy publikować kontrakt? Od strony konsumenta, po pierwsze na pewno z maina, na pewno z głównego brancha. Chcę powiedzieć, że to jest mój main i to niedługo wyjdzie na środowisko, więc chciałbym, żebyś się do tego dostosował. Ewentualnie powiedział mi, czy jesteś dostosowany, to wtedy zaczynamy rozmowę. Jak buildy nam failują, to ta rozmowa zawsze jest łatwiej zacząć, bo mamy czerwony krzyżyk nad głową. 

Ale możemy też publikować kontrakty na każdym pull requestie. To znaczy w momencie, kiedy już prawie jestem w mainie, to mogę dać znać, że to nie jest jeszcze ten docelowy branch, więc to nie jest tak, że nie możesz providerze iść na środowisko, tylko już masz teraz sygnał, że coś nowego tutaj doszło i proszę przetestuj to, po to, abym ja u konsumenta wiedział, czy ja mogę bezpiecznie zmerdzować tego PR-a, a Ty widział, że coś tutaj kombinuje i że coś się dzieje. Zmerdzujemy do maina, czyli już mamy ten kontrakt obowiązujący. 

 

Właśnie, bo mamy te wyniki weryfikacji na brokerze, przynajmniej zdajemy sobie sprawę już, jakie zmiany potencjalnie mogą się pojawić, ale to wcale nie chroni nas przed tym, żebyśmy niekompatybilne zmiany przypadkowo na środowisko testowe opublikowali. Czy w związku z tym możemy tutaj zastosować jakiś rodzaj decyzji, jakiś rodzaj bramki, która nam właśnie określi, czy idziemy z tym wdrożeniem, czy może jednak powinniśmy jeszcze coś poprawić? 

Właśnie, każdy zna ten pattern na CI, że jak test failuje, to puść jeszcze raz, albo jak ciśnie termin, to dobra, idziemy na produkcję, to tylko kontrakt. Więc każdy zna taki przypadek pomijania testów, i de facto, jeżeli wyniki weryfikacji są na brokerze, no to CI może sobie tak po cichu przemknąć się i zdeployować. W związku z tym mamy mechanizm Can I deploy, czyli sprawdzenia, czy ja mogę zdeployować się na to środowisko. 

To jest proste pytanie. Odpowiedź jest dosyć rozbudowana. Dlatego, że kiedy konsument pyta, czy mogę iść na środowisko, can I deploy to test?, to muszę sprawdzić, czy wszyscy moi providerzy są na tym środowisku ze zgodnymi kontraktami. Can I deploy? to jest pytanie do brokera i broker odpowiada listą. Ten jest, ten jest, ten jest. Możesz iść. A jak jeden z nich nie jest, no to nie bardzo możesz. Tzn. ten kontrakt jeszcze nie jest. Możesz go ustawić jako pending, to znaczy na razie go ignoruj, możesz go zignorować zupełnie, bo być może oni w ogóle nie dowieźli jeszcze PACT-a, więc po prostu go ignoruj zawsze, ale mam teraz jasną odpowiedź na pytanie, czy mogę się zdeployować na test? Możesz, bo wszyscy twoi providerzy są. 

Natomiast jeżeli jestem providerem, czyli wystawiam API, to to pytanie ma troszkę mniejszy sens, bo to nie jest tak, że ja od kogoś zależę, inni zależą ode mnie. Ja chyba wycofałbym się z tego, że to ma mniejszy sens. To ma inny sens. Tzn. jako provider sprawdzam, czy moje weryfikacje kontraktów przeszły. Czy mogę mieć failujące weryfikacje kontraktów teraz akurat w developie, w developmencie, ale na środowisku jestem kompatybilny, więc w mainie tego nie mam, możesz wyjść, bo na teście wszyscy konsumenci, którzy są, mają kompatybilność z tobą, więc okej. Nie będziesz mógł iść z kolejnym buildem, bo właśnie tutaj coś się złamało, ale z tym buildem możesz iść. 

I tutaj mamy właśnie ten element testów wdrożenia na pierwsze środowisko. To teraz, jeżeli provider czy consumer pytają, czy mogę iść na środowisko, czyli can I deploy, to wszyscy muszą zaraportować też, że oni się zdeployowali, tzn. provider, jeżeli wgrał się na środowisko z jakimś kontraktem, musi zareportować do PACT Brokera: jestem na teście, jestem na QA-u, jestem na produkcji. Więc to jest dodatkowy krok w CI-u, w tym CI-u już bardziej CD, tym odpowiedzialnym za deployment, po każdym poprawnym deploymencie raportuje, że jestem na tym środowisku, do PACT Brokera. 

Dzięki temu konsument może odpytać Pact Brokera, czy ja się mogę zdeployować na to środowisko, czy mój provider już tam jest. Więc ważny element jest też raportowania tych wdrożeń na środowisko. Na Pact Brokerze mamy stan, która wersja kontraktu, na którym środowisku jest. Można sobie to czytać ręcznie, tego trochę się tam robi. Stąd jest to właśnie pytanie, ta kwerenda do PACT Brokera Can I deploy, który zbierze te wszystkie informacje, przejrzy te wszystkie kontrakty i powie: możesz albo nie możesz. 

 

Jasne. To teraz myślę, że dobrze byłoby poznać Twoje doświadczenia z wdrażania testów kontraktowych już w takich produkcyjnych systemach. Co byś polecał, czego unikać, na co zwracać uwagę, żeby to się zakończyło sukcesem?

 

Tak, chciałbym jeszcze nawiązać do tego, co powiedziałem o tym, że rekomendowałbym PACT zamiast Spring Cloud Contract. Startowałem Spring Cloud Contract i wdrażałem to, wdrażałem też PACT-a, więc jest zasadnicza różnica w narzędziówce. Tzn. PACT broker dużo robi i dużo daje. Jest bardzo korzystny. Cały Can I Deploy, to wszystko mamy w tym narzędziu. W Spring Cloud Contract tego mi brakowało. Dodatkowo zdaje się, jak na moje obecne doświadczenie, że API PACT-a jest bardziej stabilne i jest mniej takich łamiących zmian wraz z nową wersją. Trochę mniej effortu. Dokumentacja, wydaje mi się, że PACTA była lepsza. Obie są trudne, naprawdę, obie są trudne. 

Nawet jak wdrażałem Spring Cloud Contract, rozumiałem już o co chodzi w testach kontraktowych, to jak zacząłem czytać dokumentację PACT-a, nadal nie było łatwo, więc ta dokumentacja jest trudna. Dobrze mieć takiego jednego aniołka w firmie, który przyjdzie i podpowie, który już to robił, przyjdzie i podpowie, żeby zespoły nie musiały tego przechodzić. Oszczędziłbym im tego bólu. Są pewne antywzorce, które potem gryzą. To jest po prostu strzał w stopę. Jeżeli to zrobię na początku, to wygląda bezpiecznie, ale potem to wygląda źle. 

Testy kontraktowe to nie są testy funkcjonalności. Tzn. ja nie testuję procesu biznesowego. Ja testuję tylko, czy technicznie na poziomie API jestem w stanie się dogadać. A to, jak ten request zostanie obsłużony, jak ten response zostaje wytworzony, to już jest element tego autonomicznego zespołu i ich własnych testów funkcjonalnych, ich API. My sprawdzamy, czy na oczekiwany request dostanę oczekiwany response. Czyli nie sprawdzamy całego body requestu i response’a, sprawdzamy tylko przykłady wywołań. Działamy na przykładach. Sprawdzanie całości to był JSON Schema. Tam musimy mieć wszystkie pola, wszystkie pasujące do Schema. Tutaj, co z tego, że ty masz 20 pól w responsie, ja Ci mówię, że ja oczekuję tylko dwóch. Tylko na tych dwóch opieram swoje działanie. 

To oznacza, że jeżeli inni konsumenci mają tak samo, tzn., że te 18 możesz sobie wywalić. I to jest zmiana kompatybilna wstecz. I trochę to jest tak, że testy kontraktowe to jest de facto pisanie testów drugiemu zespołowi. Bo jeżeli ja piszę jako konsument: oczekuję tego, to nagle w ich pipeline to się pojawia i coś im może zacząć failować. Więc nie nadużywamy tego. Tzn. naprawdę reprezentatywne zapytanie i odpowiedzi, to, co jest dla nas naprawdę core’owe i tylko przykłady, a nie każdy request, dlatego że to powoduje, że się zakopiemy. 

I jeszcze złota zasada testów kontraktowych jest taka, że provider nie obiecuje nic więcej niż w kontrakcie. Jeżeli coś jest w kontrakcie, to ja go dotrzymam, ale nie spodziewaj się nic więcej. Jeżeli mnie wyspecyfikowałeś tego, że potrzebujesz tego pola, to nie oczekuj, że ono tam będzie. Jeżeli oczekujesz, że ono tam będzie, no to musisz mi to wyspecyfikować w kontrakcie. Dlatego, że na małą skalę to jest ok, my się znamy i możemy sobie na kartce papieru powiedzieć, ale na większą skalę, jak ja mam 10 konsumentów, 5 konsumentów, to to już jest za dużo, żebym ja pamiętał, co Ci obiecałem. 

A z drugiej strony konsument nie może oczekiwać więcej niż w kontrakcie. Jeżeli czegoś oczekujesz, nie ma tego w kontrakcie, spodziewaj się, że to może zniknąć, bo pamięć jest słaba, ludzie się zmieniają, system się zmienia. 

 

Tak, oczywiście. Czy ten rodzaj testów według Ciebie wpływa jakoś na współpracę zespołów deweloperskich i tych związanych z QA? Czy zespoły QA w ogóle powinny wiedzieć o tego typu testach, być może być zaangażowane w ich tworzenie? Jakie tutaj dobre praktyki byś wskazał?

 

Tak, to co mówimy tutaj, testy kontraktowe to jest jeden z elementów, o jakich mówię na na swoich szkoleniach. To jest jeden z elementów. Wdrożony sam jeden już daje trochę korzyści, ale musi za tym iść całość. Taki przyświecający motyw, jaki próbuję przekazać na szkoleniach, to jest shift-left, czy left-shift, shift-left, przesunięcie testów w procesie wytwórczym w lewo. Czyli jak patrzymy sobie na taskownicę, no to jak najbardziej na development, a jak najmniej na środowiskach. 

Dlatego, że środowiska mikroserwisowe cały czas się zmieniają. Jeżeli ja muszę wdrożyć na środowisko, żeby przetestować, czy ja z integracjami moimi dobrze działam, to to już jest za późno. Testy kontraktowe pozwolą nam ten techniczny aspekt przetestować wcześniej, już na etapie developmentu. Więc testy kontraktowe piszą developerzy. 

To jest też częste nieporozumienie. Testy kontraktowe piszą developerzy, którzy integrują się z zewnętrznym systemem. QI-owie czy testerzy muszą mieć świadomość wszystkich testów, czy to są jednostkowe, czy to są integracyjne. Ja to upraszczam. Ja tę nomenklaturę troszkę inaczej rozumiem, ale upraszczam. Muszą wiedzieć, co już zostało przetestowane. Dlatego, że testerzy są odpowiedzialni za testowanie i oni twierdzą, że odpowiedzialność jest na nich za to, że wypuścimy przetestowany produkt. A to nieprawda. Developerzy są też odpowiedzialni za to, żeby wypuścić przetestowany produkt. 

To znaczy, jako tester powinienem wiedzieć, co już zostało przetestowane na poziomie mikrotestów, unit testów, testów komponentowych, testów kontraktowych, po to, żeby tego nie sprawdzać wyżej. Takie rzeczy ja mogę sprawdzić na pull request jako tester. Albo, w zależności od kodu, sprawdzić, czy taki warunek został przetestowany przez developera. Jak nie, to mu dopisać w pull requestie. 

I teraz pozwalamy testerom skupić się na tym, co jest najważniejsze. Tzn., czy całość systemu działa. Ja nie chcę, żeby oni mieli przeszkody typu, o, brakło pola w JSON-ie. Albo pole w JSON-ie nazywa się nie user ID, tylko custom ID. No, sorry. Czy naprawdę musieliśmy iść na środowisko, żeby się o tym dowiedzieć? Wydaje mi się, że flowy, które testują testerzy, powinny być pokryte testem kontraktowym, po to, żeby uniknąć takich sytuacji. To na pewno plus flowy, których nie testują testerzy, też muszą być pokryte, bo nie testują ich nawet testerzy. Więc to tym bardziej krytyczne.

Odpowiedzialność przesuwam. Szkoląc z testów, przesuwam odpowiedzialność po to, aby jak najmniej testów było potrzebne na środowisku. Dlatego, że na środowisku już mamy dość problemów i nie musimy tam dokładać sprawdzania kontraktów. 

To jest też częste nieporozumienie. Testy kontraktowe piszą developerzy, którzy integrują się z zewnętrznym systemem. QI-owie czy testerzy muszą mieć świadomość wszystkich testów, czy to są jednostkowe, czy to są integracyjne. Ja to upraszczam. Ja tę nomenklaturę troszkę inaczej rozumiem, ale upraszczam. Muszą wiedzieć, co już zostało przetestowane. Dlatego, że testerzy są odpowiedzialni za testowanie i oni twierdzą, że odpowiedzialność jest na nich za to, że wypuścimy przetestowany produkt. A to nieprawda. Developerzy są też odpowiedzialni za to, żeby wypuścić przetestowany produkt. 

 

Pewnie, na koniec dnia to wszyscy z zespołu inżynieryjnego są odpowiedzialni za jakość, więc spróbujmy sobie wzajemnie pomóc, a nie rzucać kłody pod nogi. 

Dobrze, podczas dzisiejszego spotkania o testach kontraktowych mówił Jacek Milewski, zachęcał do korzystania właśnie z tego typu testowania, dużo mówił o narzędziach i takich dobrych praktykach właśnie z wdrożenia testów kontraktowych. 

Jacku, bardzo Ci dziękuję za rozmowę i powiedz, proszę, gdzie możemy Cię znaleźć w internecie, gdzie możemy słuchaczy odesłać do Twoich materiałów. 

 

Dziękuję bardzo. Tutaj zacznę od tego GitHuba, o którym wspominałem. Podlinkujemy. Tam jest projekt, który implementuje system do sprzedaży biletów. Tam są dwa mikroserwisy i pomiędzy nimi implementacja testów kontraktowych w Cloud Contract i w PACT. Więc można sobie tam popatrzeć, jak nie to zajrzeć do mnie, napisać do mnie, to pogadamy, wprowadzimy szerzej o temacie ogólnie testowania mikroserwisów, w tym też testów kontraktowych. Można mnie spotkać na konferencjach, gdzie o tym często mówię, ale można też zobaczyć, znaleźć mój program szkoleniowy na stronce Botegi. To też podlinkujemy. Tam wyjaśniam całą koncepcję, bo left shift to jest większa rzecz niż tylko testy kontraktowe. 

Podlinkujemy też mojego bloga. Kiedyś był bardziej ożywiony, teraz jest mniej ożywiony. Różne są fazy, natomiast kilka rzeczy można się stamtąd dowiedzieć. I jest LinkedIn i X. I tam wkrótce pojawią się materiały, będą się pojawiać króciutkie materiały o zapewnianiu, o implementowaniu i różnych podejściach do wzorców komunikacji pomiędzy mikroserwisami. Nie tylko testowania, ale w ogóle komunikacji. I to będzie ciekawa forma. Tak że zachęcam. Niedługo będzie się pojawiać.

 

Świetnie. Oczywiście wszystkie te linki standardowo w trakcie do odcinka się znajdą. Tak że Jacku, jeszcze raz bardzo Ci dziękuję za poświęcony czas, za rozmowę. Dobrego dnia, do usłyszenia i cześć.

 

Dziękuję, cześć.

 

I to na tyle z tego, co przygotowałem do Ciebie na dzisiaj. Więcej wartościowych treści znajdziesz we wcześniejszych odcinkach. Masz pytania? Napisz do mnie na Krzysztof@porozmawiajmyoit.pl lub przez social media. Ja się nazywam Krzysztof Kempiński, a to był odcinek podcastu Porozmawiajmy o IT o testach kontraktowych.

Do usłyszenia w następnym odcinku. 

Cześć!

 

+ Pokaż całą transkrypcję
– Schowaj transkrypcję
Tags:
mm
Krzysztof Kempiński
krzysztof@porozmawiajmyoit.pl

Jestem ekspertem w branży IT, w której działam od 2005 roku. Zawodowo zajmuję się backendem aplikacji internetowych i zarządzaniem działami IT. Dodatkowo prowadzę podcast, występuję na konferencjach i jestem autorem książki "Marka osobista w branży IT". Moją misją jest inspirowanie ludzi do poszerzania swoich horyzontów poprzez publikowanie wywiadów o trendach, technologiach i zjawiskach występujących w IT.