Testowanie jednostkowe Katalog anty-wzorów

203

anty-wzór : muszą być obecne co najmniej dwa kluczowe elementy, aby formalnie odróżnić faktyczny wzór od prostego złego nawyku, złej praktyki lub złego pomysłu:

  • Niektóre powtarzające się wzorce działania, procesu lub struktury, które początkowo wydają się korzystne, ale ostatecznie powodują więcej złych konsekwencji niż korzystne wyniki, oraz
  • Refaktoryzowane rozwiązanie, które jest wyraźnie udokumentowane, sprawdzone w praktyce i powtarzalne.

Głosuj na anty-wzór TDD, który widziałeś „na wolności” raz za dużo.
Wpis na blogu Jamesa Carra i powiązana dyskusja na temat grupy testowej ds. Rozwoju

Jeśli znalazłeś też „nienazwany” post… em. Jeden post na anty-wzór proszę, aby głosy za coś się liczyły.

Moim głównym zainteresowaniem jest znalezienie podzbioru top-n, aby móc omówić je na spotkaniu lunchbox w najbliższej przyszłości.

Gishu
źródło
Aaron, wydajesz się, że to już koniec :) Czy dobrym pomysłem byłoby dodanie tagów lub sloganów jako komentarzy, abyśmy mogli mieć mniej przewijania… co powiedzieć?
Gishu,
1
To idzie dość dobrze .. dzięki chłopaki i dziewczęta. Trzymaj ich nadchodzących .. jeden z najbardziej pouczających SO postów IMHO
Gishu
2
+1 uwielbiam ten wątek !!! A większość z nich jest tak prawdziwa i dominująca!
Chii,
Niezły wątek, dlaczego jest to wiki społeczności ???
Quibblesome
2
Bo to rodzaj ankiety - nie chciałbyś zbierać przedstawicieli, bo opublikowałeś najczęstszy rodzaj anty-wzorca;)
Gishu,

Odpowiedzi:

70

Obywatele drugiej klasy - kod testowy nie jest tak dobrze refaktoryzowany jak kod produkcyjny, zawierający dużo zduplikowanego kodu, co utrudnia utrzymanie testów.

Ilja Preuß
źródło
67

The Free Ride / Piggyback - James Carr, Tim Ottinger
Zamiast napisać nową metodę przypadku testowego w celu przetestowania innej / odrębnej cechy / funkcjonalności , nowe stwierdzenie (i odpowiadające mu czynności, tj. Kroki z AAA) porusza się w istniejącym przypadku testowym .

Aaron Digulla
źródło
15
Tak, to moja ulubiona. Ciągle to robię. Och ... czekaj ... powiedziałeś, że to zła rzecz. :-)
guidoizm
1
Nie jestem pewien, czy to anty-wzór. Wszystkie niezmienniki muszą znajdować się truepo każdym możliwym wywołaniu mutatora. Będziesz więc chciał sprawdzić, czy każdy niezmiennik występuje truepo każdej kombinacji mutatora i testowanych danych wejściowych. Ale będziesz chciał ograniczyć duplikację i upewnić się, że sprawdziłeś wszystkie niezmienniki, w tym te, które obecnie nie powodują niepowodzenia testów. Umieszczasz je wszystkie w checkInvariants()funkcji weryfikacji i używasz jej w każdym teście. Kod zmienia się i dodawany jest kolejny niezmiennik. Oczywiście umieścisz to również w funkcji. Ale to freerider.
Raedwald
2
@ Raedwald - Z czasem nazwa testu nie pasuje już do wszystkich testowanych rzeczy. Masz też trochę wstrząsów z powodu przeplatających się testów; awaria nie wskazuje dokładnej przyczyny awarii. np. kanoniczny przykład tego testu brzmiałby jak nieprzejrzysty nadzbiór wszystkich kroków aranżacyjnych >> akt >> twierdzenie A >> akt więcej >> twierdzenie B >> akt jeszcze >> >> twierdzenie C. Teraz idealnie, jeśli A i C są zepsuty, powinieneś zobaczyć 2 niepowodzenia testów. W powyższym teście zobaczysz tylko jeden, a następnie naprawisz A, a przy następnym uruchomieniu powiesz, że teraz C jest zepsuty. teraz wyobraź sobie, że połączono ze sobą 5-6 różnych testów.
Gishu
1
„nazwa testu nie pasuje już do wszystkich rzeczy, które testuje” Tylko wtedy, gdy test jest nazwany dla pierwotnie występującego warunku postu. Jeśli nazwiesz kombinację nazwy metody, stanu konfiguracji i danych wejściowych (argumenty metody), nie ma problemu.
Raedwald
„awaria nie wskazuje dokładnej przyczyny awarii” żadna awaria stwierdzenia nigdy nie wskazuje przyczyny awarii. Wymaga to zagłębienia się w szczegóły implementacji: debugowanie w przypadku niepowodzenia regresji, znajomość stanu rozwoju niektórych prac TDD.
Raedwald
64

