4 sposoby łączenia Jenkins pipeline, które ułatwią Ci testy

Opublikowane przez Dariusz Grabowski w dniu

Sama umiejętność budowania Jenkins pipeline nie wystarczy do efektywnej pracy z ciągłą integracją. Projekty są zwykle tak złożone, że trudno jest umieścić wszystko w jednym jobie. Testy wykonywane są na różnych poziomach szczegółowości, a wytwarzane systemy składają się z wielu komponentów. Chcesz, aby Twój Jenkins pracował jak dobrze naoliwiona maszyna i odpowiadał na potrzeby projektu? Poznaj te 4 koncepcje łączenia potoków w Jenkinsie.

W większości skutecznych organizacji przy budowaniu Jenkins pipeline, stosuje się pojęcie piramidy testów. Polega ono na testowaniu aplikacji/systemu na wielu poziomach szczegółowości. W podstawowym wariancie mamy 3 rodzaje testów:

  • Jednostkowe (Unit Testy) – sprawdzają poprawne funkcjonowanie danej funkcji lub klasy. Zwykle dość proste w napisaniu, ich wykonanie zajmuje mało czasu i precyzyjnie wskazują gdzie pojawił się błąd.
  • Integracyjne – obejmują kilka komponentów systemu, mają za zadanie sprawdzić, czy poszczególne aplikacje dobrze komunikują się ze sobą. Testy są trudniejsze w przygotowaniu, zwykle trwają dłużej. Trudniej określić, w którym komponencie pojawił się błąd.
  • E2E – End to End – złożone testy obejmujące cały system. Trwają najdłużej, często operują na graficznym interfejsie użytkownika. Zwykle testuje się w ten sposób tylko podstawowe funkcjonalności użytkownika.
piramida testów

Zgodnie z piramidą powinniśmy tak podchodzić do testowania, aby testów jednostkowych było jak najwięcej, a testy E2E stosować tylko tam, gdzie to niezbędnie konieczne. To dlatego, że te pierwsze są najtańsze w utworzeniu i uruchamianiu (najkrócej się wykonują) w przeciwieństwie do E2E.

Gdy budujemy potok ciągłej integracji bardzo ważny jest czas od commita do wykrycia usterki. Im krótszy, tym łatwiej naprawić wprowadzony błąd. Gdy programista szybko otrzymuje informację, że coś jest „nie tak” z kodem który przed momentem modyfikował, najpewniej szybko przygotuje poprawkę. Gdy od commita do wykrycia błędu mija wiele tygodni o wiele trudniej będzie znów „wgryźć się w temat”.

Budując potoki ciągłej integracji warto trzymać się kilku zasad:

  1. uruchamiaj joba tak często jak to możliwe,
  2. na początku potoku uruchamiaj najszybsze testy,
  3. niezależne od siebie zadania uruchamiaj równolegle.

Dzięki temu programiści i testerzy szybko otrzymają informację zwrotną jeśli w aplikacji lub testach występuje błąd. Czas od wystąpienia błędu do informacji zwrotnej to wartość, którą warto optymalizować. Mając w głowie powyższe zasady, przedstawię Ci 4 sposoby na łączenie potoków w Jenkinsie, dzięki którym zredukujesz ten czas do minium.

1. Jeden Jenkins pipeline do wszystkiego

jenkins pipeline wszystko w jednym

To podejście warto stosować w przypadku gdy mamy do czynienia z prostą aplikacją/systemem. Jedyne co musimy zrobić to zbudować aplikację i uruchomić testy. Zwykle to będą testy jednostkowe. Na końcu umieszczamy gotową binarkę/obraz dockerowy w repozytorium binariów. Jaka jest zaleta takiego rozwiązania? Przede wszystkim prostota konfiguracji. Całość potoku zawiera się w jednym Jenkinsfile. Nie ma tutaj konieczności synchronizacji pomiędzy różnymi jobami czy repozytoriami. Możemy oczywiście w ten sposób uruchamiać wieloetapowe testy i zakończyć wdrożeniem na produkcję. Warto jednak się zastanowić czy w takim przypadku podejście to zapewni szybką informację zwrotną do zespołu wytwórczego.

2. Oddzielone budowanie i testowanie aplikacji – dwa Jenkins pipeline

Innym rozwiązaniem jest separacja budowania i testowania aplikacji. Jest to szczególnie przydatne gdy kod aplikacji i testy rozwijane są w osobnych repozytoriach. Dzieliby w takim przypadku potok na 2 joby:

  1. jeden odpowiedzialny za zbudowanie aplikacji, podstawowe testy i umieszczenie jej w repozytorium binariów. Na końcu wywołanie drugiego joba,
  2. którego zadaniem jest pobranie najnowszej aplikacji, przygotowanie środowiska testowego i uruchomienie testów.
jenkins pipeline tylko budowanie
Pierwszy job przygotowuje aplikację

Dzięki takiemu rozwiązaniu zmiany w repozytorium testów nie spowodują zbędnego budowania się aplikacji. Aby wywołać budowanie innego joba w pipeline, wystarczy użyć polecenia:

build job: 'nazwa-joba', 
     parameters: [
         string(name: 'wersja_aplikacji', value: 'master-' + String.valueOf(BUILD_NUMBER)),
         booleanParam(name: 'parametr_logiczny', value:true)
     ]

