Testuję metodę, która ma wygenerować zbiór obiektów danych. Chcę sprawdzić, czy właściwości obiektów są ustawione poprawnie. Niektóre właściwości zostaną ustawione na to samo; inne zostaną ustawione na wartość zależną od ich pozycji w kolekcji. Naturalnym sposobem na to wydaje się być pętla. Jednak Roy Osherove zdecydowanie odradza stosowanie logiki w testach jednostkowych ( Art of Unit Testing , 178). On mówi:
Test zawierający logikę zwykle testuje więcej niż jedną rzecz na raz, co nie jest zalecane, ponieważ test jest mniej czytelny i bardziej delikatny. Ale logika testowa dodaje również złożoności, która może zawierać ukryty błąd.
Testy powinny być z reguły serią wywołań metod, bez przepływów kontrolnych, nawet
try-catch
z wywołaniami asertywnymi.
Jednak nie widzę nic złego w moim projekcie (jak inaczej wygenerujesz listę obiektów danych, których niektóre wartości zależą od tego, w jakiej kolejności są? - nie mogą dokładnie wygenerować i przetestować ich osobno). Czy w moim projekcie jest coś niesprzyjającego testom? A może zbyt sztywno poświęca się naukom Osherove? A może jest jakaś tajemna magiczna testowa jednostka, o której nie wiem, która omija ten problem? (Piszę w C # / VS2010 / NUnit, ale jeśli to możliwe, szukam odpowiedzi niezależnych od języka).
źródło
in
) jest konieczna, jeśli test brzmi: „Frob został pomyślnie dodany do istniejącej kolekcji”.toString()
kolekcję i porównuję z tym, co powinno być. Prosty i działa.Odpowiedzi:
TL; DR:
Pierwszą rzeczą do przetestowania jest nieprzydatność dogmatów. Lubię czytać The Way of Testivus, która wskazuje na pewne problemy z dogmatem w beztroski sposób.
Jeśli test musi być napisany w jakiś sposób, napisz go w ten sposób. Próba wymuszenia testu na jakimś wyidealizowanym układzie testu lub jego brak wcale nie jest dobrą rzeczą. Po dzisiejszym teście, który testuje, jest to lepsze niż „idealny” test później.
Wskażę też trochę na brzydkim teście:
Można to uznać za truizmy dla tych, którzy śledzą od dawna ... i po prostu zostają zakorzenione w sposobie myślenia i pisania testów. Dla osób, które nie były i próbują dojść do tego punktu, przypomnienia mogą być pomocne (nawet uważam, że ich ponowne czytanie pomaga mi uniknąć uwikłania się w dogmat).
Zastanów się nad tym, pisząc brzydki test, jeśli kod może wskazywać, że kod też próbuje zrobić zbyt wiele. Jeśli testowany kod jest zbyt skomplikowany, aby można go było poprawnie wykonać, pisząc prosty test, warto rozważyć podzielenie go na mniejsze części, które można przetestować za pomocą prostszych testów. Nie należy pisać testu jednostkowego, który robi wszystko (może to nie być test jednostkowy ). Podobnie jak „boskie obiekty” są złe, „boskie testy jednostkowe” również są złe i powinny być wskazówką, aby wrócić i ponownie spojrzeć na kod.
Państwo powinno być w stanie wykonywać cały kod z rozsądnym pokrycia przez takich testów prostych. Testy, które wykonują więcej testów od końca do końca, zajmujące się większymi pytaniami („Mam ten obiekt, przeniesiony do xml, wysłany do usługi sieci Web, zgodnie z regułami, wycofałem się i wycofany”) jest doskonałym testem - ale na pewno nie jest to test jednostkowy (i należy do dziedziny testowania integracji - nawet jeśli ma wyśmiewane usługi, które wywołuje i niestandardowe w bazach pamięci w celu przeprowadzenia testów). Może nadal używać frameworka XUnit do testowania, ale framework testujący nie czyni go testem jednostkowym.
źródło
Dodam nową odpowiedź, ponieważ moja perspektywa jest inna niż wtedy, gdy napisałem oryginalne pytanie i odpowiedź; połączenie ich w jedno nie ma sensu.
Powiedziałem w pierwotnym pytaniu
To tam popełniłem błąd. Po zrobieniu programowania funkcjonalnego przez ostatni rok, teraz zdaję sobie sprawę, że potrzebowałem tylko operacji zbierania z akumulatorem. Następnie mógłbym napisać moją funkcję jako funkcję czystą, która działała na jednej rzeczy i użyć jakiejś standardowej funkcji biblioteki, aby zastosować ją do kolekcji.
Tak więc moja nowa odpowiedź brzmi: użyj funkcjonalnych technik programowania , a przez większość czasu unikniesz tego problemu. Możesz pisać swoje funkcje, aby działać na pojedynczych rzeczach i stosować je tylko do kolekcji rzeczy w ostatniej chwili. Ale jeśli są czyste, możesz je przetestować bez odwoływania się do kolekcji.
Aby uzyskać bardziej złożoną logikę, skorzystaj z testów opartych na właściwościach . Gdy mają logikę, powinna być mniejsza i odwrotna do logiki testowanego kodu, a każdy test weryfikuje znacznie więcej niż jednostkowy test oparty na wielkości liter, że niewielka ilość logiki jest tego warta.
Przede wszystkim zawsze polegaj na swoich typach . Zdobądź najsilniejsze typy, jakie możesz, i wykorzystaj je na swoją korzyść. Zmniejszy to liczbę testów, które musisz napisać w pierwszej kolejności.
źródło
Nie próbuj testować zbyt wielu rzeczy na raz. Każda z właściwości każdego obiektu danych w kolekcji jest za duża na jeden test. Zamiast tego polecam:
Wykonanie tego w ten sposób sprawia, że testy są na tyle małe, że pomijanie pętli nie wydaje się bolesne. Przykład C # / Unit, podany testowany sposób
ICollection<Foo> generateFoos(uint numberOfFoos)
:Jeśli jesteś przyzwyczajony do paradygmatu „testu płaskich jednostek” (brak zagnieżdżonych struktur / logiki), testy te wydają się dość czyste. W ten sposób unika się logiki w testach, identyfikując pierwotny problem jako próbę przetestowania zbyt wielu właściwości jednocześnie, zamiast braku pętli.
źródło