Ustal, co musisz przetestować, a co możesz wykluczyć.
W poprzednim artykule omówiliśmy podstawy testów i to, co powinny zawierać. Z tego artykułu dowiesz się więcej o tworzeniu przypadków testowych z technicznego punktu widzenia. Znajdziesz tu szczegółowe informacje o tym, co powinno być uwzględnione w każdym teście, a czego należy unikać. Otrzymasz odpowiedzi na odwieczne pytania „Co testować?” i „Czego nie testować?”.
Ogólne wskazówki i wzorce
Warto pamiętać, że konkretne wzorce i punkty są kluczowe niezależnie od tego, czy przeprowadzasz testy jednostek, integracji czy kompleksowe. Te zasady można i należy stosować w przypadku obu rodzajów testów, więc stanowią one dobry punkt wyjścia.
Trzymaj się prostych rozwiązań
Podczas pisania testów należy pamiętać, aby były jak najprostsze. Ważne jest, aby wziąć pod uwagę pojemność mózgu. Główny kod produkcyjny zajmuje dużo miejsca, przez co nie ma zbyt wiele miejsca na dodatkowe złożoność. Dotyczy to zwłaszcza testowania.
Jeśli masz mniej miejsca, możesz się bardziej zrelaksować podczas testowania. Dlatego ważne jest, aby w testach dążyć do prostoty. W fakcie sprawdzone metody testowania kodu JavaScript autorstwa Yoni Goldberg podkreślają znaczenie złotej zasady – test powinien być pomocnikiem, a nie skomplikowaną formułą matematyczną. Inaczej mówiąc, już na pierwszy rzut oka powinno być wiadomo, jaki jest cel testu.
W przypadku wszystkich testów, niezależnie od ich złożoności, należy dążyć do uproszczenia. Im bardziej złożony test, tym ważniejsze jest jego uproszczenie. Jednym ze sposobów na to jest stosowanie testów płaskich, które są jak najbardziej uproszczone i sprawdzają tylko to, co jest niezbędne. Oznacza to, że każdy test powinien zawierać tylko 1 przypadek testowy, który powinien dotyczyć testowania jednej konkretnej funkcji.
Pomyśl o tym w ten sposób: czytając test, który nie zadziałał, powinno być łatwo zidentyfikować, co poszło nie tak. Dlatego ważne jest, aby testy były proste i łatwe do zrozumienia. Dzięki temu możesz szybko wykrywać i rozwiązywać problemy, gdy się pojawią.
Testowanie najważniejszych aspektów
Płaski interfejs testu zachęca do skupienia się na istotnych elementach. Pamiętaj, że nie musisz tworzyć testów tylko po to, aby zwiększyć zasięg. Testy powinny zawsze służyć określonemu celowi.
Nie testuj szczegółów implementacji
Jednym z częstych problemów podczas testowania jest to, że testy są często projektowane tak, aby sprawdzać szczegóły implementacji, np. użycie selektorów w komponentach lub testy kompleksowe. Szczegóły implementacji dotyczą elementów, których użytkownicy kodu zwykle nie używają, nie widzą ani nie wiedzą o nich. Może to prowadzić do 2 głównych problemów w testach: fałszywie negatywnych i fałszywie pozytywnych.
Fałszywie ujemne wyniki występują, gdy test się nie powiedzie, mimo że testowany kod jest prawidłowy. Może się to zdarzyć, gdy szczegóły implementacji ulegną zmianie z powodu refaktoryzacji kodu aplikacji. Z drugiej strony, wyniki fałszywie pozytywne występują, gdy test jest pozytywny, mimo że testowany kod jest nieprawidłowy.
Jednym z rozwiązań tego problemu jest uwzględnienie różnych typów użytkowników. Użytkownicy i programiści mogą mieć różne podejście i w różny sposób korzystać z kodu. Podczas planowania testów należy wziąć pod uwagę, co użytkownicy będą widzieć lub z czym będą wchodzić w interakcje, i uwzględnić to w testach zamiast szczegółów implementacji.
Na przykład wybór selektorów, które są mniej podatne na zmiany, może zwiększyć niezawodność testów: atrybuty danych zamiast selektorów arkusza CSS. Więcej informacji znajdziesz w artykule Kent C. zapoznaj się z artykułem Doddsa na ten temat lub bądź na bieżąco – wkrótce opublikujemy kolejny artykuł na ten temat.
Mocking: Don't lose control
Mockowanie to ogólna koncepcja używana w testach jednostkowych, a czasem także w testach integracyjnych. Polega ono na tworzeniu fałszywych danych lub komponentów, aby symulować zależności, które mają pełną kontrolę nad aplikacją. Umożliwia to testowanie w odizolowanym środowisku.
Używanie w testach obiektów testowych może zwiększyć przewidywalność, rozdzielenie problemów i wydajność. Jeśli chcesz przeprowadzić test, który wymaga udziału człowieka (np. weryfikacji paszportu), musisz go ukryć, używając fałszywego dokumentu. Z tych wszystkich powodów warto rozważyć użycie mockupów.
Jednocześnie symulacje mogą wpływać na dokładność testu, ponieważ są to symulacje, a nie rzeczywiste wrażenia użytkownika. Dlatego musisz zachować ostrożność podczas używania mocków i stubów.
Czy w przypadku testów kompleksowych należy tworzyć modele danych?
Zasadniczo nie. Jednak mockowanie może czasami uratować życie, więc nie wykluczajmy go całkowicie.
Wyobraź sobie, że piszesz test funkcji, która korzysta z usługi zewnętrznego dostawcy płatności. Użytkownik jest w ich środowisku piaskownicy, co oznacza, że nie są przeprowadzane żadne transakcje. Piaskownica nie działa prawidłowo, co powoduje niepowodzenie testów. Musi to zrobić dostawca płatności. Możesz tylko poczekać, aż usługodawca rozwiąże problem.
W takim przypadku korzystniejsze może być zmniejszenie zależności od usług, nad którymi nie masz kontroli. W przypadku testów integracyjnych i kompleksowych należy jednak ostrożnie stosować metodę mockowania, ponieważ zmniejsza ona poziom ufności testów.
Szczegóły testu: zalecenia i ograniczenia
Co zawiera test? Czy są jakieś różnice między typami testów? Przyjrzyjmy się bliżej kilku konkretnym aspektom dostosowanym do głównych typów testów.
Co należy do dobrego testu jednostkowego?
Idealny i skuteczny test jednostkowy powinien:
- Skup się na konkretnych aspektach.
- działać niezależnie;
- Obejmują scenariusze na małą skalę.
- Używaj nazw opisowych.
- W stosownych przypadkach stosuj wzór AAA.
- Zapewnij kompleksowe testowanie.
Do ✅ | Nie ❌ |
---|---|
Testy powinny być jak najmniejsze. Testuj tylko jedną rzecz na każdy przypadek testowy. | pisać testy obejmujące duże jednostki, |
Zawsze izoluj testy i symuluj elementy, których potrzebujesz, a które znajdują się poza Twoją jednostką. | zawierać inne komponenty lub usługi; |
Testy powinny być niezależne. | Użyj wyników poprzednich testów lub udostępnij dane testowe. |
Obejmują różne scenariusze i ścieżki. | Ogranicz się do testów pozytywnych lub maksymalnie negatywnych. |
Używaj opisowych tytułów testów, aby od razu wiedzieć, o co chodzi. | Testowanie tylko według nazwy funkcji, która nie jest wystarczająco precyzyjna: testBuildFoo() lub testGetId() . |
Postaraj się o dobry zasięg testów kodu lub szerszy zakres przypadków testowych, zwłaszcza na tym etapie. | Testuj od każdej klasy do poziomu bazy danych (wejścia/wyjścia). |
Co należy do dobrego testu integracji?
Idealny test integracji spełnia też niektóre kryteria testów jednostkowych. Musisz jednak wziąć pod uwagę kilka dodatkowych kwestii. Dobry test integracji powinien:
- symulować interakcje między komponentami;
- Uwzględnij scenariusze z życia wzięte i użyj mocków lub stubów.
- Zastanów się nad wydajnością.
Do ✅ | Nie ❌ |
---|---|
Testowanie punktów integracji: sprawdź, czy po zintegrowaniu poszczególne jednostki działają prawidłowo. | Testuj poszczególne jednostki osobno – do tego właśnie służą testy jednostkowe. |
Testowanie scenariuszy rzeczywistych: używaj danych testowych pochodzących z danych rzeczywistych. | Używanie powtarzających się automatycznie generowanych danych testowych lub innych danych, które nie odzwierciedlają rzeczywistych przypadków użycia. |
Aby zachować kontrolę nad pełnym testem, używaj mocków i stubów w przypadku zewnętrznych zależności. | Tworzenie zależności od usług innych firm, np. żądań sieciowych do usług zewnętrznych. |
Przed każdym testem i po nim należy użyć procedury czyszczenia. | Nie używaj w testach środków czyszczących, ponieważ może to spowodować niepowodzenie testów lub wyniki fałszywie pozytywne z powodu braku odpowiedniej izolacji testów. |
Co należy do dobrego testu kompleksowego?
Kompleksowy test kompleksowy powinien:
- powielanie interakcji użytkowników;
- Obejmują one najważniejsze scenariusze.
- obejmują wiele warstw;
- Zarządzanie operacjami asynchronicznymi.
- Sprawdź wyniki.
- Uwzględniaj wydajność.
Do ✅ | Nie ❌ |
---|---|
Używaj skrótów obsługiwanych przez interfejs API. Więcej informacji | Używaj interakcji z interfejsem użytkownika na każdym kroku, w tym na haku beforeEach . |
Przed każdym testem należy użyć procedury czyszczenia. Pamiętaj, aby jeszcze bardziej zadbać o izolację testów niż w przypadku testów jednostkowych i testów integracyjnych, ponieważ w tym przypadku istnieje większe ryzyko wystąpienia efektów ubocznych. | zapomnienie o czyszczeniu po każdym teście. Jeśli nie usuniesz pozostałego stanu, danych lub efektów ubocznych, wpłyną one na inne testy wykonywane później. |
Traktuj testy kompleksowe jako testy systemowe. Oznacza to, że musisz przetestować cały pakiet aplikacji. | Testuj poszczególne jednostki osobno – do tego właśnie służą testy jednostkowe. |
W ramach testu używaj minimalnej ilości mocków lub nie używaj ich wcale. Zastanów się, czy chcesz zamockować zewnętrzne zależności. | Używaj mocków. |
Weź pod uwagę wydajność i obciążenie, na przykład nie testuj zbyt długo dużych scenariuszy w ramach tego samego testu. | Obsługa dużych procesów bez korzystania ze skrótów. |