Poza samym wywołaniem możemy w ten sposób przekazać parametry do uruchomienia joba. Warto pamiętać, że owe parametry muszą być najpierw skonfigurowane w jobie, który będzie wywoływany. Inaczej otrzymamy błąd. Do wygenerowania polecenia najlepiej użyć Snippet Generatora, którego szerzej opisywałem w swoim darmowym e-booku.

jenkins pipeline uruchomienie wyzwolonych testów
Drugi job testuje aplikację

Jaki jest minus takiego rozwiązania? Gdy zmienimy parametry dla joba z testami musimy uwzględnić to w 2 miejscach (osobnych repozytoriach). Ale spokojna głowa – jeśli o tym zapomnimy Jenkins przypomni nam generując siarczysty błąd 🙂

3. Pipeline orkiestrator

Zadaniem joba orkiestratora jest niemal wyłącznie uruchamianie innych jobów. Takie rozwiązanie jest przydatne wtedy, gdy chcemy jednocześnie uruchomić wiele testów. Załóżmy, że mamy 10 różnych jobów z testami naszego systemu. Każdy z tych jobów testuje inną funkcjonalność. Są to długotrwałe testy E2E, które chcemy uruchamiać w trybie nocnym. W takim przypadku możemy stworzyć joba orkiestratora który:

  1. o określonej godzinie wyzwoli uruchomienie wszystkich jobów z testami aplikacji
  2. zbierze wyniki tych testów i wygeneruje zbiorczy raport
zrównoleglony jenkins pipeline

Aby to zrealizować, wystarczy użyć zrównoleglonych kroków. Zastosowanie wait: true spowoduje, że nasz job orkiestrator będzie oczekiwał na zakończenie się wywołanych jobów, zanim przejdzie do następnego kroku. Aby wygenerować raport, wystarczy w jobach testowych zapisać wyniki jako artefakt. Następnie należy pobrać je w jobie orkiestratorze i zaaplikować je z użyciem wtyczki JUnit. Poniższy listing przedstawia sposób na jednoczesne wyzwolenie wielu jobów.

stage ('Run tests') {
  steps {
    parallel (
      gui: {
        build wait: true, job: 'gui-tests'
      },
      users: {
        build wait: true, job: 'users-tests'
      },
      orders: {
        build wait: true, job: 'orders-tests'
      },
      failFast: false)
  }
}

4. Orkiestracja z użyciem repozytorium binariów

Ostatni sposób różni się od pozostałych sposobem wyzwolenia jobów. Polega on na użyciu w tym celu repozytorium binariów np. Artifactory. Jest to serwis, dzięki któremu możemy przechowywać binarne wersje aplikacji lub zbudowane obrazy dockera. W tym podejściu możemy wyróżnić dwa rodzaje jobów:

  1. Pierwszy z nich, gdy pojawi się nowy kod w repozytorium, buduje aplikację i umieszcza ją w Artifactory.
  2. Drugi cyklicznie odpytuje Artifactory czy nie pojawiła się nowa wersja aplikacji. Jeśli tak to job uruchamia się i realizuje swoje zadanie, np. przeprowadza testy.
potok z wykorzystaniem serwera Artifactory

Do realizacji tego scenariusza wymagana jest wtyczka Artifactory do Jenkinsa. Na stronie dokumentacji możemy zapoznać się ze sposobem konfigurowania wyzwalacza (triggera) budowania. Jedyne co musimy ustawić to adres URL serwera Artifactory, ścieżkę w repozytorium, którą chcemy obserwować i określić, co jaki czas Jenkins ma odpytywać serwer o zmiany.

Jakie są plusy tego rozwiązania? Joby w naszym potoku nie są w żaden sposób powiązane. Nie ma tutaj bezpośredniego wyzwalania jobów jeden przez drugi. Dzięki temu możemy dowolnie zmieniać ich nazwy i parametry bez obawy o błędy w przepływie. Tak długo jak kolejne wersje aplikacji będą umieszczane pod tym samym adresem w Artifactory, joby budujące i testowe nie muszą nawet „wiedzieć” o swoim istnieniu.

Podsumowanie

W tym artykule przedstawiłem Ci sposoby na łączenie ze sobą jobów. Wiesz już, że możesz umieścić cały potok w jednym jobie. Możesz też rozbić go na kilka zadań i wyzwalać w odpowiedniej kolejności. Do wyzwoleń możesz użyć polecenia build job lub wykorzystać serwer binariów Artifactory. Możesz też połączyć przedstawione tutaj metody i stworzyć taki potok, który najbardziej odpowiada potrzebom Twojego projektu. Decyzja należy do Ciebie 🙂 Swoje pomysły możesz opisać w komentarzu.

Chcesz dowiedzieć się więcej na temat wtyczek, dzięki którym wykorzystasz na maksa możliwości Jenkinsa? Zachęcam Cię do pobrania mojego darmowego e-booka na ten temat. Poznaj wtyczki, które ułatwią Ci codzienną pracę z Jenkinsem.


Subscribe
Powiadom o
guest
2 Comments
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments
Kuba
Kuba
2 lat temu

Czy sposób opisany w punkcie 4 daje się rozszerzyć na monitorowanie wielu ścieżek w repozytorium Artifactory? Myślę tu o sytuacji, w której pipeline budujący dany komponent powinien się uruchamiać za każdym razem, gdy pojawią się nowe wersje jego zależności (np. wykorzystywanych bibliotek).

2
0
Would love your thoughts, please comment.x