Szczęśliwa ścieżka

Test pozostaje na szczęśliwych ścieżkach (tj. Oczekiwanych wynikach) bez testowania granic i wyjątków.

JUnit Antipatterns

Geoglif
źródło
Przyczyna: Przesadzone ograniczenia czasowe lub rażące lenistwo. Refaktoryzowane rozwiązanie: poświęć trochę czasu na napisanie kolejnych testów, aby pozbyć się fałszywych wyników pozytywnych. Ta ostatnia przyczyna wymaga bata. :)
Spoike
59

Lokalny bohater

Przypadek testowy zależny od czegoś specyficznego dla środowiska programistycznego, na którym został napisany w celu uruchomienia. Wynik jest taki, że test przechodzi na skrzynki programistyczne, ale kończy się niepowodzeniem, gdy ktoś próbuje uruchomić go w innym miejscu.

Ukryta zależność

Ściśle związany z lokalnym bohaterem, test jednostkowy, który wymaga wypełnienia niektórych istniejących danych gdzieś przed uruchomieniem testu. Jeśli te dane nie zostaną wypełnione, test zakończy się niepowodzeniem i nie pozostawi twórcy wskazówek, czego chciał lub dlaczego… zmuszając ich do przekopania się przez akry kodu, aby dowiedzieć się, skąd dane miały pochodzić.


Niestety, widziałem to zdecydowanie zbyt wiele razy ze starożytnymi bibliotekami DLL, które zależą od mglistych i różnorodnych plików .ini, które są ciągle niezsynchronizowane w dowolnym systemie produkcyjnym, nie mówiąc już o istnieniu na twoim komputerze bez szeroko zakrojonych konsultacji z trzema programistami odpowiedzialnymi za te biblioteki. Westchnienie.

annakata
źródło
To dobry przykład akronimu programisty WOMPC. „Działa na moim komputerze!” (zwykle mówi się, że ściągają testerów z pleców.)
Joris Timmermans,
58

Gang łańcucha

Kilka testów, które muszą zostać uruchomione w określonej kolejności, tj. Jeden test zmienia globalny stan systemu (zmienne globalne, dane w bazie danych) i od tego zależą kolejne testy.

Często widać to w testach bazy danych. Zamiast wycofywania teardown(), testy zatwierdzają zmiany w bazie danych. Inną częstą przyczyną jest to, że zmiany stanu globalnego nie są zawijane w blokach try / wreszcie, które usuwają się w przypadku niepowodzenia testu.

Aaron Digulla
źródło
ten jest po prostu paskudny. Przerwanie testów musi być niezależnym pojęciem. Ale czytałem o tym w wielu miejscach .. zgadnij, że „popularne TDD” jest dość popsute
Gishu
56

Kpina
Czasami kpiny mogą być dobre i przydatne. Ale czasami programiści mogą się zatracić i próbować wyśmiewać to, co nie jest testowane. W tym przypadku test jednostkowy zawiera tak wiele próbnych prób, kodów pośredniczących i / lub podróbek, że testowany system w ogóle nie jest testowany, zamiast tego testowane są dane zwrócone z próbnych testów.

Źródło: post Jamesa Carra.

Gishu
źródło
2
Uważam, że przyczyną tego jest to, że twoja testowana klasa ma zbyt wiele zależności. Refaktoryzowaną alternatywą jest wyodrębnienie kodu, który można wyizolować.
Spoike,
@Spoike; Jeśli jesteś w architekturze warstwowej, która naprawdę zależy od roli klasy; niektóre warstwy mają zwykle więcej zależności niż inne.
krosenvold
Niedawno widziałem, na szanowanym blogu, stworzenie fałszywej konfiguracji bytu, która ma zostać zwrócona z fałszywego repozytorium. WTF? Dlaczego nie po prostu stworzyć prawdziwego bytu. Ja sam zostałem spalony przez szyderczy interfejs, w którym moja implementacja rzucała dookoła wyjątki NotImplementedExceptions.
Thomas Eyde
40

