Jestem świeżo po studiach i zaczynam studia gdzieś w przyszłym tygodniu. Widzieliśmy testy jednostkowe, ale trochę ich nie używaliśmy; i wszyscy o nich mówią, więc pomyślałem, że może powinienem coś zrobić.
Problem polega na tym, że nie wiem, co przetestować. Czy powinienem przetestować wspólny przypadek? Sprawa krawędzi? Skąd mam wiedzieć, że funkcja jest odpowiednio objęta?
Zawsze mam okropne przeczucie, że chociaż test udowodni, że funkcja działa w określonym przypadku, to zupełnie bezużyteczne jest udowodnienie, że funkcja działa, kropka.
unit-testing
testing
test-coverage
skradać się
źródło
źródło
Odpowiedzi:
Moja osobista filozofia była zatem następująca:
źródło
Spośród mnóstwa odpowiedzi dotychczas nikt nie poruszył podziału na równoważności i analizy wartości granicznych , co jest istotnym czynnikiem w odpowiedzi na pytanie. Wszystkie pozostałe odpowiedzi, choć użyteczne, są jakościowe, ale możliwe jest - i lepiej - być tutaj ilościowe. @fishtoaster zapewnia pewne konkretne wytyczne, wystarczy zajrzeć pod zakres kwantyfikacji testowej, ale podział równoważności i analiza wartości brzegowych pozwalają nam lepiej.
W partycjonowaniu równoważności dzielisz zestaw wszystkich możliwych danych wejściowych na grupy na podstawie oczekiwanych wyników. Wszelkie dane wejściowe z jednej grupy przyniosą równoważne wyniki, dlatego takie grupy nazywane są klasami równoważności . (Uwaga: równoważne wyniki nie oznaczają identycznych wyników).
Jako prosty przykład rozważ program, który powinien przekształcać małe znaki ASCII na wielkie litery. Inne postacie powinny przejść transformację tożsamości, tzn. Pozostać niezmienione. Oto jeden z możliwych podziałów na klasy równoważności:
Ostatnia kolumna podaje liczbę przypadków testowych, jeśli wyliczysz je wszystkie. Technicznie, zgodnie z regułą @ fishtoaster 1, uwzględniałbyś 52 przypadki testowe - wszystkie te dla dwóch pierwszych wierszy podanych powyżej należą do „wspólnego przypadku”. Reguła 2 @ fishtoaster dodałaby także część lub całość z wierszy 3 i 4 powyżej. Ale przy testowaniu partycjonowania równoważności wystarczy jeden przypadek testowy w każdej klasie równoważności. Jeśli wybierzesz „a”, „g” lub „w”, testujesz tę samą ścieżkę kodu. Tak więc masz w sumie 4 przypadki testowe zamiast 52+.
Analiza wartości brzegowych zaleca nieznaczne udoskonalenie: zasadniczo sugeruje, że nie każdy element klasy równoważności jest, cóż, równoważny. Oznacza to, że wartości graniczne należy również uważać za warte osobnego przypadku testowego. (Jednym z łatwych uzasadnień tego jest niesławny błąd „jeden po drugim” ). Zatem dla każdej klasy równoważności można mieć 3 wejścia testowe. Patrząc na domenę wejściową powyżej - i z pewną wiedzą na temat wartości ASCII - mogę wymyślić te dane wejściowe dla przypadków testowych:
(Gdy tylko otrzymasz więcej niż 3 wartości graniczne, które sugerują, że możesz chcieć ponownie przemyśleć swoje pierwotne nakreślenia klas równoważności, ale było to na tyle proste, że nie wróciłem do ich poprawiania.) Zatem analiza wartości granicznych prowadzi nas do 17 przypadków testowych - z dużą pewnością pełnego pokrycia - w porównaniu do 128 przypadków testowych do przeprowadzenia wyczerpujących testów. (Nie wspominając już o tym, że kombinatoryka dyktuje, że wyczerpujące testy są po prostu niemożliwe do zastosowania w rzeczywistych aplikacjach!)
źródło
Prawdopodobnie moja opinia nie jest zbyt popularna. Ale sugeruję, abyś był oszczędny dzięki testom jednostkowym. Jeśli masz zbyt wiele testów jednostkowych, możesz łatwo spędzić połowę czasu lub dłużej na utrzymywaniu testów zamiast na faktycznym kodowaniu.
Proponuję napisać testy na rzeczy, które mają złe przeczucia w jelitach lub rzeczy, które są bardzo ważne i / lub elementarne. Testy jednostkowe IMHO nie zastępują dobrej inżynierii i defensywnego kodowania. Obecnie pracuję nad projektem, który jest mniej lub bardziej bezużyteczny. Jest naprawdę stabilny, ale stanowi problem dla refaktora. W rzeczywistości nikt nie dotknął tego kodu w ciągu jednego roku, a stos oprogramowania, na którym jest oparty, ma 4 lata. Dlaczego? Ponieważ jest zaśmiecony testami jednostkowymi, a ściślej: testami jednostkowymi i automatycznymi testami integracji. (Słyszałeś kiedyś o ogórkach itp.) A oto najlepsza część: to (jeszcze) bezużyteczne oprogramowanie zostało opracowane przez firmę, której pracownicy są pionierami na scenie programistycznej opartej na testach. :RE
Więc moja sugestia to:
Zacznij pisać testy po opracowaniu podstawowego szkieletu, w przeciwnym razie refaktoryzacja może być bolesna. Jako programista, który opracowuje dla innych, nigdy nie spełniasz wymagań od samego początku.
Upewnij się, że testy jednostkowe można wykonać szybko. Jeśli masz testy integracyjne (takie jak ogórek), możesz je potrwać dłużej. Ale długotrwałe testy nie są zabawne, uwierz mi. (Ludzie zapominają o wszystkich powodach, dla których C ++ stał się mniej popularny ...)
Pozostaw to TDD ekspertom TDD.
I tak, czasami koncentrujesz się na przypadkach skrajnych, a czasem na typowych przypadkach, w zależności od tego, gdzie oczekujesz nieoczekiwanego. Chociaż jeśli zawsze oczekujesz nieoczekiwanego, powinieneś naprawdę przemyśleć swój tok pracy i dyscyplinę. ;-)
źródło
Leave this TDD stuff to the TDD-experts
.Jeśli najpierw testujesz za pomocą Test Driven Development, wtedy Twój zasięg wzrośnie w zakresie 90% lub wyższym, ponieważ nie dodasz funkcjonalności bez uprzedniego napisania dla niej nieudanego testu jednostkowego.
Jeśli dodajesz testy po fakcie, nie mogę zalecić, abyś dostał kopię Efektywnej pracy ze starszym kodem autorstwa Michaela Feathersa i przyjrzał się niektórym technikom zarówno dodawania testów do kodu, jak i sposobów refaktoryzacji kodu aby był bardziej testowalny.
źródło
The problem is, I don't know _what_ to test
Jeśli zaczniesz następujący rozwój testów Driven praktyk, będą one rodzaj poprowadzi Cię przez proces i wiedząc, co testować przyjdzie naturalnie. Niektóre miejsca na początek:
Testy są najważniejsze
Nigdy nie pisz kodu przed napisaniem testów. Wyjaśnienie patrz Red-Green-Refactor-Powtórz .
Napisz testy regresji
Ilekroć napotkasz błąd, napisz testcase i upewnij się, że się nie powiedzie . O ile nie możesz odtworzyć błędu za pomocą nieudanej próby, tak naprawdę go nie znalazłeś.
Powtórz refaktor czerwony-zielony-zielony
Czerwony : Zacznij od napisania najbardziej podstawowego testu dla zachowania, które próbujesz wdrożyć. Pomyśl o tym kroku jak o napisaniu przykładowego kodu, który używa klasy lub funkcji, nad którą pracujesz. Upewnij się, że kompiluje / nie ma błędów składniowych i że zawiedzie . To powinno być oczywiste: nie napisałeś żadnego kodu, więc musi się nie powieść, prawda? Ważną rzeczą do nauczenia się tutaj jest to, że dopóki przynajmniej nie zobaczysz, że test się nie powiedzie, nigdy nie możesz być pewien, że jeśli się powiedzie, zrobi to z powodu czegoś, co zrobiłeś z jakiegoś fałszywego powodu.
Zielony : Napisz najprostszy i najgłupszy kod, który tak naprawdę sprawia, że test się powiedzie. Nie próbuj być mądry. Nawet jeśli widzisz, że istnieje oczywisty przypadek krawędzi, ale test bierze pod uwagę, nie pisz kodu, aby go obsłużyć (ale nie zapomnij o przypadku krawędzi: będziesz go potrzebować później). Chodzi o to, że każdy kawałek kodu yo pisać, każdy
if
, każdytry: ... except: ...
powinien być uzasadniony przypadek testowy. Kod nie musi być elegancki, szybki ani zoptymalizowany. Po prostu chcesz, aby test się zdał.Refaktoryzacja : Wyczyść kod, popraw nazwy metod. Sprawdź, czy test nadal mija. Być optymistą. Uruchom test ponownie.
Powtórz : Pamiętasz przypadek na krawędzi, którego test nie obejmował, prawda? A więc teraz jest wielki moment. Napisz skrzynkę testową, która obejmie tę sytuację, zobacz, jak się nie udaje, napisz kod, zobacz, jak to się skończy, refaktoryzuj.
Przetestuj swój kod
Pracujesz nad jakimś konkretnym fragmentem kodu i właśnie to chcesz przetestować. Oznacza to, że nie powinieneś testować funkcji biblioteki, biblioteki standardowej ani kompilatora. Staraj się także unikać testowania „świata”. Obejmuje to: wywoływanie zewnętrznych interfejsów API sieci Web, niektóre czynności wymagające intensywnej pracy z bazami danych itp. Ilekroć możesz spróbować wyszydzić go (stwórz obiekt zgodny z tym samym interfejsem, ale zwróci statyczne, predefiniowane dane).
źródło
W przypadku testów jednostkowych zacznij od przetestowania, czy robi to, do czego został przeznaczony. To powinien być pierwszy przypadek, który napiszesz. Jeśli częścią projektu jest „powinno się wprowadzić wyjątek, jeśli zdasz śmieci”, przetestuj to również, ponieważ jest to część projektu.
Zacznij od tego. Gdy zdobędziesz doświadczenie w wykonywaniu tego najbardziej podstawowego testowania, zaczniesz się uczyć, czy to wystarcza, i zobaczysz inne aspekty kodu, które wymagają testowania.
źródło
Podstawową odpowiedzią jest „przetestować wszystko, co może się zepsuć” .
Co jest zbyt łatwe do złamania? Pola danych, niedoświadczone akcesoria do nieruchomości i podobne górne płyty. Wszystko inne prawdopodobnie implementuje pewną możliwą do zidentyfikowania część wymagania i może skorzystać z testowania.
Oczywiście Twój przebieg i praktyki w twoim środowisku pracy mogą się różnić.
źródło