Standardy kodowania testów jednostkowych

22

Zwykle mówiąc o standardach kodowania, odnosimy się do kodu samego programu, ale co z testami jednostkowymi? Czy istnieją pewne wytyczne standardów kodowania, które są unikalne dla testów jednostkowych? Czym oni są?

EpsilonVector
źródło

Odpowiedzi:

12

Z góry głowy mogę wymyślić trzy różnice w stylu kodowania kodu testowego.

W metodzie testowania nazw kieruję się wzorem shouldDoSomethingWhenSomeConditionHolds.

W teście zwykle stosuje się następujący wzór odstępów:

@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
    // Some lines 
    // of setup code
    // go here.

    // The action being tested happens after a blank line.

    // An assertion follows another blank line.
}

Niektórzy nalegają na tylko jedno stwierdzenie na test, ale nie jest to uniwersalne.

DRY (Don't Repeat Yourself) jest mniej ważne w kodzie testowym niż w kodzie produkcyjnym. Podczas gdy część powtarzanego kodu należy umieścić w metodzie setUp lub klasie testUtils, dążenie do zerowego powtórzenia w kodzie testowym doprowadzi do ściśle powiązanych i nieelastycznych testów, co zniechęca do refaktoryzacji.

Eric Wilson
źródło
Oczywiście istnieje wiele wzorów, dlatego też powinieneś udzielić odpowiedzi.
Eric Wilson
10
To jest wzór Arrange, Act, Assert .
StuperUser
SUSZENIE jest nadal ważne. Jeśli musisz wykonać te same twierdzenia w wielu testach, utwórz wspólną funkcję i wywołaj ją we wszystkich testach.
MiFreidgeim SO-przestań być zły
@MichaelFreidgeim Może mówimy tylko o stopniach, ale mam znacznie wyższą tolerancję na powtarzanie w kodzie testowym. Miałem kilka doświadczeń z budowaniem zestawów testowych z bardzo małą liczbą powtórzeń i odkryłem, że testy stały się trudne do modyfikacji i zrozumienia, kiedy zmieniły się wymagania. Potem przestałem się martwić o DRY w testach, a moje zestawy testów były łatwiejsze w użyciu. <shrug>
Eric Wilson,
16

Roy Osherove zaleca następujący wzór do nazwania swoich testów:

NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior() 

Zobacz http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx

Robert Harvey
źródło
Zgadzam się z Royem. Poprawia czytelność, choć ReSharper wciąż mówi mi, że powinienem je usunąć NameOfMethodUnderTestStateUnderTestExpectedBehavior();)
Oscar Mederos
Jak sprawić, by działało, gdy metoda jest przeciążona, aby istniało wiele metod o tej samej nazwie?
Narendra Pathai
6

Najważniejsze jest, aby pamiętać, że testy jednostkowe są zasadniczo mini-specyfikacjami. Oznacza to, że zawsze należy kłaść nacisk na czytelność.

Po pierwsze, oznacza to, że nazwy muszą jasno komunikować, co jest testowane i co jest potwierdzane.

Po drugie jednak, o czym czasem się zapomina, jest to, że jako specyfikacje powinni robić właśnie to - określając zachowanie. Oznacza to, że testy jednostkowe nie powinny zawierać logiki - lub potencjalnie wpadają w pułapkę powtarzania funkcjonalności programu zamiast testowania go.

Czasami testy będą obejmować obiekty, których konfiguracja jest skomplikowana, powinieneś starać się trzymać tę logikę konfiguracji osobną od testów, używając czegoś takiego jak matka obiektu lub konstruktor danych testowych .

Zakończę kilkoma zaleceniami dotyczącymi książek:

Wzorce testowe xUnit: Refaktoryzacja Kod testowy: Doskonała książka, niektórzy twierdzą, że jest trochę sucha, ale nie sądzę. Wchodzi w wiele szczegółów na temat wielu różnych sposobów organizowania testów i sposobów ich utrzymania. Ważne, jeśli używasz czegoś takiego jak NUnit itp.

Sztuka testowania jednostkowego: z przykładami w .Net : najlepsza książka na temat drobiazgowości pisania i utrzymywania testów. Pomimo tego, że jestem naprawdę nowy, drwiące sekcje są już trochę przestarzałe, ponieważ składnia AAA jest teraz raczej standardem niż tylko innym sposobem na zrobienie tego.