The Silent Catcher - Kelly?
Test, który jest pozytywny, jeśli zostanie zgłoszony wyjątek. Nawet jeśli faktycznie wystąpi wyjątek, jest on inny niż ten, który zamierzył programista.
Zobacz też: Secret Catcher

[Test]
[ExpectedException(typeof(Exception))]
public void ItShouldThrowDivideByZeroException()
{
   // some code that throws another exception yet passes the test
}
Gishu
źródło
Jest to trudne i niebezpieczne (tzn. Sprawia, że ​​myślisz, że testowałeś kod, który zawsze eksploduje przy każdym uruchomieniu). Dlatego staram się sprecyzować zarówno klasę wyjątków, jak i coś wyjątkowego w komunikacie.
Joshua Cheek
34

Inspektor
Test jednostkowy, który narusza enkapsulację w celu uzyskania 100% pokrycia kodu, ale wie tyle o tym, co dzieje się w obiekcie, że każda próba refaktoryzacji przerwie istniejący test i będzie wymagała odzwierciedlenia każdej zmiany w jednostce test.


„w jaki sposób testować zmienne składowe bez upubliczniania ich… tylko do testowania jednostkowego?”

Gishu
źródło
2
Przyczyna: Absurdalne poleganie na testach białych skrzynek. Istnieją narzędzia do generowania tego rodzaju testów, takich jak Pex na .NET. Refaktoryzowane rozwiązanie: Zamiast tego sprawdź zachowanie, a jeśli naprawdę musisz sprawdzić wartości graniczne, pozwól automatycznym narzędziom wygenerować resztę.
Spoike,
1
Zanim pojawił się Moq, musiałem porzucić szydercze ramy na rzecz pisma ręcznego. Po prostu zbyt łatwo było powiązać moje testy z faktyczną implementacją, co uniemożliwiło refaktoryzację. Nie umiem odróżnić, poza Moq, rzadko popełniam tego rodzaju błędy.
Thomas Eyde
34

Nadmierna konfiguracja - James Carr
Test, który wymaga ogromnej konfiguracji, aby nawet rozpocząć testowanie. Czasami używa się kilkuset wierszy kodu do przygotowania środowiska do jednego testu, z kilkoma zaangażowanymi obiektami, co może utrudnić naprawdę ustalenie, co jest testowane z powodu „szumu” całej trwającej konfiguracji. (Src: post Jamesa Carra )

Gishu
źródło
Rozumiem, że nadmierna konfiguracja testu zwykle wskazuje na a) źle skonstruowany kod lub b) niewystarczające kpiny, prawda?
Topher Hunt
Każda sytuacja może być inna. Może to być spowodowane wysokim sprzężeniem. Ale zwykle jest to przypadek zawyżenia specyfikacji, określający (pozorne oczekiwania) każdego współpracownika w scenariuszu - to łączy test z implementacją i czyni je kruchymi. Jeśli połączenie do współpracownika jest przypadkowym szczegółem testu, nie powinno być w teście. Pomaga to również utrzymać krótki i czytelny test.
Gishu,
32

Sonda analna

Test, który musi wykorzystywać szalone, nielegalne lub w inny sposób niezdrowe sposoby wykonywania swojego zadania, takie jak: Odczytywanie pól prywatnych za pomocą setAccessible Javy (true) lub rozszerzanie klasy w celu uzyskania dostępu do chronionych pól / metod lub konieczność umieszczenia testu w określonym pakiecie w celu uzyskania dostępu pakuj globalne pola / metody.

Jeśli widzisz ten wzorzec, testowane klasy wykorzystują zbyt wiele ukrywania danych.

Różnica między tym a Inspektorem polega na tym, że testowana klasa próbuje ukryć nawet to, co musisz przetestować. Twoim celem nie jest więc uzyskanie 100% pokrycia testowego, ale możliwość dowolnego testowania. Pomyśl o klasie, która ma tylko prywatne pola, run()metodę bez argumentów i żadnych pobierających. Nie ma sposobu, aby to sprawdzić bez złamania zasad.


Komentarz Michaela Borgwardta: To nie jest tak naprawdę testowy antypattern, pragmatyzm radzi sobie z brakami w testowanym kodzie. Oczywiście lepiej jest naprawić te braki, ale może to nie być możliwe w przypadku bibliotek stron trzecich.

Aaron Digulla: Zgadzam się. Być może ten wpis jest naprawdę lepiej dostosowany do wiki „JUnit HOWTO”, a nie do antipattern. Komentarze?

