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 myśl o przetestowaniu każdej z twoich metod za pomocą własnej metody testowej (w relacji 1-1) będzie śmieszna. *
a następnie zapytaj:
Jeśli więc utworzenie testu dla każdej metody jest „śmiechu warte”, to w jaki sposób / kiedy wybierasz, dla czego piszesz testy?
Ale myślę, że źle zrozumiałeś tutaj autora:
Idea posiadania one test method
per one 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 zdasz sobie sprawę, że chodzi o określenie zachowania, a nie pisanie testów, twój punkt widzenia się zmienia.
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:
przyzwoita liczba metod nie może zostać przetestowana w określonym kontekście, ponieważ albo zależą, albo są zależne od innych metod
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:
$stuff = new Stuff();
$stuff->setBla(12);
$stuff->setFoo(14);
$stuff->execute();
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.