Testy integracyjne, różna odpowiedź z serwisu zewnętrznego.

0

Cześć.

Mam taki problem mianowicie: w projekcie mamy zestaw testów które uderzają do serwisu zewnętrznego. Są one zrobione po to aby w przypadku gdy dostawca API coś zmieni w np. modelu/jsonie, abyśmy mieli informację że coś się zmieniło. Wiadomo jak to z komunikacją w IT jest. ;)

Problem jaki mam to taki że serwis w zależności od momentu wykonania requesta potrafi zwracać dwie różne informacje: ok lub in_progress i teraz moje pytanie brzmi: jak podejść do pisania testu, w chwili obecnej testy wyglądają mniej więcej tak:

@Test
public void test() {
	(...)
	String result = clientForExternal.send(myData);
	
	// tu się wywala bo jak za szybko ponownie uruchomię test
	// a serwis poprzedniego zapytania nie przetworzy 
    // to potrafi zwrócić 'in_progress'
	assertEquals(result, "OK"); 
}

Dane wejściowe myData dla serwisu nie mogą być generowane. Pytanie jak to ugryźć? Dopisać asercje z or że spodziewam się potencjalnie dwóch wyników? Próbowałem drutować ze sleepem ale też, raz na 10 buildów coś się wywali.

Będę wdzięczny za sensowne pomysły i uwagi jak temat załatwić "po-bożemu". ;)

0

Awaitility i czekasz na spodziewany stan i ja bym tak robił w każdym teście żeby mieć pewność że "zresetowałeś" stan do sytuacji początkowej, więc robiłbym też Awaitility w jakimś After żeby mieć pewność że można bezpiecznie odpalać kolejny test.

0

@Shalom: No okej, czyli działałoby to tak że przed każdym uruchomieniem testu odpalałbym to Awaitility i czekał aż serwis zewnętrzny się zresetuje / przestanie zwracać in_progres ?

0

Tak, ale PO teście a nie PRZED testem. Innej mozliwości nie widzę, bo przecież jak tego nie zrobisz, to jaką masz pewność że kolejne in progress albo ok jest wynikiem aktualnego testu a nie pozostałością po poprzednim? Dobra praktyka to sprzątać po każdym teście. W innym wypadku są klasyczne kwiatki w stylu: zmieniliśmy kolejność testów i nagle zaczęły failować, bo okazuje się że niektóre testy korzystały z pozostałości po innym teście ;]

Sprzątanie przed testem to słaby pomysł, bo ktoś moze o tym zapomnieć albo nawet nie zdawać sobie sprawy.

0

@Shalom: Hmm sugeruje sprzątanie przed testem z tego względu że np. rozpatrz taką sytuację. Kolega z zespołu odpalił u siebie na localhoście ten sam zestaw testów co Ty a Ty uruchomiłeś je chwilę po nim (brzmi abstrakcyjnie ale się już tak zdarzało) i jemu te testy przeszły a u mnie na dzień dobry serwis zwraca już in_progress bo kolega chwilę wcześniej odpalił testy i serwis tego nie przetworzył. Jak sobie poradzić z sytuacją gdy ktoś inny z zespołu odpala testy?

0

@MrMadMatt: a nie ma jakiegos klucza zeby zapytanie traktowc jako unikalne? W rzeczywistym systemie chyba nie ma problemu ze dwoch klientow na raz cos pobiera?

0

@MrMadMatt średnio mi się to podoba, ale w takiej sytuacji może ma to sens. Niemniej to raczej dość dziwne żeby takie testy z remotowymi zależnościami ktoś odpalał "lokalnie". Lokalnie to bym się raczej jednak spodziewał odpalania z httpmockami a taki ciężki e2e dopiero na jakimś CI albo ewentualnie w specjalnym przypadku kiedy zewnętrzne API się zmieni i musicie coś poprawić w testach i ktoś lokalnie to robi.

0

@WhiteLightning: No właśnie w normalnym codziennym użytkowaniu aplikacji, obie zwrotki traktowane są jako poprawne w sensie ok i in_progress mapowane na jakiś tam komunikat w przeglądarce chyba. Stąd też wniosek taki że skoro oba komunikaty są okej z poziomu użytkowania i oba potwierdzają przepływ danych między nami a nimi to teoretycznie OR w asercji byłby ok ale jakoś mi to na wątrobie on nie leży. ;) Pytanie czy tak się robi?

@Shalom W projekcie jest na razie tak "lekko" że wszystkie ciężkie testy możesz odpalić na localhoście i raczej nie przepchnę zakazu odpalania e2e każdemu w zespole na lokalnej maszynie. ;)

0

Mały hint: socjologiczno - filozoficzny.
Proponuję nie nazywać tego testem. To jest monitoring.
Sprawdzasz działanie jakiegoś komponentu. Z testami ludzie mają wiele powiązanych skojarzeń, że powinny generalnie być odpalane na CI, że nie powinny się losowo wywalać itp. Uniknie się przez to niepotrzebnych dyskusji.

Oczywiście nic nie stoi na przeszkodzie, żeby użyć takich samych technologii takich jak do testów - to zupełnie normalne.
A co do przykładu - jeśli in_progress jest zupełnie normalne i nie ma powodu, żeby sprawdzać dlaczego in_progress to taki zrobiłbym warunek.
Jeśli jednak chcecie choć raz na jakiś czas zobaczyć OK - to wtedy zrobiłbym powtarzanie, oczekiwanie na OK. Takie coś może sobie trwać ( bo zakładam, że oczywiście nie macie tego w normalnym build pipeline odpalanego).

0

oba potwierdzają przepływ danych między nami a nimi to teoretycznie OR w asercji byłby ok

No niby jak byłby ok skoro nie masz pewności czy to twój test ten stan striggerował? o_O

W projekcie jest na razie tak "lekko" że wszystkie ciężkie testy możesz odpalić na localhoście i raczej nie przepchnę zakazu odpalania e2e każdemu w zespole na lokalnej maszynie.

Myślę że to raczej wyniki z braku innych testów a nie chęci odpalania e2e przez każdego developera ;)

0
Shalom napisał(a):

No niby jak byłby ok skoro nie masz pewności czy to twój test ten stan striggerował? o_O

Nie rozumiem co masz na myśli że nie będę wiedział czy się wykonał, jak nie dodam żadnego Awaita po testach i zdrutuje to tak:

@Test
public void test() {
    (...)
	// zwraca OK lub IN_PROGRESS
    String result = clientForExternal.send(myData);

	// coś w tym stylu, jak zwraca co innego to test się wywala
	assertThat(result).equals("OK").or("IN_PROGRESS");
}

To teoretycznie, kod ten spełnia swoją funkcje. Sprawdza przepływ między nimi a nami (np. że serializacja się nie wywaliła / nie zmienili JSONa) ale wygląda... ch*jowo. ;)

0

@MrMadMatt no właśnie myk polega na tym ze to wcale niczego nie sprawdza :D Równie dobrze result który dostałeś może wynikać z jakiegoś innego requestu, a ten twój request był błędny, ale został zignorowany bo było już in progress.
Await też niekoniecznie załatwi sprawę, bo nadal możecie lokalnie u siebie mieć jakieś race condition, dlatego sugerowałbym odpalanie czegoś takiego tylko z CI a lokalnie używać wiremocka.

0

Jak ten zewnętrzny serwis to inny zespół w tej samej organizacji to sprawdźcie contract testing.

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