Czy powielony kod jest bardziej tolerowany w testach jednostkowych?

Zniszczyłem kilka testów jednostkowych jakiś czas temu, kiedy przeszedłem i zrefakturowałem je, aby były bardziej suche--intencja każdego testu nie była już jasna. Wydaje się, że istnieje kompromis między czytelnością testów i ich konserwacją. Jeśli zostawię powielony kod w testach jednostkowych, będą one bardziej czytelne, ale jeśli zmienię SUT, będę musiał wyśledzić i zmienić każdą kopię zduplikowanego kodu.

Czy zgadzasz się, że ten kompromis istnieje? Jeśli tak, to czy wolisz twoje testy mają być czytelne, czy możliwe do utrzymania?

Author: Daryl Spitzer, 2008-09-25

11 answers

Zduplikowany kod jest zapachem w kodzie testu jednostkowego tak samo jak w innym kodzie. Jeśli zdublowałeś kod w testach, trudniej jest refaktorować kod implementacji, ponieważ masz nieproporcjonalną liczbę testów do aktualizacji. Testy powinny pomóc ci refaktorować z pewnością, a nie być dużym obciążeniem, które utrudnia pracę nad testowanym kodem.

Jeśli duplikacja jest ustawiona, rozważ większe wykorzystanie metody setUp lub dostarczenie większej (lub większej elastyczne) metody tworzenia .

Jeśli duplikacja jest w kodzie manipulującym SUT, zadaj sobie pytanie, dlaczego wiele tak zwanych "testów jednostkowych" wykonuje dokładnie tę samą funkcjonalność.

Jeśli duplikacja jest w twierdzeniach, to być może potrzebujesz własnych twierdzeń . Na przykład, jeśli wiele testów ma ciąg twierdzeń, takich jak:

assertEqual('Joe', person.getFirstName())
assertEqual('Bloggs', person.getLastName())
assertEqual(23, person.getAge())

Być może potrzebujesz jednej metody assertPersonEqual, aby móc pisać assertPersonEqual(Person('Joe', 'Bloggs', 23), person). (A może po prostu potrzeba przeciążenia operatora równości na Person.)

Jak już wspomniałeś, ważne jest, aby kod testowy był czytelny. W szczególności ważne jest, aby intencja testu była jasna. Uważam, że jeśli wiele testów wygląda w większości tak samo, (np. trzy czwarte wierszy to samo lub praktycznie to samo) trudno jest dostrzec i rozpoznać znaczące różnice bez uważnego czytania i porównywania ich. Dlatego uważam, że refaktoryzacja w celu usunięcia duplikacji pomaga czytelność, ponieważ każda linia każdej metody badania jest bezpośrednio związana z celem badania. Jest to o wiele bardziej pomocne dla czytelnika niż losowa kombinacja linii, które są bezpośrednio istotne, i linii, które są tylko kotłem.

To powiedziawszy, czasami testy wykonują złożone sytuacje, które są podobne, ale nadal znacząco różne, i trudno jest znaleźć dobry sposób, aby zmniejszyć powielanie. Używaj zdrowego rozsądku: jeśli uważasz, że testy są czytelne i sprawiają, że ich intencja jasne, i jesteś zadowolony z Być może trzeba zaktualizować więcej niż teoretycznie minimalną liczbę testów podczas refaktoryzacji kodu wywoływanego przez testy, a następnie zaakceptować niedoskonałość i przejść do czegoś bardziej produktywnego. Zawsze możesz wrócić i refaktorować testy później,gdy natchnienie uderzy!

 55
Author: spiv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-28 04:39:40

Czytelność jest ważniejsza w testach. Jeśli test się nie powiedzie, chcesz, aby problem był oczywisty. Programista nie powinien przedzierać się przez wiele mocno uwzględnionych kodów testowych, aby dokładnie określić, co się nie udało. Nie chcesz, aby Twój kod testowy stał się tak złożony, że musisz napisać unit-test-tests.

Jednak wyeliminowanie duplikacji jest zazwyczaj dobrą rzeczą, o ile nic nie zasłania, a wyeliminowanie duplikacji w testach może prowadzić do lepszego API. Just upewnij się, że nie przekroczysz punktu malejących zwrotów.

 145
Author: Kristopher Johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-04 00:11:21

Kod implementacji i testy to różne zwierzęta, a Zasady faktoringu stosują się do nich inaczej.

Zduplikowany kod lub struktura jest zawsze zapachem w kodzie implementacji. Kiedy zaczniesz mieć boilerplate w implementacji, musisz zmienić swoje abstrakcje.

Z drugiej strony, kod testowy musi utrzymywać poziom duplikacji. Powielanie w kodzie testowym osiąga dwa cele:

  • trzymanie testów odsprzęgniętych. Nadmierne sprzężenie testowe może utrudnić zmianę jeden nieudany test, który wymaga aktualizacji, ponieważ kontrakt się zmienił.
  • utrzymywanie znaczenia testów w izolacji. Gdy pojedynczy test zawodzi, musi być dość proste, aby dowiedzieć się dokładnie, co to jest testowanie.

Mam tendencję do ignorowania trywialnego powielania w kodzie testowym, o ile każda metoda testowa pozostaje krótsza niż około 20 linii. Lubię, gdy rytm setup-run-verify jest widoczny w metodach testowych.

Gdy duplikacja skrada się w części "verify" z testów często korzystne jest zdefiniowanie niestandardowych metod twierdzenia. Oczywiście metody te muszą nadal testować jasno określoną relację, która może być widoczna w nazwie metody: assertPegFitsInHole - > good, assertPegIsGood - > bad.