Aaron Digulla
źródło
czy to nie to samo co inspektor?
Gishu,
1
Hmm ... ta linia „testowana klasa próbuje ukryć nawet to, co musisz przetestować” wskazuje na walkę o władzę między klasą a testem. Jeśli powinien zostać przetestowany .. powinien być jakoś publicznie osiągalny .. poprzez zachowanie klasowe / interfejs .. to w jakiś sposób pachnie naruszeniem enkapsulacji
Gishu
2
npellow: Maven2 ma do tego wtyczkę, prawda?
Aaron Digulla,
1
To nie jest tak naprawdę testowy wzorzec, pragmatyzm radzi sobie z brakami w testowanym kodzie. Oczywiście lepiej jest naprawić te braki, ale może to nie być możliwe w przypadku bibliotek stron trzecich.
Michael Borgwardt,
1
IDK, to musi mieć jakiś efekt uboczny. Sprawdziłbym efekt uboczny. Nie jestem pewien, co masz na myśli przez testowanie interfejsu API strony trzeciej, argumentuję, że powinieneś zawrzeć to w swoim własnym kodzie, który można przetestować, został użyty poprawnie, a następnie przetestuj ten kod pod kątem interfejsu API strony trzeciej. Nie testowałby kodu strony trzeciej.
Joshua Cheek
26

Test bez nazwy - Nick Pellow

Test, który jest dodawany w celu odtworzenia określonego błędu w narzędziu do śledzenia błędów i którego autor sądzi, nie gwarantuje własnej nazwy. Zamiast ulepszać istniejący, brakujący test, tworzony jest nowy test o nazwie testForBUG123.

Dwa lata później, gdy test się nie powiedzie, być może będziesz musiał najpierw znaleźć BUG-123 w swoim narzędziu do śledzenia błędów, aby ustalić cel testu.

npellow
źródło
7
Tak prawdziwe. Jest to nieco bardziej pomocne niż test o nazwie „TestMethod”
NikolaiDante,
8
chyba że bugtracker się zmieni, a ty stracisz stary moduł śledzący i jego identyfikatory problemów ... więc PROJECT-123 już nic nie znaczy ...
Chii,
25

The Slow Poke

Test jednostkowy, który działa niezwykle wolno. Kiedy programiści zaczynają, mają czas, aby pójść do łazienki, złapać dym lub, co gorsza, rozpocząć test, zanim wrócą do domu pod koniec dnia. (Src: post Jamesa Carra )

czyli testy, które nie będą uruchamiane tak często, jak powinny

Gishu
źródło
Niektóre testy przebiegają powoli z samej swojej natury. Jeśli zdecydujesz się nie uruchamiać ich tak często, jak inne, upewnij się, że działają przynajmniej na serwerze CI tak często, jak to możliwe.
Chris Vest,
To oczywiste pytanie, ale jakie są najbardziej ogólne sposoby rozwiązania tego problemu?
Topher Hunt
Początkowo wydaje się to korzystne, prawda?
Kev
1
@TopherHunt Zazwyczaj testy są powolne, ponieważ mają one pewną kosztowną zależność (tj. System plików, baza danych). Sztuką jest analizowanie zależności, dopóki nie zobaczysz problemu, a następnie przesuwanie zależności w górę stosu wywołań. Napisałem studium przypadku, w którym moi uczniowie wzięli zestaw testów jednostkowych z 77 sekund do 0,01 sekundy, naprawiając swoje zależności: github.com/JoshCheek/fast_tests
Joshua Cheek
20

Motyl

Musisz przetestować coś, co zawiera dane, które cały czas się zmieniają, na przykład strukturę zawierającą bieżącą datę, i nie ma sposobu, aby doprowadzić wynik do ustalonej wartości. Brzydkie jest to, że w ogóle nie przejmujesz się tą wartością. To po prostu komplikuje test bez dodawania wartości.

Nietoperz jego skrzydła może spowodować huragan po drugiej stronie świata. - Edward Lorenz, Efekt motyla

Aaron Digulla
źródło
Co to jest anty-wzór tutaj: Jak wygląda taki test? Czy jest jakaś poprawka? Czy testowany kod ma jakąkolwiek uzasadnioną zaletę w odróżnieniu zależności System.DateTime.Now, oprócz posiadania prostszych lub bardziej deterministycznych testów jednostkowych?
Merlyn Morgan-Graham
1
W Javie przykładem może być wywołanie toString()obiektu, który nie zastąpi metody. To da ci identyfikator obiektu, który zależy od adresu pamięci. Lub toString()zawiera klucz podstawowy obiektu, który zmienia się przy każdym uruchomieniu testu. Istnieją trzy sposoby, aby to naprawić: 1. Zmień testowany kod, 2. Użyj wyrażenia regularnego, aby usunąć zmienne części wyników testu lub 3. Użyj potężnych narzędzi do zastąpienia usług systemowych, aby zwróciły przewidywalne wyniki.
Aaron Digulla
Przyczyną tego anty-wzorca jest to, że testowany kod nie dba o to, ile wysiłku może wymagać jego przetestowania. Kaprys dewelopera to skrzydło motyla, które powoduje problemy gdzie indziej.
Aaron Digulla
19

