Przeglądałem dokumenty phpunit i natrafiłem na następujący cytat:
Zawsze możesz napisać więcej testów. Jednak szybko przekonasz się, że tylko ułamek testów, które możesz sobie wyobrazić, są w rzeczywistości przydatne. To, co chcesz, to pisać testy, które zawiodą, nawet jeśli uważasz, że powinny one działać, lub testy, które zakończą się powodzeniem, nawet jeśli uważasz, że powinny zawieść. Innym sposobem myślenia o tym jest stosunek kosztów do korzyści. Chcesz napisać testy, które zwrócą ci informacje. - Bogata gamma
Zastanawiałem się. W jaki sposób określasz, co sprawia, że test jednostkowy jest bardziej przydatny niż inny, oprócz tego, co podano w cytacie na temat kosztów / korzyści. Jak decydujesz, dla którego fragmentu kodu tworzysz testy jednostkowe? Proszę o to, ponieważ inny z tych cytatów również powiedział:
Więc jeśli nie chodzi o testowanie, o co chodzi? Chodzi o to, aby dowiedzieć się, co próbujesz zrobić, zanim uciekniesz na wpół, aby spróbować. Piszesz specyfikację, która precyzuje mały aspekt zachowania w zwięzłej, jednoznacznej i wykonywalnej formie. To takie proste. Czy to oznacza, że piszesz testy? Nie. Oznacza to, że piszesz specyfikacje tego, co twój kod będzie musiał zrobić. Oznacza to, że z góry określasz zachowanie swojego kodu. Ale niewiele wcześniej. W rzeczywistości tuż przed napisaniem kodu najlepiej jest, ponieważ wtedy masz pod ręką tyle informacji, ile potrzebujesz. Podobnie jak dobrze zrobione TDD, pracujesz w małych krokach ... określając jeden mały aspekt zachowania na raz, a następnie wdrażając go. Kiedy zdasz sobie sprawę, że chodzi o określenie zachowania, a nie pisanie testów, twój punkt widzenia się zmienia. Nagle pomysł posiadania klasy testowej dla każdej klasy produkcyjnej jest absurdalnie ograniczający. Myśl o przetestowaniu każdej z twoich metod za pomocą własnej metody testowej (w relacji 1-1) będzie śmieszna. - Dave Astels
Ważną częścią tego jest
* A myśl o przetestowaniu każdej z twoich metod za pomocą własnej metody testowej (w relacji 1-1) będzie śmieszna. *
Jeśli więc utworzenie testu dla każdej metody jest „śmiechu warte”, to w jaki sposób / kiedy wybierasz, dla czego piszesz testy?
źródło
Odpowiedzi:
Ile testów na metodę?
Cóż, teoretycznym i wysoce niepraktycznym maksimum jest złożoność ścieżki N (załóżmy, że wszystkie testy obejmują różne sposoby w kodzie;)). Minimum to JEDEN !. Według metody publicznej , czyli nie testuje szczegółów implementacji, tylko zewnętrzne zachowania klasy (zwracają wartości i wywołują inne obiekty).
Cytujesz:
a następnie zapytaj:
Ale myślę, że źle zrozumiałeś tutaj autora:
Idea posiadania
one test method
perone method in the class to test
jest tym, co autor nazywa „śmiesznym”.(Dla mnie przynajmniej) Nie chodzi o „mniej”, chodzi o „więcej”
Pozwólcie, że sformułuję to tak, jakbym go rozumiał:
Myśl o przetestowaniu każdej z metod przy użyciu TYLKO JEDNEJ METODY (własnej metody testowej w relacji 1-1) będzie śmieszna.
Aby ponownie zacytować ofertę:
Kiedy ćwiczysz TDD, nie myślisz :
Mam metodę
calculateX($a, $b);
i potrzebuje testu,testCalculcateX
który przetestuje WSZYSTKO na temat tej metody.TDD mówi ci, aby pomyśleć o tym, JAK POWINIEN WIDZIĆ Twój kod :
Muszę obliczyć większą z dwóch wartości ( pierwszy przypadek testowy! ), Ale jeśli $ a jest mniejsze od zera, to powinien wygenerować błąd ( drugi przypadek testowy! ), A jeśli $ b jest mniejszy od zera, powinien .... ( trzeci przypadek testowy! ) i tak dalej.
Chcesz przetestować zachowania, a nie tylko pojedyncze metody bez kontekstu.
W ten sposób otrzymujesz zestaw testowy, który jest dokumentacją twojego kodu i NAPRAWDĘ wyjaśnia, co należy zrobić, a może nawet dlaczego :)
Jak decydujesz, dla którego fragmentu kodu tworzysz testy jednostkowe?
Cóż, wszystko, co kończy się w repozytorium lub gdziekolwiek w pobliżu produkcji, wymaga testu. Nie sądzę, żeby autor twoich cytatów nie zgodził się z tym, jak starałem się stwierdzić powyżej.
Jeśli nie masz testu, zmiana kodu staje się znacznie trudniejsza (droższa), zwłaszcza jeśli nie dokonujesz zmiany.
TDD jest sposobem na upewnienie się, że masz testy na WSZYSTKO, ale tak długo, jak PISUJESZ testy, wszystko jest w porządku. Zwykle pisanie ich tego samego dnia pomaga, ponieważ nie zamierzasz tego robić później, prawda? :)
Odpowiedź na komentarze:
Są trzy rzeczy, które te metody mogą wywołać:
Metody publiczne innych klas
Możemy wyśmiewać inne klasy, więc zdefiniowaliśmy tam stan. Kontrolujemy kontekst, więc nie stanowi to problemu.
* Metody chronione lub prywatne na tym samym *
Wszystko, co nie jest częścią publicznego interfejsu API klasy, zwykle nie jest testowane bezpośrednio.
Chcesz przetestować zachowanie, a nie implementację, a jeśli klasa robi wszystko, działa w jednej dużej publicznej metodzie lub w wielu mniejszych chronionych metodach, które wywoływane są implementacją . Chcesz móc ZMIENIĆ te chronione metody BEZ dotykania swoich testów. Ponieważ testy zostaną przerwane, jeśli zmiany w kodzie zmienią zachowanie! Właśnie po to są twoje testy, żeby ci powiedzieć, kiedy coś złamiesz :)
Metody publiczne w tej samej klasie
To się nie zdarza często, prawda? A jeśli tak jest w poniższym przykładzie, istnieje kilka sposobów radzenia sobie z tym:
To, że setery istnieją i nie są częścią podpisu metody wykonania, to inny temat;)
Możemy tutaj przetestować, czy wykonanie wykonuje wysadzenie, gdy ustawimy nieprawidłowe wartości. To
setBla
rzuca wyjątek, gdy przekazujesz ciąg, który można przetestować osobno, ale jeśli chcemy przetestować, czy te dwie dozwolone wartości (12 i 14) nie działają RAZEM (z jakiegokolwiek powodu) niż jeden przypadek testowy.Jeśli chcesz mieć „dobry” pakiet testowy, możesz, w php, może (!) Dodać
@covers Stuff::execute
adnotację, aby upewnić się, że generujesz pokrycie kodu tylko dla tej metody, a inne rzeczy, które są po prostu konfigurowane, muszą zostać przetestowane osobno (ponownie, jeśli chcesz tego).Chodzi o to, że może najpierw musisz stworzyć otaczający świat, ale powinieneś być w stanie napisać sensowne przypadki testowe, które zwykle obejmują tylko jedną lub dwie rzeczywiste funkcje (setery nie liczą się tutaj). Resztę można wykpić z eteru lub najpierw przetestować, a następnie polegać na niej (patrz
@depends
)* Uwaga: Pytanie zostało migrowane z SO i początkowo dotyczyło PHP / PHPUnit, dlatego przykładowy kod i referencje pochodzą ze świata php, myślę, że dotyczy to również innych języków, ponieważ phpunit nie różni się tak bardzo od innych xUnit ramy testowe.
źródło
Testy i testy jednostkowe to nie to samo. Testowanie jednostkowe jest bardzo ważnym i interesującym podzbiorem Testowania ogólnie. Twierdzę, że skupienie się na testowaniu jednostkowym skłania do myślenia o tego rodzaju testowaniu w sposób, który w pewien sposób jest sprzeczny z powyższymi cytatami.
Po pierwsze, jeśli podążamy za TDD, a nawet DTH (tj. Opracowujemy i testujemy w ścisłej harmonii), używamy testów, które piszemy, aby skupić się na poprawnym zaprojektowaniu. Myśląc o przypadkach narożnych i odpowiednio pisząc testy, unikamy błędów, więc w rzeczywistości piszemy test, który spodziewamy się zaliczenia (OK na początku TDD zawodzą, ale to tylko artefakt zamawiania, kiedy kod jest gotowy, oczekujemy, że przejdą, a większość tak, ponieważ myślałeś o kodzie.
Po drugie, testy jednostkowe naprawdę sprawdzają się, gdy dokonujemy refaktoryzacji. Zmieniamy naszą implementację, ale oczekujemy, że odpowiedzi pozostaną takie same - Test jednostkowy stanowi naszą ochronę przed zerwaniem umowy dotyczącej interfejsu. Po raz kolejny oczekujemy, że testy zakończą się pomyślnie.
Oznacza to, że dla naszego interfejsu publicznego, który prawdopodobnie jest stabilny, potrzebujemy wyraźnej identyfikowalności, abyśmy mogli zobaczyć, że każda metoda publiczna jest testowana.
Aby odpowiedzieć na Twoje wyraźne pytanie: Test jednostkowy interfejsu publicznego ma wartość.
edytowane w komentarzu w odpowiedzi:
Testujesz prywatne metody? Tak, powinniśmy, ale jeśli nie musimy czegoś testować, to właśnie tam pójdę na kompromis. W końcu, jeśli publiczne metody działają, to czy te błędy w prywatnych materiałach mogą być tak ważne? Pragmatycznie, rezygnacja ma miejsce w prywatnych sprawach, ciężko pracujesz, aby utrzymać swój publiczny interfejs, ale jeśli rzeczy, na których polegasz, mogą się zmienić. W pewnym momencie utrzymanie wewnętrznych testów może być dużym wysiłkiem. Czy ten wysiłek jest dobrze wykorzystany?
źródło
Testy jednostkowe powinny być częścią większej strategii testowania. Przestrzegam tych zasad, wybierając rodzaje testów do napisania i kiedy:
Skoncentruj się na pisaniu kompleksowych testów. Obejmujesz więcej kodu na test niż w testach jednostkowych, dzięki czemu zyskujesz więcej testowania za grosze. Spraw, by były to automatyczne sprawdzanie poprawności systemu jako całości.
Przejdź do pisania testów jednostkowych wokół modeli użytkowych o skomplikowanej logice. Testy jednostkowe są warte swojej wagi w sytuacjach, w których kompleksowe testy byłyby trudne do debugowania lub nieporęczne do napisania w celu zapewnienia odpowiedniego pokrycia kodu.
Poczekaj, aż testowany interfejs API będzie stabilny, aby napisać test dowolnego typu. Chcesz uniknąć konieczności refaktoryzacji zarówno implementacji, jak i testów.
Rob Ashton ma świetny artykuł na ten temat, z którego mocno zaczerpnąłem, aby sformułować powyższe zasady.
źródło
Zazwyczaj stosuję inne podejście do testów jednostkowych, które wydaje się działać dobrze. Zamiast myśleć o testach jednostkowych jako o „Testowaniu niektórych zachowań”, myślę o tym bardziej jako o „specyfikacji, której musi przestrzegać mój kod”. W ten sposób możesz w zasadzie zadeklarować, że obiekt powinien zachowywać się w określony sposób, a biorąc pod uwagę, że zakładasz, że gdzie indziej w twoim programie, możesz być całkiem pewien, że jest stosunkowo wolny od błędów.
Jeśli piszesz publiczny interfejs API, jest to niezwykle cenne. Jednak zawsze będziesz potrzebować dobrej dawki kompleksowych testów integracyjnych, ponieważ podejście do 100% pokrycia testów jednostkowych zwykle nie jest tego warte i będzie brakowało rzeczy, które większość osób uznałaby za „niesprawdzalne” metodami testów jednostkowych (kpiny, itp)
źródło