Czy lepiej mieć któryś z nich
- Deterministyczny zestaw testów, który powoduje, że te same testy się powiodły
- Niedeterministyczny zestaw testów, który potencjalnie może obejmować więcej przypadków
?
Przykład: piszesz pakiet testowy, aby przetestować funkcjonalność kontrolera w aplikacji MVC. Kontroler wymaga danych aplikacji z bazy danych jako danych wejściowych podczas testu. Można to zrobić na dwa sposoby:
- Na stałe wpisujesz, które wiersze z testowej bazy danych są wybrane jako dane wejściowe (np. Wiersz 10 i 412)
- Używasz generatora liczb losowych do pseudolosowego wybierania danych z bazy danych (dwa wiersze wybrane przez generator liczb losowych)
Pierwszy jest deterministyczny: każde uruchomienie testu dla tej samej wersji kodu powinno dać ten sam wynik. Drugi jest niedeterministyczny: przy każdym uruchomieniu zestawu testów można uzyskać inny wynik. Losowo wybrane dane mogą jednak lepiej reprezentować przypadki krawędzi danych. Czy może to lepiej symulować użytkownika karmiącego nasze kontrolery nieprzewidywalnymi danymi?
Jakie są powody, aby wybierać między sobą?
Odpowiedzi:
Gdy każde uruchomienie pakietu testowego daje możliwość uzyskania innego wyniku, test jest prawie całkowicie bezwartościowy - gdy pakiet pokazuje błąd, masz dużą szansę, że nie będziesz w stanie go odtworzyć, a gdy spróbujesz naprawić błąd, nie można sprawdzić, czy poprawka działa.
Jeśli więc uważasz, że do generowania danych testowych potrzebujesz jakiegoś generatora liczb losowych, upewnij się, że zawsze inicjujesz generator z tym samym ziarnem, lub utrwalasz dane z testu losowego w pliku przed wprowadzeniem go do testu, dzięki czemu możesz ponownie uruchomić test z dokładnie tymi samymi danymi z wcześniejszego uruchomienia. W ten sposób możesz przekształcić dowolny test niedeterministyczny w test deterministyczny.
EDYCJA: Używanie generatora liczb losowych do wybierania niektórych danych testowych jest czasami IMHO oznaką zbyt lenistwa przy wybieraniu dobrych danych testowych. Zamiast rzucać 100 000 losowo wybranych wartości testowych i mieć nadzieję, że to wystarczy, aby przypadkowo odkryć wszystkie poważne błędy, lepiej użyj swojego mózgu, wybierz 10 do 20 „interesujących” przypadków i wykorzystaj je do zestawu testów. Spowoduje to nie tylko lepszą jakość testów, ale także znacznie wyższą wydajność pakietu.
źródło
Zarówno deterministyczne, jak i niedeterministyczne mają swoje miejsce
Podzielę je w następujący sposób:
Testy jednostkowe.
Powinny one mieć za każdym razem deterministyczne, powtarzalne testy z dokładnie tymi samymi danymi. Testy jednostkowe towarzyszą określonym, izolowanym sekcjom kodu i powinny je testować w sposób deterministyczny.
Testy wytrzymałościowe i wejściowe.
Mogą stosować podejście niedeterministyczne z następującymi zastrzeżeniami:
źródło
Obie.
Testy deterministyczne i niedeterministyczne mają różne przypadki użycia i różne wartości w zależności od pakietu. Ogólnie niedeterministyczny nie może zapewnić takiej samej precyzji jak test deterministyczny, który powoli przerodził się w „testowanie niedeterministyczne nie przynosi żadnej wartości”. To nieprawda. Mogą być mniej precyzyjne, ale mogą być również znacznie szersze, co ma swoje zalety.
Weźmy przykład: piszesz funkcję, która sortuje listę liczb całkowitych. Jakie przydatne byłyby niektóre deterministyczne testy jednostkowe?
NaN
,INT_MIN
iINT_MAX
A to tylko funkcja sortowania! Jasne, możesz argumentować, że niektóre z nich są niepotrzebne lub że niektóre z nich można wykluczyć za pomocą nieformalnego uzasadnienia. Ale jesteśmy inżynierami i widzieliśmy nieformalne rozumowanie wysadzone w naszą twarz. Wiemy, że nie jesteśmy wystarczająco inteligentni, aby całkowicie zrozumieć systemy, które zbudowaliśmy, lub w pełni utrzymać złożoność w naszych głowach. Dlatego w pierwszej kolejności piszemy testy. Dodanie niedeterministycznych testów mówi po prostu, że niekoniecznie jesteśmy wystarczająco bystrzy, aby z góry poznać wszystkie dobre testy. Rzucając pół losowe dane do swojej funkcji, znacznie łatwiej znajdziesz przypadek, który przegapiłeś.
Oczywiście nie wyklucza to również testów deterministycznych. Testy niedeterministyczne pomagają znaleźć błędy w ogromnych obszarach programu. Jednak po znalezieniu błędów potrzebujesz powtarzalnego sposobu, aby pokazać, że je naprawiłeś. Więc:
Zauważ, że oznacza to wiele solidnych porad na temat testów jednostkowych niekoniecznie dotyczy testów niedeterministycznych. Na przykład, że muszą być szybkie. Niskopoziomowe testy właściwości powinny być szybkie, ale niedeterministyczny test, taki jak „symuluj użytkownika losowo klikającego przyciski w witrynie i upewnij się, że nigdy nie pojawi się błąd 500”, powinien sprzyjać kompleksowości zamiast szybkości. Po prostu wykonaj taki test, który uruchamia się niezależnie od procesu kompilacji, aby nie spowalniał rozwoju. Na przykład uruchom go na swoim prywatnym polu testowym.
źródło
Naprawdę nie chcesz deterministycznego kontra niedeterministycznego.
To, czego możesz chcieć, to „zawsze taki sam” vs. „nie zawsze taki sam”.
Na przykład, możesz mieć numer kompilacji, który zwiększa się z każdą kompilacją, a gdy chcesz uzyskać liczby losowe, inicjujesz generator liczb losowych z numerem kompilacji jako ziarnem. Więc przy każdej kompilacji wykonujesz testy z różnymi wartościami, co daje większe szanse na znalezienie błędów.
Ale po znalezieniu błędu wystarczy uruchomić test z tym samym numerem kompilacji i jest on odtwarzalny.
źródło