Test migotania (źródło: Romilly Cocking)

Test, który po prostu czasami kończy się niepowodzeniem, a nie w określonych momentach, i jest generalnie spowodowany warunkami wyścigowymi w teście. Zazwyczaj występuje podczas testowania czegoś asynchronicznego, takiego jak JMS.

Być może super zestaw do anty-wzoru „ Wait and See ” i anty-wzoru „ The Sleeper ”.

Kompilacja nie powiodła się, no cóż, po prostu uruchom kompilację ponownie. - Anonimowy programista

Stuart
źródło
@Stuart - film, który trzeba zobaczyć, to „Car Stalled - Try Now!” videosift.com/video/… Ten wzorzec można również nazwać „Wypróbuj teraz!” lub po prostu „The Flakey Test”
npellow
1
Kiedyś napisałem test dla PRGN, który zapewnił prawidłową dystrybucję. Czasami zawodzi losowo. Domyśl. :-)
Chris Vest
1
Czy nie byłby to dobry test? Jeśli test kiedykolwiek się nie powiedzie, musisz wyśledzić źródło problemu. Walczyłem z kimś o teście, który nie powiódł się między 9p a północą. Powiedział, że to przypadkowe / sporadyczne. W końcu został wyśledzony przez błąd dotyczący stref czasowych. Domyśl.
Trenton
@Christian Vest Hansen: nie mógłbyś go zasiać?
Andrew Grimm,
@trenton To tylko dobry test, jeśli programiści mogą mieć problem z wyśledzeniem go, zamiast po prostu ignorować (z czym mogą sobie poradzić, gdy mija większość czasu).
Will Sheppard,
19

Poczekaj i zobacz

Test, który uruchamia pewien ustawiony kod, a następnie musi „poczekać” określony czas, zanim będzie mógł „zobaczyć”, czy testowany kod działa zgodnie z oczekiwaniami. TestMethod, który korzysta z Thread.sleep () lub odpowiednika, jest z pewnością testem „Czekaj i patrz”.

Zazwyczaj można to zobaczyć, jeśli test testuje kod, który generuje zdarzenie zewnętrzne względem systemu, takie jak wiadomość e-mail, żądanie HTTP lub zapisuje plik na dysku.

Taki test może być również bohaterem lokalnym, ponieważ zakończy się niepowodzeniem, gdy zostanie uruchomiony na wolniejszym komputerze lub na przeciążonym serwerze CI.

Anty-wzór Czekaj i patrz nie należy mylić z Uśpionym .

npellow
źródło
Hmm .. cóż, używam czegoś takiego. w jaki inny sposób mógłbym przetestować kod wielowątkowy?
Gishu,
@Gishu, czy naprawdę chcesz testować jednostkowo wiele wątków działających jednocześnie? Próbuję po prostu przetestować jednostkę niezależnie od tego, co robi metoda run () w izolacji. Łatwym sposobem na to jest wywołanie run () - które zablokuje zamiast start () z testu jednostkowego.
npellow
@ Gishu używa CountDownLatches, semaforów, warunków itp., Aby wątki mówiły sobie, kiedy mogą przejść do następnego poziomu.
Chris Vest,
Przykład: madcoderspeak.blogspot.com/2008/11/… Przycisk zaparzania evt. Obserwator okresowo odpytuje i podnosi zmienione zdarzenia. W takim przypadku dodam opóźnienie, aby wątki odpytywania mogły uruchomić się przed zakończeniem testu.
Gishu,
Myślę, że link do kreskówki jest zepsuty.
Andrew Grimm
17

Niewłaściwie współużytkowane urządzenie - Tim Ottinger
Kilka przypadków testowych w urządzeniu testowym nawet nie używa ani nie wymaga konfiguracji / rozerwania. Częściowo z powodu bezwładności programisty, aby utworzyć nowe urządzenie testowe ... łatwiej jest po prostu dodać jeszcze jeden przypadek testowy do stosu

