Czy przydatne są metody testów jednostkowych, w których jedyną logiką są osłony?

12

Powiedz, że mam taką metodę:

public void OrderNewWidget(Widget widget)
{
   if ((widget.PartNumber > 0) && (widget.PartAvailable))
   {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

Mam kilka takich metod w moim kodzie (przednia połowa asynchronicznego wywołania usługi sieci Web).

Zastanawiam się, czy warto ich objąć testami jednostkowymi. Tak, tutaj jest logika, ale to tylko logika wartownicza. (Czyli upewniam się, że mam potrzebne rzeczy, zanim pozwolę na wywołanie usługi internetowej).

Część mnie mówi „pewnie, że możesz je przetestować w jednostce, ale nie jest to warte czasu” (jestem przy projekcie, który jest już opóźniony).

Ale druga strona mnie mówi, że jeśli ich nie przetestujesz, a ktoś zmieni Strażników, mogą wystąpić problemy.

Ale pierwsza część mnie mówi: jeśli ktoś zmieni strażników, to po prostu wykonujesz dla nich więcej pracy (ponieważ teraz oni muszą zmienić strażników i testy jednostkowe dla strażników).

Na przykład, jeśli moja usługa przyjmuje na siebie odpowiedzialność za sprawdzenie dostępności Widżetu, być może nie chcę już tego strażnika. Jeśli jest to test jednostkowy, muszę teraz zmienić dwa miejsca.

Widzę zalety i wady na dwa sposoby. Pomyślałem więc, że zapytam, co zrobili inni.

Vaccano
źródło
17
Nie robisz „więcej pracy” dla opiekunów. Jeśli zmienią logikę, muszą zmienić odpowiednie testy jednostkowe. Tak to działa. Nie widzę twoich wad: jeśli twój test jednostkowy nie wymagał zmiany, to nie testowałby niczego, prawda? Równie dobrze możesz zadać pytanie, czy testowanie jednostkowe jest w ogóle przydatne.
Andres F.,
9
To nie jest temat, ale zmieniłbym logikę, aby zgłosić wyjątek, jeśli numer części wynosi 0 lub mniej, lub jeśli część nie jest dostępna, ponieważ moim zdaniem błędem byłoby zezwolenie komuś na wywołanie tej metody za pomocą fałszywy widget, dyskretnie maskujący inny problem.
Matthew
2
@Matthew bardzo dobry punkt. Ta funkcja leży. Nazewnictwo mówi ci, że coś zamówisz. A potem tak się nie stanie, ale nigdy się nie dowiesz, chyba że zastosujesz taką samą logikę jak w środku, która narusza SUSZENIE. Innymi słowy: jeśli projekt zostanie zmieniony, aby był bardziej poprawny, to pytanie może nie zostałoby zadane w pierwszej kolejności.
stijn
2
but it is not worth the time" (I am on a project that is already behind schedule).Jesteśmy programistami. Jedynym harmonogramem jest to, kiedy nie żyjemy :)
wałek klonowy

Odpowiedzi:

26

Część mnie mówi „pewnie, że możesz je przetestować w jednostce, ale nie jest to warte czasu” (jestem przy projekcie, który jest już opóźniony).

To trzy bardzo krótkie testy. Spędziłeś tyle czasu, zadając sobie pytanie.

Ale druga strona mnie mówi, że jeśli ich nie przetestujesz, a ktoś zmieni Strażników, mogą wystąpić problemy.

Posłuchaj tej strony.

Ale pierwsza część mnie mówi: jeśli ktoś zmieni strażników, to po prostu wykonujesz dla nich więcej pracy (ponieważ teraz oni muszą zmienić strażników i testy jednostkowe dla strażników).

Jeśli twoim opiekunem jest orzech TDD, utrudniasz im to. Każda zmiana, którą dokonuję bez powiązanej zmiany lub dodania testów, powoduje, że muszę intensywnie myśleć. W rzeczywistości prawdopodobnie dodałbym testy, zanim zacznę wprowadzać zmiany.

Pierwsza część ciebie jest po prostu błędna. Poklep drugą część plecami i przestań o tym myśleć.

pdr
źródło
+1 za zwięzłość, mimo że napisałem też odpowiedź heh
Jimmy Hoffa
3
+1. Tak, jeśli wymagania się zmienią, niektóre testy będą musiały zostać dostosowane.
Olivier Jacot-Descombes
Chociaż podoba mi się to, co mówisz, mam wiele wystąpień tego rodzaju wywołań w moim kodzie (przednia połowa wywołania asynchronicznego). Więc to nie tylko 3 testy jednostkowe. Mimo to, jeśli jest to „właściwy” sposób, chcę je wykonać.
Vaccano
@Vaccano: Im więcej z nich musisz napisać, tym więcej logicznych ścieżek nie masz testów i tym bardziej konieczne jest ich napisanie.
pdr
9

Uprościłoby to testowanie jednostkowe, gdyby logika ochronna i faktyczne zamawianie były odrębnymi metodami.

W Widgetklasie

public bool IsReadyForOrdering { get { return PartNumber > 0 && PartAvailable; } }

lub równoważna metoda gdzie indziej

public bool IsWidgetReadyForOrdering(Widget widget)
{
    return widget.PartNumber > 0 && widget.PartAvailable;
}

Metoda zamówienia

public void OrderNewWidget(Widget widget)
{
   if (IsWidgetReadyForOrdering(widget)) {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

Teraz testowanie IsWidgetReadyForOrderingstało się łatwe. Nie myśl o tym dłużej. Sprawdź to!

Olivier Jacot-Descombes
źródło
1
O, logika stanowa we właściwości .. -1, która powinna być metodą i powinna przyjmować PartNumber, PartAvailable ze względu na jej prostotę. Zabezpiecz go, jeśli nie musi być częścią publicznego interfejsu API, ale nie jest własnością. Poza tym generalnie się nie zgadzam. Logika ochrony w metodzie jest całkowicie w porządku, a moim zdaniem lepiej, ponieważ jest to tak mała metoda, że ​​po prostu zanieczyszczasz klasę, aby zmniejszyć już małą metodę. W takim przypadku dodaj go do klasy, tylko jeśli jest to powtarzalna logika.
Jimmy Hoffa
1
Po pierwsze, to nie odpowiada na pytanie. Po drugie, to nieprawda. Tak czy inaczej, musisz napisać trzy testy. Po trzecie, niepotrzebnie naraża szczegóły implementacji na wywołanie kodu.
pdr
8
@JimmyHoffa: gdzie widzisz logikę stanową w tej właściwości? W rzeczywistości przykład pokazuje, jak oddzielić logikę zmieniającą stan (OrderNewWidget) od logiki niestatystycznej (ReadyForOrdering). I jestem głęboko przekonany, że wyodrębnienie nawet tych małych funkcji poprawi kod, a nie pogorszy go, jak sam twierdzisz. Więc +1.
Doc Brown
2
Metoda OrderNewWidgetprawdopodobnie należy do innej klasy Widget, ponieważ ma Widgetargument. Ponieważ metoda nie ma wartości zwracanej, testowanie nie jest oczywiste. Będziesz musiał wstrzyknąć WigdetOrderingService-mock, który śledzi OrderNewWidgetAsyncpołączenie.
Olivier Jacot-Descombes
2
@ JimmyHoffa: w rzeczywistości twoja definicja „bezstanowy” oznacza „statyczny” w języku C #. Zatem mówisz, że „właściwości nie powinny mieć dostępu do stanu obiektu”. Ale nawet głupi getters uzyskują dostęp do zmiennych stanu, co oznaczałoby „zapisywanie tylko właściwości statycznych” - co nie wydaje się mieć większego sensu.
Doc Brown
6

Jeśli nie masz czasu w harmonogramie testów jednostkowych, ale masz czas przeznaczony na solidne korzystanie z QA, zapytaj, czy możesz ukraść część tego czasu na napisanie testów jednostkowych, czy też możesz poświęcić część okresu QA robienie testów jednostkowych, a może po prostu radzenie sobie z kodem, który nie jest testowany jednostkowo. Niestety harmonogramy, które są nieruchome, zmuszają cię do ustępstw lub pracy na śmierć, generalnie sugeruję pierwszą opcję, ponieważ druga spowoduje, że nie będziesz w stanie wspierać / utrzymanie systemu poprawnie przez cały okres jego ważności.

To powiedziawszy, na twoje ogólne pytanie dotyczące testowania wypowiedzi strażników; Tak! Absolutnie przetestuj strażników! Są to ważne elementy zachowania tej metody, nie będzie chciał się dowiedzieć, że ktoś coś robi źle zrozumiany bug-fix i usunięto swoich strażników lub zmienił &&się ||prawda? Testy jednostkowe upewnią się, że a) rzeczywiście masz logikę na swoich strażnikach i b) nikt później nie złamie tej logiki, nie otrzymując skargi, gdy przeprowadzą testy jednostkowe, mówiąc im, że z jakiegoś powodu tak powinno być.

Jimmy Hoffa
źródło
0

Powyżej znajduje się kilka doskonałych odpowiedzi, a ich uwagi są bardzo ważne. Ale wydaje się, że pominięto to, że masz kompleksowy zestaw testów jednostkowych, które czytają jak bardzo szczegółową specyfikację kodu. Jeśli pominiesz sprawdzanie poprawności tylko dlatego, że kod jest tak łatwy, że trudno zrozumieć, jak może się nie udać, brakuje części specyfikacji. Gdybym wszedł do zespołu, w którym te testy zostały pominięte, zakładałbym, że twoja usługa nie potwierdziła swoich argumentów.

Jules
źródło
-5

Kod to kod. Powinieneś spróbować uzyskać 100% zasięgu podczas testowania. Gdyby to nie było ważne, nie byłoby go.

SuperUser
źródło