Zarówno twierdzenia, jak i testy jednostkowe służą jako dokumentacja bazy kodu i sposób wykrywania błędów. Główne różnice polegają na tym, że funkcja działa jako kontrola poczytalności i widzi rzeczywiste dane wejściowe, podczas gdy testy jednostkowe działają na określonych symulowanych danych wejściowych i są testami na podstawie jednej dobrze zdefiniowanej „właściwej odpowiedzi”. Jakie są względne zalety stosowania twierdzeń w porównaniu z testami jednostkowymi jako głównego sposobu weryfikacji poprawności? Jak myślisz, co powinno zostać podkreślone mocniej?
testing
unit-testing
assertions
dsimcha
źródło
źródło
:-)
Odpowiedzi:
Aserty są przydatne do informowania o wewnętrznym stanie programu . Na przykład, że twoje struktury danych mają prawidłowy stan, np. Że
Time
struktura danych nie przechowuje wartości25:61:61
. Warunki sprawdzane przez stwierdzenia to:Warunki wstępne, które gwarantują, że dzwoniący dotrzyma umowy,
Warunki dodatkowe, które gwarantują, że odbiorca dotrzymuje kontraktu, oraz
Niezmienniki, które zapewniają, że struktura danych zawsze ma pewną właściwość po powrocie funkcji. Niezmiennik jest warunkiem, który jest warunkiem wstępnym i wtórnym.
Testy jednostkowe są przydatne, aby poinformować Cię o zewnętrznym zachowaniu modułu . Możesz
Stack
mieć spójny stan popush()
wywołaniu metody, ale jeśli rozmiar stosu nie wzrośnie o trzy po wywołaniu trzykrotnie, to jest to błąd. (Na przykład trywialny przypadek, w którym niepoprawnapush()
implementacja sprawdza tylko twierdzenia i kończy działanie).Ściśle mówiąc, główna różnica między asertami a testami jednostkowymi polega na tym, że testy jednostkowe zawierają dane testowe (wartości umożliwiające uruchomienie programu), podczas gdy twierdzenia nie. Oznacza to, że możesz wykonać testy jednostkowe automatycznie, podczas gdy nie możesz powiedzieć tego samego o twierdzeniach. Na potrzeby tej dyskusji założyłem, że mówisz o wykonywaniu programu w kontekście testów funkcji wyższego rzędu (które wykonują cały program i nie sterują modułami jak testy jednostkowe). Jeśli nie mówimy o automatycznych testach funkcji jako sposobie „zobaczenia rzeczywistych danych wejściowych”, to oczywiście wartość leży w automatyzacji, a zatem testy jednostkowe by wygrały. Jeśli mówisz o tym w kontekście (automatycznych) testów funkcji, zobacz poniżej.
Testowane elementy mogą się pokrywać. Na przykład
Stack
warunek końcowy może faktycznie twierdzić, że rozmiar stosu wzrasta o jeden. Są jednak granice tego, co można wykonać w tym stwierdzeniu: czy powinno to również sprawdzić, czy element górny jest właśnie dodany?W obu przypadkach celem jest poprawa jakości. W przypadku testów jednostkowych celem jest znalezienie błędów. W przypadku stwierdzeń celem jest ułatwienie debugowania poprzez obserwowanie niepoprawnych stanów programu natychmiast po ich wystąpieniu.
Zauważ, że żadna technika nie weryfikuje poprawności. W rzeczywistości, jeśli przeprowadzisz testy jednostkowe w celu sprawdzenia, czy program jest poprawny, prawdopodobnie opracujesz nieciekawy test, o którym wiesz, że zadziała. To efekt psychologiczny: zrobisz wszystko, aby osiągnąć swój cel. Jeśli Twoim celem jest znalezienie błędów, twoje działania to odzwierciedlą.
Oba są ważne i mają swoje własne cele.
[Jako ostatnia uwaga na temat twierdzeń: Aby uzyskać jak największą wartość, musisz używać ich we wszystkich krytycznych punktach programu, a nie kilku kluczowych funkcjach. W przeciwnym razie pierwotne źródło problemu mogło zostać zamaskowane i trudne do wykrycia bez wielu godzin debugowania.]
źródło
Mówiąc o asercjach, pamiętaj, że można je wyłączyć jednym naciśnięciem przycisku.
Przykład bardzo złego stwierdzenia:
Dlaczego to takie złe? Ponieważ sprawdzanie błędów nie jest wykonywane, jeśli to twierdzenie zostanie pominięte z powodu zdefiniowania czegoś takiego jak NDEBUG.
Test jednostkowy (prawdopodobnie) po prostu spowodowałby błąd w powyższym kodzie. Jasne, że wykonał swoją pracę, mówiąc ci, że coś poszło nie tak, czy to zrobiło? Jakie jest prawdopodobieństwo
malloc()
niepowodzenia w teście?Asercje służą do debugowania, gdy programista musi sugerować, że żadne „normalne” zdarzenie nie spowodowałoby uruchomienia asercji.
malloc()
upadek jest rzeczywiście normalnym wydarzeniem, dlatego nigdy nie należy go twierdzić.Istnieje wiele innych przypadków, w których stosowane są twierdzenia zamiast odpowiedniego postępowania z rzeczami, które mogą pójść nie tak. To dlatego twierdzenia cieszą się złą reputacją i dlaczego języki takie jak Go nie uwzględniają ich.
Testy jednostkowe mają na celu stwierdzenie, kiedy coś, co zmieniłeś, zepsuło coś innego. Zostały one zaprojektowane tak, aby uchronić Cię (w większości przypadków) przed przeglądaniem wszystkich funkcji programu (jednak testery są ważne w wersjach) za każdym razem, gdy tworzysz kompilację.
Naprawdę nie ma żadnej wyraźnej korelacji między nimi, poza tym, że obie mówią, że coś poszło nie tak. Pomyśl o asercie jako o punkcie przerwania w czymś, nad czym pracujesz, bez konieczności używania debuggera. Pomyśl o teście jednostkowym jako o czymś, co powie ci, jeśli złamałeś coś, nad czym nie pracujesz.
źródło
Oba narzędzia służą do poprawy ogólnej jakości budowanego systemu. Wiele zależy od używanego języka, rodzaju tworzonej aplikacji i miejsca, w którym najlepiej spędzić czas. Nie wspominając o tym, że masz na ten temat kilka szkół.
Na początek, jeśli używasz języka bez
assert
słowa kluczowego, nie możesz używać asercji (przynajmniej nie tak, jak tutaj mówimy). Przez długi czas Java nie miałaassert
słowa kluczowego, a wiele języków nadal nie ma. Testy jednostkowe stają się wtedy znacznie ważniejsze. W niektórych językach asercje są uruchamiane tylko po ustawieniu flagi (ponownie tutaj w Javie). Gdy zabezpieczenia nie zawsze są dostępne, nie jest to bardzo przydatna funkcja.Istnieje szkoła myślenia, która mówi, że „twierdząc” o czymś, równie dobrze możesz napisać
if
/throw
znaczący blok wyjątków. Ten proces myślowy pochodzi z wielu twierdzeń umieszczonych na początku metody, aby upewnić się, że wszystkie wartości mieszczą się w granicach. Testowanie warunków wstępnych jest bardzo ważną częścią posiadania oczekiwanego warunku końcowego.Testy jednostkowe to dodatkowy kod, który należy napisać i utrzymywać. Dla wielu jest to wadą. Jednak przy obecnych uprawach ram testów jednostkowych istnieje możliwość wygenerowania większej liczby warunków testowych przy stosunkowo niewielkim kodzie. Testy sparametryzowane i „teorie” przeprowadzą ten sam test z dużą liczbą próbek danych, które mogą wykryć niektóre trudne do znalezienia błędy.
Osobiście uważam, że dzięki testom jednostkowym mam większy przebieg niż twierdzenie, ale dzieje się tak z powodu platform, które rozwijam przez większość czasu (Java / C #). Inne języki mają bardziej niezawodną obsługę asercji, a nawet „Design by Contract” (patrz poniżej), aby zapewnić jeszcze więcej gwarancji. Gdybym pracował z jednym z tych języków, mógłbym użyć DBC bardziej niż testowania jednostkowego.
http://en.wikipedia.org/wiki/Design_by_contract#Languages_with_native_support
źródło