Gishu
źródło
1
Może się również zdarzyć, że testowana klasa próbuje zrobić zbyt wiele.
Mike Two
16

Gigant

Test jednostkowy, który mimo prawidłowego testowania testowanego obiektu, może obejmować tysiące linii i zawierać wiele wielu przypadków testowych. Może to wskazywać, że testowany system jest obiektem Boga (post Jamesa Carra).

Pewnym znakiem tego testu jest test obejmujący więcej niż kilka wierszy kodu. Często test jest tak skomplikowany, że zaczyna zawierać błędy własnego lub niestabilnego zachowania.

Gishu
źródło
15

Uwierzę w to, gdy zobaczę migające GUI
. Niezdrowe utrwalenie / obsesja na punkcie testowania aplikacji za pomocą GUI „jak prawdziwy użytkownik”

Testowanie reguł biznesowych za pomocą GUI jest straszną formą łączenia. Jeśli napiszesz tysiące testów za pomocą GUI, a następnie zmienisz GUI, tysiące testów się zepsują.
Zamiast tego testuj tylko GUI za pomocą GUI i po uruchomieniu tych testów połącz GUI z atrapą systemu zamiast z prawdziwym systemem. Testuj reguły biznesowe za pomocą interfejsu API, który nie wymaga interfejsu GUI. - Bob Martin

„Musisz zrozumieć, że widzenie to wiara, ale także wiedzieć, że wiara to widzenie”. - Denis Waitley

Gishu
źródło
1
Jeśli uważasz, że flashowanie GUI jest złe, widziałem kogoś, kto napisał test jUnit, który uruchomił GUI i potrzebował interakcji użytkownika, aby kontynuować. Zawiesił resztę zestawu testowego. Tyle o automatyzacji testów!
Spoike,
Nie zgadzam się. Testowanie GUI jest trudne, ale są też źródłem błędów. Nie testowanie ich jest po prostu leniwe.
Ray
3
chodzi o to, że nie powinieneś testować GUI, a raczej, że nie powinieneś testować tylko za pomocą GUI. Testy bezgłowe można wykonywać bez interfejsu GUI. Utrzymuj GUI tak cienkie, jak to możliwe - użyj smaku MVP - możesz wtedy uniknąć testowania go w ogóle. Jeśli okaże się, że przez cały czas pojawiają się błędy w cienkiej warstwie interfejsu GUI, obejrzyj je testami ... ale przez większość czasu nie uważam, że warto. Błędy „okablowania” GUI są zazwyczaj łatwiejsze do naprawienia ...
Gishu,
@Spoike: Testy ręczne z przewodnikiem nie są złe, ani nie używa jUnit (ani żadnej innej platformy testów jednostkowych) do przeprowadzania testów automatycznych, które nie są testami jednostkowymi. Po prostu nie powinieneś umieszczać ich w tym samym projekcie, ani traktować ich jak testów jednostkowych (np. Ciągłego uruchamiania lub po każdej kompilacji).
Merlyn Morgan-Graham
1
@ MerlynMorgan-Graham Zgadzam się i nie miałem na myśli, że nie powinieneś testować GUI. Przekonanie członków zespołu, że mieszanie testów manualnych z automatycznymi jest w porządku, niepokoiło mnie. Dowiedziałem się później, że był to doskonały sposób na to, aby wszyscy, którzy nie są przyzwyczajeni do TDD, przestali go używać. Uważam, że mieszanie testów funkcjonalnych (które są lotne) z testami jednostkowymi (które powinny być stabilne) jest złe, jeśli chcesz postępować zgodnie z procesem TDD.
Spoike
14

Śpiący, znany również jako Wezuwiusz - Nick Pellow

Test, który ma zakończyć się niepowodzeniem o określonej godzinie i dacie w przyszłości. Jest to często spowodowane nieprawidłowym sprawdzaniem granic podczas testowania kodu, który używa obiektu Date lub Calendar. Czasami test może się nie powieść, jeśli zostanie przeprowadzony o bardzo określonej porze dnia, na przykład o północy.

„The Sleeper” nie należy mylić z anty-wzorem „ Wait And See ”.

Kod ten zostanie zastąpiony na długo przed 2000 rokiem - wielu programistów w 1960 roku

npellow
źródło
Wolę nazwać to uśpionym wulkanem :) .. ale wiem o czym mówisz .. np. Data wybrana jako data przyszłej próby w momencie pisania stanie się datą teraźniejszą / przeszłą, kiedy ta data przechodzi ... przełamując test. Czy możesz opublikować przykład… tylko dla zilustrowania tego.
Gishu,
@Gishu - +1. Myślałem tak samo, ale nie mogłem się zdecydować. Zaktualizowałem tytuł, aby było trochę jaśniej;)
npellow
11

