Zduplikowany kod to zapach w kodzie testów jednostkowych, tak samo jak w innym kodzie. Jeśli masz zduplikowany kod w testach, trudniej jest zrefaktoryzować kod implementacji, ponieważ masz nieproporcjonalną liczbę testów do zaktualizowania. Testy powinny pomóc ci w pewnej refaktoryzacji, a nie być dużym obciążeniem, które utrudnia pracę nad testowanym kodem.
Jeśli powielanie jest w ustawieniach urządzenia, rozważ większe wykorzystanie tej setUp
metody lub zapewnienie większej (lub bardziej elastycznej) metody tworzenia .
Jeśli powielenie występuje w kodzie manipulującym SUT, zadaj sobie pytanie, dlaczego wiele tak zwanych testów „jednostkowych” wykonuje dokładnie tę samą funkcjonalność.
Jeśli duplikacja znajduje się w potwierdzeniach, być może potrzebujesz niektórych potwierdzeń niestandardowych . Na przykład, jeśli wiele testów ma ciąg stwierdzeń, takich jak:
assertEqual('Joe', person.getFirstName())
assertEqual('Bloggs', person.getLastName())
assertEqual(23, person.getAge())
W takim razie może potrzebujesz jednej assertPersonEqual
metody, aby móc pisać assertPersonEqual(Person('Joe', 'Bloggs', 23), person)
. (A może po prostu musisz przeciążyć operator równości Person
).
Jak wspomniałeś, ważne jest, aby kod testowy był czytelny. W szczególności ważne jest, aby cel testu był jasny. Uważam, że jeśli wiele testów wygląda w większości tak samo (np. Trzy czwarte wierszy jest takich samych lub praktycznie takich samych), trudno jest dostrzec i rozpoznać istotne różnice bez uważnego ich przeczytania i porównania. Dlatego uważam, że refaktoryzacja w celu usunięcia duplikatów poprawia czytelność, ponieważ każda linia każdej metody testowej jest bezpośrednio związana z celem testu. Jest to o wiele bardziej pomocne dla czytelnika niż przypadkowa kombinacja wierszy, które są bezpośrednio istotne, i wierszy, które są tylko szablonami.
To powiedziawszy, czasami testy sprawdzają złożone sytuacje, które są podobne, ale wciąż znacząco różne, i trudno jest znaleźć dobry sposób na ograniczenie powielania. Kieruj się zdrowym rozsądkiem: jeśli uważasz, że testy są czytelne i jasno określają ich intencje, i czujesz się komfortowo, jeśli podczas refaktoryzacji kodu wywołanego przez testy musisz zaktualizować więcej niż teoretycznie minimalną liczbę testów, zaakceptuj niedoskonałość i przenieś na coś bardziej produktywnego. Zawsze możesz wrócić i zmodyfikować testy później, gdy nadejdzie inspiracja!
Czytelność jest ważniejsza w przypadku testów. Jeśli test się nie powiedzie, chcesz, aby problem był oczywisty. Deweloper nie powinien musieć przebrnąć przez wiele mocno podzielonego na czynniki kodu kodu testowego, aby dokładnie określić, co się nie powiodło. Nie chcesz, aby Twój kod testowy stał się tak złożony, że musisz pisać testy jednostkowe.
Jednak wyeliminowanie duplikacji jest zwykle dobrą rzeczą, o ile niczego nie przesłania, a wyeliminowanie duplikacji w testach może prowadzić do lepszego interfejsu API. Tylko upewnij się, że nie przekroczysz punktu malejących zwrotów.
źródło
Kod i testy implementacyjne to różne zwierzęta, a zasady faktoringu mają do nich różne zastosowanie.
Powielony kod lub struktura jest zawsze zapachem w kodzie implementacji. Kiedy zaczniesz wdrażać schemat standardowy, musisz zrewidować swoje abstrakcje.
Z drugiej strony, kod testowy musi zachowywać poziom powielania. Duplikacja w kodzie testowym ma dwa cele:
Zwykle ignoruję trywialne powielanie w kodzie testowym, o ile każda metoda testowa jest krótsza niż około 20 linii. Lubię, gdy rytm konfiguracja-uruchomienie-weryfikacja jest widoczny w metodach testowych.
Kiedy powielanie pojawia się w części testów „weryfikującej”, często korzystne jest zdefiniowanie niestandardowych metod potwierdzania. Oczywiście metody te muszą nadal testować jasno określoną zależność, która może być uwidoczniona w nazwie metody:
assertPegFitsInHole
-> dobra,assertPegIsGood
-> zła.Kiedy metody testowe stają się długie i powtarzalne, czasami wydaje mi się przydatne zdefiniowanie szablonów testów uzupełniających, które przyjmują kilka parametrów. Następnie rzeczywiste metody testowe sprowadzają się do wywołania metody szablonowej z odpowiednimi parametrami.
Jeśli chodzi o wiele rzeczy związanych z programowaniem i testowaniem, nie ma jednoznacznej odpowiedzi. Musisz rozwinąć gust, a najlepszym sposobem na to jest popełnianie błędów.
źródło
Zgadzam się. Kompromis istnieje, ale jest różny w różnych miejscach.
Bardziej prawdopodobne jest, że zmienię zduplikowany kod w celu skonfigurowania stanu. Ale jest mniej prawdopodobne, że zmienimy tę część testu, która faktycznie ćwiczy kod. To powiedziawszy, jeśli ćwiczenie kodu zawsze zajmuje kilka wierszy kodu, to mogę pomyśleć, że jest to zapach i refaktoryzacja rzeczywistego testowanego kodu. A to poprawi czytelność i łatwość utrzymania zarówno kodu, jak i testów.
źródło
Możesz zmniejszyć liczbę powtórzeń, używając kilku różnych odmian metod testowych .
Jestem bardziej tolerancyjny na powtórzenia w kodzie testowym niż w kodzie produkcyjnym, ale czasami frustrowało mnie to. Kiedy zmieniasz projekt klasy i musisz cofnąć się i ulepszyć 10 różnych metod testowych, z których wszystkie wykonują te same kroki konfiguracji, jest to frustrujące.
źródło
Jay Fields ukuł zdanie, że „DSL powinny być wilgotne, a nie suche”, gdzie DAMP oznacza opisowe i znaczące wyrażenia . Myślę, że to samo dotyczy testów. Oczywiście zbyt duże powielanie jest złe. Ale usuwanie powielania za wszelką cenę jest jeszcze gorsze. Testy powinny działać jako specyfikacje ujawniające zamiary. Jeśli, na przykład, określisz ten sam element z kilku różnych punktów widzenia, należy spodziewać się pewnego powielenia.
źródło
Uwielbiam rspec z tego powodu:
Ma dwie rzeczy do pomocy -
wspólne grupy przykładowe do testowania typowego zachowania.
możesz zdefiniować zestaw testów, a następnie „uwzględnić” go w swoich prawdziwych testach.
zagnieżdżone konteksty.
zasadniczo możesz mieć metodę „konfiguracji” i „porzucenia” dla określonego podzbioru testów, a nie tylko dla wszystkich w klasie.
Im szybciej platformy testowe .NET / Java / inne zastosują te metody, tym lepiej (lub możesz użyć IronRuby lub JRuby do napisania testów, co osobiście uważam za lepszą opcję)
źródło
Uważam, że kod testowy wymaga podobnego poziomu inżynierii, który normalnie byłby stosowany w kodzie produkcyjnym. Z pewnością można argumentować za czytelnością i zgadzam się, że to ważne.
Jednak z mojego doświadczenia wynika, że dobrze opracowane testy są łatwiejsze do odczytania i zrozumienia. Jeśli istnieje pięć testów, z których każdy wygląda tak samo, z wyjątkiem jednej zmiennej, która została zmieniona, i stwierdzenia na końcu, może być bardzo trudno znaleźć ten pojedynczy, różniący się element. Podobnie, jeśli zostanie uwzględnione w taki sposób, że widoczna jest tylko zmienna, która się zmienia, i asercja, wtedy łatwo jest natychmiast dowiedzieć się, co robi test.
Znalezienie odpowiedniego poziomu abstrakcji podczas testowania może być trudne i uważam, że warto to zrobić.
źródło
Myślę, że nie ma związku między bardziej zduplikowanym i czytelnym kodem. Myślę, że twój kod testowy powinien być tak dobry, jak twój inny kod. Niepowtarzający się kod jest bardziej czytelny niż kod zduplikowany, jeśli jest dobrze wykonany.
źródło
Idealnie byłoby, gdyby testy jednostkowe nie zmieniły się zbytnio po ich napisaniu, więc skłaniałbym się do czytelności.
Posiadanie tak dyskretnych testów jednostkowych, jak to tylko możliwe, pomaga również skupić się na testach na określonej funkcjonalności, do której są przeznaczone.
Mając to na uwadze, staram się ponownie używać pewnych fragmentów kodu, których używam w kółko, takich jak kod konfiguracji, który jest dokładnie taki sam w zestawie testów.
źródło
„refaktoryzowałem je, aby były bardziej SUCHE - cel każdego testu nie był już jasny”
Wygląda na to, że miałeś problem z refaktoryzacją. Zgaduję, ale jeśli okazało się mniej jasne, czy to nie oznacza, że nadal masz więcej pracy, 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 mieliśmy narzędzia testowe, które korzystały z różnych języków programowania. Trudno było (lub niemożliwe) zaprojektować przyjemne, łatwe w obsłudze testy.
Masz pełną moc - niezależnie od używanego języka - Python, Java, C # - więc dobrze używaj tego języka. Możesz uzyskać dobrze wyglądający kod testowy, który jest przejrzysty i niezbyt zbędny. Nie ma kompromisu.
źródło