Gdy metody testowe stają się długie i powtarzalne, czasami uważam, że przydatne jest zdefiniowanie szablonów testów wypełniających puste pola, które przyjmują kilka parametrów. Następnie rzeczywiste metody testowe są zredukowane do wywołania metody szablonowej z odpowiednimi parametrami.

Jak na wiele z rzeczy w programowaniu i testowaniu, nie ma jasnej odpowiedzi. Musisz wyrobić sobie smak, a najlepszym sposobem na to jest popełnianie błędów.

 36
Author: ddaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 21:31:10

Można zredukować powtarzanie za pomocą kilku różnych smaków metod testowych .

Jestem bardziej tolerancyjny na powtarzanie w kodzie testowym niż w kodzie produkcyjnym, ale czasami mnie to frustruje. Kiedy zmieniasz projekt klasy i musisz wrócić i dostosować 10 różnych metod testowania, wszystkie wykonują te same kroki konfiguracji, jest to frustrujące.

 7
Author: Don Kirkby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 21:17:47

Zgadzam się. Handel istnieje, ale jest inny w różnych miejscach.

Jestem bardziej skłonny do refakturowania zduplikowanego kodu do Ustawienia stanu. Ale mniej prawdopodobne, aby refakturować część testu, która faktycznie ćwiczy kod. To powiedziawszy, jeśli ćwiczenie kodu zawsze zajmuje kilka linijek kodu, to mogę pomyśleć, że jest to zapach i refaktor rzeczywisty kod testowany. A to poprawi czytelność i konserwację zarówno kodu, jak i testów.

 6
Author: stucampbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 20:30:07

Jay Fields ukuł zdanie, że "DSLs powinny być wilgotne, a NIE suche", gdzie DAMP oznacza opisowe i znaczące zwroty . Myślę, że to samo dotyczy również testów. Oczywiście zbyt duże powielanie jest złe. Ale usuwanie duplikacji za wszelką cenę jest jeszcze gorsze. Testy powinny działać jako specyfikacje ujawniające intencje. Jeśli na przykład podasz tę samą funkcję pod kilkoma różnymi kątami, należy spodziewać się pewnej ilości powielania.

 4
Author: Jörg W Mittag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-02 00:11:14

Kocham rspec z tego powodu:

MA 2 rzeczy do pomocy -

  • Wspólne grupy przykładowe do testowania wspólnych zachowań.
    możesz zdefiniować zestaw testów, a następnie włączyć go do rzeczywistych testów.

  • Zagnieżdżone konteksty.
    możesz zasadniczo mieć metodę "setup" i "teardown" dla określonego podzbioru testów, a nie tylko każdego z nich w klasie.

Im szybciej. Net / Java / inne frameworki testowe przyjmą te metody, tym lepiej (albo możesz użyć IronRuby lub JRuby do napisania testów, co osobiście uważam za lepszą opcję)

 3
Author: Orion Edwards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 00:11:02

Wydaje mi się, że nie ma związku między bardziej duplikowanym i czytelnym kodem. Myślę, że Twój kod testowy powinien być tak dobry jak twój inny kod. Kod nie powtarzający się jest bardziej czytelny niż duplikowany, gdy jest dobrze wykonany.

 2
Author: Paco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 20:26:47

Idealnie, testy jednostkowe nie powinny się zbytnio zmieniać po ich napisaniu, więc skłaniałbym się ku czytelności.

Aby testy jednostkowe były tak dyskretne, jak to możliwe, pomaga również skupić się na konkretnych funkcjach, które są kierowane.

Mając to na uwadze, staram się ponownie używać pewnych fragmentów kodu, których używam w kółko, takich jak kod konfiguracyjny, który jest dokładnie taki sam w zestawie testów.

 2
Author: 17 of 26,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 20:29:04

"przeformułowano je, aby były bardziej suche-intencja każdego testu nie była już jasna"

Wygląda na to, że miałeś problemy z refaktoryzacją. Zgaduję, ale jeśli skończy się mniej jasno, czy to nie znaczy, że masz jeszcze więcej pracy do zrobienia, aby mieć dość eleganckie testy, które są całkowicie jasne?

Dlatego testy są podklasą UnitTest -- dzięki czemu można zaprojektować dobre zestawy testów, które są poprawne, łatwe do zweryfikowania i przejrzyste.

W dawnych czasach my miał narzędzia testowe, które używały różnych języków programowania. Trudno było (lub niemożliwe) zaprojektować przyjemne, łatwe w obsłudze testy.

Masz pełną moc -- jakiegokolwiek języka używasz -- Python, Java, C# -- więc używaj tego języka dobrze. Możesz uzyskać dobrze wyglądający kod testowy, który jest jasny i nie jest zbyt zbędny. Nie ma kompromisu.

 2
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 00:03:29

Uważam, że kod testowy wymaga podobnego poziomu inżynierii, który normalnie byłby stosowany do kodu produkcyjnego. Na pewno mogą być argumenty przemawiające za czytelnością i zgadzam się, że to ważne.

Z mojego doświadczenia wynika jednak, że dobrze przemyślane testy są łatwiejsze do odczytania i zrozumienia. Jeśli jest 5 testów, które każdy wygląda tak samo, z wyjątkiem jednej zmiennej, która się zmieniła i twierdzenia na końcu, może być bardzo trudno znaleźć to, co ten pojedynczy różni item is. Podobnie, jeśli jest uwzględniona tak, że widoczna jest tylko zmienna, która się zmienia i twierdzenie, to łatwo jest natychmiast zorientować się, co robi test.

Znalezienie odpowiedniego poziomu abstrakcji podczas testowania może być trudne i uważam, że warto to zrobić.

 1
Author: Kevin London,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-02 22:16:56