Przestań używać cy.wait()
Hardcodowane timeouty nie są dobrym rozwiązaniem w Cypressie. Sprawdź lepsze sposoby!
Używanie cy.wait() w Cypressie jest wygodnym rozwiązaniem. Element, którego oczekujemy, pojawia się z opóźnieniem, więc po prostu odczekujemy określony czas i dopiero wtedy wykonujemy związane z nim czynności. Ale czy to dobre podejście? Niekoniecznie, bo przecież dany element może załadować się szybciej niż czas ustawiony w cy.wait() - a to sprawia, że nasze testy są niepotrzebnie wydłużane.
To może dotyczyć też oczekiwania na wczytanie wszystkich elementów na stronie. Pewnie wiecie o co mi chodzi i spotkaliście się z takim rozwiązaniem:
Timeout dla danego elementu
Jeśli decydujemy się na zwiększanie timeoutu, zdecydowanie polecam zmieniać wartość przy oczekiwaniu na konkretny element. Jest to bardzo proste:
Oczekiwanie na odpowiedź z API
Jeszcze lepiej, gdy możemy oczekiwać na odpowiedź z API konieczną do wygenerowania danych elementów. W takim przypadku świetnym rozwiązaniem jest skorzystanie z metody .intercept() i aliasów:
A może jednak cy.wait()?
Domyślny timeout oczekiwania na element
Zaczynamy od podejścia, którego... nie polecam 😅 Chodzi o zmianę domyślnego czasu oczekiwania Cypressowych komend na dostępność danego elementu strony. Komendy typu .get() czy .contains() domyślnie oczekują 4 sekundy na pojawienie się elementu w DOMie. Wartość można globalnie zmienić dla całego projektu w pliku cypress.config (z rozszerzeniem .ts lub .js w zależności od używanego języka) poprzez edycję defaultCommandTimeout.
Na pierwszy rzut wygląda to nieźle. Przykładowo - przedłużamy timeout do 10 sekund. Usuwamy sztywne .waity() i od teraz Cypress czeka maksymalnie 10 sekund na pojawienie się elementu. Jeśli element pojawi się szybciej, no to jest super, przechodzimy do kolejnych linii kodu. Ale co jeśli element nie pojawi się wcale? Musimy czekać 10 sekund na informację o nieudanym teście, czyli znowu niepotrzebnie przedłużamy cały proces. Idźmy więc dalej.
Nie ma to większego sensu i tylko przedłuża wykonywanie testów - nawet jeśli wszystkie elementy strony zostaną załadowane szybciej niż w 5 sekund, to w powyższym przykładzie Cypress i tak będzie czekał na wykonanie dalszych części kodu. A przy dużej liczbie testów, każdy taki .wait() ma kolosalny wpływ na ogólny czas wykonania testów automatycznych. Zamiast tego, Cypress oferuje kilka ciekawszych i przede wszystkim bardziej optymalnych rozwiązań.
W takim przypadku zwiększamy timeout tylko dla tego konkretnego (problematycznego) elementu na stronie. Nie przedłużamy timeoutów globalnie, a jedynie w wybranych przez nas miejscach. Dzięki temu ograniczamy wydłużanie zbiorczego czasu wykonania testów (wiem, wiem, uparłem się na ten temat, ale oszczędności czasu trzeba szukać wszędzie).
Nie mamy tu żadnego niepotrzebnego przedłużania testów. Dzięki .intercept() nasłuchujemy zasobu books, a w .wait() oczekujemy (dzięki aliasowi) na przetworzenie żądania. Dopiero po tym zabieramy się do pracy z konkretnymi elementami (oczywiście, powiązanymi z danym zasobem API).
"Ale ja muszę użyć tego waita!". To go użyj! 😛 Nie chodzi przecież o to, by przy każdym problemie katować się idealnym rozwiązaniem. Doskonale wiem, że czasami lepiej użyć .wait(500) niż spędzić kilka dni w poszukiwaniu rozwiązania na oszczędzenie pół sekundy. Pisanie testów automatycznych jest w praktyce zazwyczaj bardziej skomplikowane od powyższych przykładów. Pamiętajcie jednak, że często da się zastosować lepsze podejście niż sztywny .wait(). Podejdźcie więc do tego racjonalnie - korzystajcie z najlepszych praktyk w Cypressie, a raz na jakiś czas pozwólcie sobie na malutkiego waita (o ile sytuacja tego wymaga).
Dziękuję, że czytasz mojego bloga!
Masz jakieś pytania? Z chęcią odpowiem :)