The Dead Tree

Test, w którym utworzono kod pośredniczący, ale test nie został w rzeczywistości napisany.

Rzeczywiście widziałem to w naszym kodzie produkcyjnym:

class TD_SomeClass {
  public void testAdd() {
    assertEquals(1+1, 2);
  }
}

Nie wiem nawet, co o tym myśleć.

Wielebny Gonzo
źródło
8
:) - znany również jako Backdoor Process Compliance.
Gishu,
1
Mieliśmy przykład tego niedawno w teście i testowanej metodzie, które były wielokrotnie refaktoryzowane. Po kilku iteracjach test stał się wywołaniem testowanej metody. A ponieważ metoda zwróciła się teraz jako nieważna, nie było żadnych twierdzeń do potwierdzenia. Zasadniczo test polegał na upewnieniu się, że metoda nie zgłasza wyjątku. Nie miało znaczenia, czy faktycznie zrobiło coś pożytecznego czy poprawnie. Znalazłem to w przeglądzie kodu i zapytałem: „Więc… co tu testujemy?”
Marvo
11

ugryzł mnie dzisiaj:

Mokra podłoga :
test tworzy dane, które są gdzieś utrwalane, ale test nie jest czyszczony po zakończeniu. Powoduje to, że testy (ten sam test lub ewentualnie inne testy) kończą się niepowodzeniem podczas kolejnych testów.

W naszym przypadku test pozostawił plik leżący w katalogu „temp” z uprawnieniami użytkownika, który uruchomił test po raz pierwszy. Gdy inny użytkownik próbował przetestować na tej samej maszynie: boom. W komentarzach na stronie Jamesa Carra Joakim Ohlrogge określił to jako „niechlujny robotnik” i było to częścią inspiracji dla „Hojnych resztek”. Bardziej podoba mi się moje imię (mniej obraźliwe, bardziej znane).

Zac Thompson
źródło
Możesz użyć reguły folderów tymczasowych junita, aby uniknąć mokrych podłóg.
DaveFar
Ten rodzaj odnosi się do anty-wzorca ciągłej integracji. W CI każdy programista powinien mieć własne miejsce do pracy i zasoby, a maszyną do kompilacji powinno być także własne środowisko. Następnie unikasz takich problemów, jak problemy z pozwoleniami (a może ukrywasz je, aby pojawiły się tylko w produkcji)
Marvo
11

Kukułka - Frank Carver
Test jednostkowy, który siedzi w skrzynce testowej z kilkoma innymi i cieszy się tym samym (potencjalnie długim) procesem konfiguracji jak inne testy w przypadku testowym, ale następnie odrzuca niektóre lub wszystkie artefakty z konfiguracji i tworzy własne.
Zaawansowany Objaw: Niewłaściwie udostępnione urządzenie

Gishu
źródło
10

The Secret Catcher - Frank Carver
Test, który na pierwszy rzut oka wydaje się nie przeprowadzać testów z powodu braku stwierdzeń. Ale „diabeł tkwi w szczegółach” .. test naprawdę polega na zgłoszeniu wyjątku i oczekuje, że środowisko testowe uchwyci wyjątek i zgłosi go użytkownikowi jako niepowodzenie.

[Test]
public void ShouldNotThrow()
{
   DoSomethingThatShouldNotThrowAnException();
}
Gishu
źródło
2
Moim zdaniem może to być poprawny test - szczególnie jako test regresji.
Ilja Preuß,
przepraszam, znowu pomyliłem to z Cichym łapaczem ... testy jednostkowe powinny jasno określać zamiar tego, co jest testowane, zamiast mówić „to powinno działać” .. (+1 tp coś jest lepsze niż nic. szczególnie jeśli jesteś w regresji starszej wersji kraj)
Gishu,
1
W tego rodzaju testach przynajmniej wychwytuję wyjątek i przypisuję go do zmiennej. Następnie twierdzę, że nie jest zerowy.
Thomas Eyde,
4
Niektóre frameworki mają Assert.DoesNotThrow(SomeDelegateType act)asertywność stylu, która może być używana w takich przypadkach. Uważam, że jest to mniej obrzydliwe niż posiadanie przypadku testowego, który kończy się powodzeniem, gdy konstruktor zwraca wartość inną niż null, ale kończy się niepowodzeniem, gdy konstruktor wyrzuca. Konstruktor nigdy nie zwróci wartości null. (Uwaga: dotyczy tylko języków, w których konstruktor gwarantuje zwrócenie wartości innej niż null)
Merlyn Morgan-Graham
10

