Testy integracyjne - concurrency

0

Czy to dobra praktyka uruchamiać testy integracyjne na kilku wątkach równolegle?
No bo mamy sobie 1 instancję db na jakimś test containers, jakąś kolejkę typu rabbit albo kafka i puszczając równolegle testy jest duża szansa na randomowe failowania - np test A doda do kolejki i potem będzie chciał wyjąć a w międzyczasie test B wyjmie.
Jak sobie radzić w takich wypadkach?
Puszczać sekwencyjnie testy w 1 wątku czg jakieś @DirtiesContext?

4

Jeśli mówimy o prawdziwych testach integracyjnych/e2e to zakładanie, że rzeczy dzieją się sekwencyjnie i jednowatkowo (i moze jeszcze na pustym stanie z rollbackami czy truncate pomiedzy testami) nie odzwierciedla realnego wykorzystania aplikacji. Może wystarczy pisać testy tak, żeby zbiór danych na których operują był rozłączny z innym testami, a asercje opierać nie o stan po fakcie tylko deltę stanu?

W ogóle temat jest wg mnie nie na ten dział, to dotyczy testowania w ogóle.

2

Posługuj się UUID-ami w testach, to infra będzie mogła być współdzielona, a dane rozróżnione per test. @DirtiesContext używaj jako last resort - będziesz startował Dockery kilka razy.

3

Pamiętaj, że E2E powinny testować funkcjonalność, nie stan. Jeśli twoja aplikacja nie dopuszcza takiej sytuacji, w której użytkownik A i B pracują jednocześnie to nie należy odpalać ich równocześnie. Jeśli twoja aplikacja jednak dopuszcza taką sytuację, ale testy z sobą interferują - to być może coś nie tak jest z testami.

Przykładowo:

  1. Aplikacja, która wysyła alerty na podstawie zbiorczych danych - np. jeśli counter > 10 to wysyła maila z alarmem. Wtedy jeden test, który zwiększy counter o 11 nie może być wykonany równolegle z testem, który ten licznik zwiększa o 1.
  2. Natomiast jeśli masz np. typowy system bankowy i testujesz wpłatę (pierwszy test) i wypłatę (drugi test) to powinieneś po prostu sprawdzać, czy zlecenia zostały zaksięgowane, a ewentualną zgodność konta liczyć na podstawie listy transakcji pomiędzy wysyłką zlecenia i jego realizacją - lub po prostu porównać deltę z stanu sprzed realizacji i po realizacji.
0

@Charles_Ray: a jeśli u mnie w testach coś po prostu pcha do kolejki a potem assertuje używając pop()? Nie ma tu miejsca na uuid. i zaczyna się problem jak inny test mi coś dodatkowo wepcha albo ściągnie.

0

Dobre pytanie, moze jest jakas mozliwosc przygotowania infrastruktury pod testy - np. poslugiwanie sie jakims filtrem, naglowkiem, tworzenie kolejek lub partycji z unikalnym id, etc.

1

Jak system potrafi dzialac wielowatkowo to testy tez powinny. jak on sobie radzi w analogicznym case ?
Zastanow sie czy sie da inaczej. Ew w najgorszym wypadku czy musisz pchac wszystko do jednej i tej samej kolejki?

2

U mnie w projekcie odpalamy testy integracyjne w pełni równolegle na aplikacji Spring Bootowej z użyciem JUnit 5. Jeśli ktoś używa Spring Cloud Sleuth to można łatwo sprawić, że header który wysyłasz na endpoint Twojej aplikacji (jakieś wygenerowane correlation ID) będzie propagowany dalej przez KafkaTemplate i RestTemplate (te beany będą zinstrumentowane). Teraz jeśli używasz do mockowania zewnętrznych REST serwisów czegoś typu Wiremock, to tworząc mappingi możesz oczekiwać headera z correlation ID (przez co mappingi dla różnych testów będą rozłączne). Kafkę ogrywam w taki sposób, że mam w testach fasadę która enkapsuluje listenera podpiętego do wszystkich topiców - ściągając wiadomości rozdziela je po typie body i correlation ID obecnym w headerach (mam mapę Map<Tuple2<Type, CorrelationId>, Queue<Message>>)). Fasada udostępnia metodę w stylu kafkaFacade.pollNext(MyEvent.class) - nie muszę nigdzie podawać correlation ID bieżącego testu bo idę "na skróty" przez trzymanie "kontekstu" bieżącego testu (zawierającego correlation ID) jako ThreadLocal ustawiane na początku testu :)

Uważam że zrównoleglanie testów integracyjnych to gra warta świeczki i efekty potrafią być znakomite :)

1

Jeden rabin powie puszczać, drugi rabin powie nie puszczać…
Współbieżne testy na tej samej instancji bazy/kolejki kojarzą mi się z losowo padającymi buildami, gdzie zespół się poddaje z walką o zielony build i zaczyna ignorować mentalnie a czasem nawet zakomentowywuje testy. Potem projekt przejmuje teoria rozbitych okien.
Jakbym musiał uwspółbieżniać, to raczej na zasadzie modułów/komponentów, gdzie każdy moduł testowany jest w osobnym wątku i z niezależną bazą.

1

Ja uważam że trzeba sie zastanowić co testujemy. Jak testuje konkretną funkcje/zachowanie systemu, to nie ma sensu utrudniać sobie życia przez wprowadzanie dodatkowego szumu. Więc czyścisz sobie bazy i kolejki i wykonujesz tylko operacje związane z danym use-case.
Test współbieżności to moze być zupełnie osobny test, który np. pcha tysiąc eventow na raz na koniec sprawdza czy wszystkie zostały obsłużone.

0

@Shalom: nawet majac 2 testy jednowatkowe, moze dojsc do przeplotu, jesli odpalisz je rownolegle - jeden pobierze dane przeznaczone dla drugiego. Na jakims poziomie trzeba zadbac o separacje. Najlatwiej oczywiscie odpalac sekwencyjnie i czyscic po sobie dane.

1 użytkowników online, w tym zalogowanych: 0, gości: 1