Testy jednostkowe: „To jest zapach kodu, jeśli refaktoryzujesz i nie ma współpracowników”?

9

Czytam The Art of Unit Testing autorstwa Roy Osherove. Jestem w sekcji 7.2. Pisanie możliwych do utrzymania testów, w których autor ma notatkę o zapachu kodu:

UWAGA: Czy po przefakturowaniu stanu wewnętrznego, aby był widoczny dla testu zewnętrznego, można uznać go za zapach kodu (znak, że coś może być nie tak z projektem lub logiką kodu)? To nie jest zapach kodu, gdy refaktoryzujesz, aby ujawnić współpracowników. Jest to zapach kodu, jeśli refaktoryzujesz i nie ma żadnych współpracowników (więc nie musisz niczego stubować ani wyśmiewać).

EDYCJA : Autor rozumie przez „współpracowników” zależności. Niektóre z jego przykładów zależności są klasami, które uzyskują dostęp do bazy danych lub systemu plików systemu operacyjnego. Oto, gdzie definiuje skrót i zaczyna używać słowa współpracownik:

En jest sterowany zastąpienie istniejącej zależności (lub współpracowników ) w systemie.

Autor nie ma przykładu tego zapachu kodu i mam problem ze zrozumieniem / wyobrażeniem sobie, jak by to wyglądało. Czy ktoś może to trochę wyjaśnić i być może podać konkretny przykład?

programista
źródło
Myślę, że zamieszanie wynika tutaj ze słowa „Współpracownicy”. Muszę przyznać, że nie jestem pewien, co on ma na myśli w tym kontekście.
rossipedia,
@Bryan Ross, zaktualizowałem post o tym, jak autor używa słowa „współpracownik”. Dzięki!
programista

Odpowiedzi:

3

Myślę, że do tego zmierza autor.

W moim przykładzie kodu mam okno czasowe, które przyjmuje wielkość wyjściową oraz czas rozpoczęcia i zakończenia. Ma to na celu narysowanie okna wyjściowego w ciągu 24 godzin. Zmarszczka jest dodawana, gdy czas rozpoczęcia jest dłuższy niż czas zatrzymania, ponieważ jest to okno czasowe, które obejmuje północ.

Możesz pisać testy jednostkowe, które w pełni wykonują obiekt bez ujawniania zmiennych prywatnych. Te prywatne boole i przedziały czasowe to współpracownicy, o których mowa, ujawniając elementy wewnętrzne do testów jednostkowych. Według książki odsłonięcie tych elementów wewnętrznych NIE byłoby zapachem kodu, ponieważ są one współpracownikami.

Ujawnienie podwójnego outputbyłoby zapachem kodu, ponieważ nie jest współpracownikiem - jest to element wyraźnie ukryty przez samą klasę, który ma logikę warunkową, GetOutputaby określić, co należy zwrócić.

Zagłębianie się w wartości bools / przedziałów czasowych uczyniłoby testy jednostkowe bardziej kompleksowymi. Mówi, że to dobrze.
Wkopanie się w podwójną outputwymagałoby dodatkowej logiki w teście jednostkowym, która odzwierciedlała to, co się GetOutputdziało. To będzie zapach kodu, do którego się odnosi.

TimeWindow klasy publicznej
{
  private bool isConst;
  prywatne przedziały boolMidnight;
  prywatny TimeSpan start1;
  prywatny TimeSpan stop1;
  prywatny TimeSpan start2;
  prywatny TimeSpan stop2;
  prywatne podwójne wyjście;

  public TimeWindow (double out, TimeSpan start, TimeSpan stop)
  {
    wyjście = wyjście;

    if (start == stop)
      isConst = true;
    else if (start> stop)
    {
      spansMidnight = true;
      start1 = północ;
      stop1 = stop;
      start2 = start;
      stop2 = północ;
    }
    jeszcze 
    {
      start1 = start;
      stop1 = stop;
    }
  }

  publiczne podwójne GetOutput (czas TimeSpan)
  {
    // trochę logiki na temat tego, co / jak zwrócić
    ...
    wyjście wyjściowe;
  }

}

źródło
0

Załóżmy, że mamy klasę domeny, a ta klasa domeny ma bezpośrednią wiedzę o warstwie trwałości przy użyciu repozytorium, którego używa w celu ujawnienia metody „Zapisz” na poziomie instancji, którą obiekty działające na klasie domeny mogą wywoływać, aby zachować zmiany wykonane bez potrzeby znajomości mechanizmu (czy to „dobry” projekt to dyskusja na kolejny dzień). Refaktoryzacja klasy w celu ujawnienia tego repozytorium jako właściwości i / lub argumentu konstruktora, umożliwiając w ten sposób przekazanie fałszywego repozytorium, które może zapewnić prawidłowe wywołanie, jest zwykle dobrą rzeczą nie tylko do testowania, ale i ogólnej konserwacji.

Teraz, ponieważ jest to klasa domeny, ma dane stanu. Załóżmy przez chwilę, że jedna z właściwości stanowych ma pole bazowe, a akcesory właściwości testują, że nowe dane wejściowe są poprawne na podstawie bieżącej (być może nowa wartość nigdy nie może być mniejsza niż stara). Musisz przetestować to sprawdzanie poprawności, ale okazuje się, że wymaga to dostępu do pola zaplecza, aby ustawić wartość początkową, którą następnie spróbujesz zastąpić. To powinna być czerwona flaga; jeśli test potrzebuje dostępu do pola zaplecza (które jest szczegółem implementacji; żaden konsument nigdy nie powinientrzeba wiedzieć, że tam jest), aby uzyskać spójny stan testu, to w jaki sposób kod produkcyjny uzyska spójny obiekt? Jeśli istnieje metoda wykonania kodu produkcyjnego w taki sam sposób, jak w teście, test prawdopodobnie powinien naśladować ten sposób. Jeśli nie ma prawidłowego sposobu, aby kod produkcyjny doprowadził obiekt do tego stanu, to dlaczego testujesz ten scenariusz?

KeithS
źródło