Rosnące oprogramowanie obiektowe oparte na testach : ta książka jest po prostu niesamowita! Zdecydowanie najlepsza książka o testach jednostkowych i jedyna zaawansowana, która stawia testy jednostkowe jako obywatela pierwszej klasy w procesie projektowania. Czytałem to, gdy była to publiczna wersja beta i od tego czasu polecam. Doskonały przykład z prawdziwego świata zastosowany w całej książce. Poleciłbym jednak najpierw przeczytać książkę Roya.

FinnNk
źródło
IMHO jest w porządku, aby testy jednostkowe zawierały logikę: całkowicie rozsądne jest przetestowanie wysoce zoptymalizowanej, wydajnej wersji algorytmu za pomocą naiwnego algorytmu, który robi to samo, aby określić prawidłowe zachowanie. Na przykład wyobraź sobie testowanie tabeli skrótów poprzez zbudowanie liniowej tablicy asocjacyjnej opartej na wyszukiwaniu.
dsimcha
2
Tak, ale należy to do testu poza konstruktorami danych testowych (które same powinny być testowane jednostkowo, jeśli logika w nich nie jest trywialna). Wyjątkiem byłyby biblioteki stron trzecich, które na ogół są „zaufane”, że są poprawne i mogą być używane bez testów.
FinnNk
3

Nie umieszczaj logiki w testach jednostkowych. Załóżmy na przykład, że testujesz metodę dodawania, możesz mieć coś takiego:

void MyTest_SaysHello()
{
   string name = "Bob";
   string expected = string.Format("Hello, {0}", name);
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello(name);
   Assert.AreEqual(expected, actual);
}

W tym konkretnym przypadku prawdopodobnie powtarzasz tę samą logikę, co w teście, więc zasadniczo testujesz „1 + 1 == 1 + 1” zamiast „1 + 1 == 2”, czyli „prawdziwy” test. Tak więc naprawdę chciałbyś, aby Twój kod testowy wyglądał:

void MyTest_SaysHello()
{
   string expected = "Hello, Bob";
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello("Bob");
   Assert.AreEqual(expected, actual);
}
Hugo
źródło
2
Mała korekta: myślę, że miałeś na myśli „string oczekiwano = string.Format („ Hello, Bob ”)” powinien być „string oczekiwano =„ Hello, Bob ”.
Mike Rosenblum,
@MikeRosenblum masz oczywiście rację i ktoś próbował to poprawić, ale dwóch recenzentów odrzuciło tę zmianę
Konrad Morawski
@Konrad: to dziwne. To jest forum programistyczne, prawda?
Mike Rosenblum,
Ponownie zredagowałem odpowiedź zgodnie z sugestią Mike'a Rosenbluma.
bdsl,
0

Długie opisowe nazwy metod. Pamiętaj, że metody testowe nigdy nie są wywoływane z kodu (są one wywoływane przez moduł testujący jednostki, który odkrywa je i wywołuje przez odbicie), więc można szaleć i mieć nazwy metod o długości 50-80 znaków. Konkretna konwencja nazewnictwa (wielbłąd, podkreślenia, „powinien”, „musi”, „kiedy”, „dany” itd.) Nie jest tak naprawdę ważna, o ile nazwa odpowiada na trzy pytania:

  • co jest testowane?
  • jakie są warunki
  • jaki jest oczekiwany wynik?

Metody testowe powinny być krótkie .

Metody testowe powinny mieć prostą, liniową strukturę . Nie, jeśli lub konstrukcja pętli.

Metody testowe powinny być zgodne ze wzorcem „arrange-act-assert” .

Każdy test powinien przetestować jedną rzecz . Zazwyczaj oznacza to jeden assert na test. Test taki { Do A; Assert B; Assert C; }powinien zostać podzielony na dwie części: { Do A; Assert B; }i{ Do A; Assert C; }

Unikaj przypadkowych danych lub rzeczy takich jak „DateTime.Now”

Upewnij się, że wszystkie elementy urządzenia testowego powracają do pierwotnego stanu na koniec testu (np. Przy użyciu rozerwania )

Nawet jeśli bezwzględnie usuniesz powielanie w kodzie produkcyjnym, powielanie kodu w urządzeniach testowych jest znacznie mniejszym problemem.

azheglov
źródło
-1

Nieco podobny do tego, co już wspomniał Farmboy, format nazwy mojej metody

 <MethodName>Should<actionPerformed>When<Condition>

na przykład

 GetBalanceShouldReturnAccountBalance() {
Amit Wadhwa
źródło