Wandal środowiskowy

Test „jednostkowy”, który dla różnych „wymagań” zaczyna rozlewać się do środowiska, wykorzystując i ustawiając zmienne środowiskowe / porty. Uruchomienie dwóch z tych testów jednocześnie spowoduje wyjątki „niedostępny port” itp.

Testy te będą sporadyczne, a programiści powiedzą „po prostu uruchom ponownie”.

Jednym z rozwiązań, które widziałem, jest losowy wybór numeru portu do użycia. Zmniejsza to możliwość konfliktu, ale wyraźnie nie rozwiązuje problemu. Jeśli możesz, zawsze kpij z kodu, aby nie przydzielał zasobów, których nie można udostępnić.

gcrain
źródło
@gcrain .. testy powinny być deterministyczne. IMO lepszym rozwiązaniem byłoby użycie portu „dobrze znanego w zespole” do testowania i czyszczenia przed i po teście poprawnie, tak aby zawsze był dostępny ...
Gishu
1
@gishu - problemem nie jest to, że nie ma metod setup () i teardown () do obsługi tych portów. problemem jest na przykład uruchomienie serwera CI i jednoczesne uruchomienie wielu wersji testowych, próba użycia tych samych, zakodowanych w teście numerów portów
gcrain
10

Test Turinga

Przypadek testowy wygenerowany automatycznie przez jakieś drogie narzędzie, które ma wiele, wiele stwierdzeń zebranych z testowanej klasy przy użyciu zbyt sprytnej analizy przepływu danych o połowę. Lulls programistów ma fałszywe poczucie pewności, że ich kod jest dobrze przetestowany, zwalniając ich z odpowiedzialności za projektowanie i utrzymanie wysokiej jakości testów. Jeśli maszyna może napisać dla ciebie testy, dlaczego nie może wyciągnąć palca i napisać samej aplikacji!

Cześć głupi. - Najmądrzejszy komputer na świecie dla nowego ucznia (od starego komiksu Amigi).

bhumphreys
źródło
10

Test bieguna czterdziestostopowego

W obawie przed zbytnim zbliżeniem się do klasy, którą próbują przetestować, testy te działają na odległość, oddzielone niezliczonymi warstwami abstrakcji i tysiącami linii kodu od logiki, którą sprawdzają. Jako takie są niezwykle kruche i podatne na wszelkiego rodzaju skutki uboczne, które zdarzają się podczas epickiej podróży do i od zainteresowań.

bhumphreys
źródło
9

Doppelgänger

Aby coś przetestować, musisz skopiować części testowanego kodu do nowej klasy o tej samej nazwie i pakiecie oraz musisz użyć magii ścieżki klas lub niestandardowego modułu ładującego klasy, aby upewnić się, że jest on widoczny jako pierwszy (więc twoja kopia zostanie wybrana w górę).

Ten wzór wskazuje na niezdrową ilość ukrytych zależności, których nie można kontrolować za pomocą testu.

Spojrzałem na jego twarz ... moją twarz! To było jak lustro, ale zamroziło mi krew.

Aaron Digulla
źródło
7

Matka kura - Frank Carver
Wspólna konfiguracja, która robi znacznie więcej niż potrzeba rzeczywistych przypadków testowych. Na przykład tworzenie wszelkiego rodzaju złożonych struktur danych wypełnionych pozornie ważnymi i unikalnymi wartościami, gdy testy potwierdzają tylko obecność lub brak czegoś.
Zaawansowany Objaw: Niewłaściwie udostępnione urządzenie

Nie wiem, co robi ... I tak to dodam, na wszelki wypadek. - Anonimowy programista

Gishu
źródło
7

Testuj wszystko

Nie mogę uwierzyć, że do tej pory o tym nie wspomniano, ale testy nie powinny łamać zasady pojedynczej odpowiedzialności .

Zetknąłem się z tym wiele razy, testy łamiące tę zasadę są z definicji koszmarem do utrzymania.

thegreendroid
źródło
6

Hitter linii

Na pierwszy rzut oka testy obejmują wszystko, a narzędzia pokrycia kodu potwierdzają to w 100%, ale w rzeczywistości testy tylko trafiają w kod bez analiz wyjściowych.

zasięg-kontra-osiągalny-kod

Rusłan Dżabbarow
źródło