2010-11-18 15 views
6

Czytałem, że statyczne metody są zwykle pomijane podczas korzystania z TDD, ponieważ są trudne do udawania. Uważam jednak, że najłatwiejszą rzeczą w testowaniu jednostkowym jest metoda statyczna, która ma prostą funkcjonalność. Nie musisz tworzyć instancji żadnych klas, zachęca metody, które są proste, czynią jedno, są "niezależne" itp.Metody statyczne i testy jednostkowe

Czy ktoś może wyjaśnić tę rozbieżność między najlepszymi praktykami TDD i pragmatyczną łatwością?

Dzięki,

Odpowiedz

14

Metoda statyczna jest łatwe do sprawdzenia, ale coś, co nazywa się bezpośrednio generalnie metoda statyczna nie jest łatwe do sprawdzenia niezależnie od metody statycznej to zależy. W przypadku metody niestatycznej można użyć kodu pośredniczącego/fałszywego/fałszywego w celu ułatwienia testowania, ale jeśli testowany kod wywołuje metody statyczne, jest on efektywnie "połączony na stałe" z tą statyczną metodą.

+0

myślę termin szukasz ponieważ jest ściśle powiązany. –

+1

@Martin: Dzięki, znam termin, choć jest bardziej ogólny niż to, co tu robiłem. Powszechnie używane terminy często kończą się prawie tracąc znaczenie, ponieważ ludzie (ab) używają ich tak bardzo, więc zdecydowałem się użyć metafory w nadziei, że będzie to bardziej jasne. –

+0

Pierwsze przesłuchanie "hard-wired" w miejscu ściśle powiązanego. To absolutnie genialne, jak zmiana warunków może pomóc w zrozumieniu. – jrahhali

2

Łatwo przetestować metodę statyczną. Problem polega na tym, że nie ma możliwości odizolowania twojego drugiego kodu od tej statycznej metody podczas testowania drugiego kodu. Kod wywołujący jest ściśle powiązany z kodem statycznym.

Odniesienie do metody statycznej nie może być wyśmiewane przez wiele szyderczych frameworków i nie można go przesłonić.

Jeśli masz klasę, która wykonuje dużo wywołań statycznych, to aby ją przetestować, musisz skonfigurować globalny stan aplikacji dla wszystkich wywołań statycznych - więc konserwacja staje się koszmarem. A jeśli twój test się nie powiedzie, nie wiesz, który fragment kodu spowodował awarię.

Pomyłka to jeden z powodów, dla których wielu programistów uważa, że ​​TDD to nonsens. Włożyli duży wysiłek w konserwację wyników testów, które tylko niejasno wskazują, co poszło nie tak. Gdyby ograniczyli tylko sprzężenie pomiędzy ich jednostkami kodu, konserwacja byłaby trywialna, a wyniki testu charakterystyczne.

3

Odpowiedź na zadane pytanie jest, moim zdaniem, "Obiekt zorientowany na wszystko wydaje się być wszystkim, o czym myślą ludzie TDD".

Dlaczego? Nie wiem Może wszyscy są programistami Java, którzy zostali zarażeni chorobą polegającą na tym, że wszystko zależy od sześciu warstw pośrednich, wtyczek zależności i adapterów interfejsu.

Programiści Java wydają się uwielbiać wszystko, co jest trudne z góry, aby "zaoszczędzić czas później".

Radzę zastosować pewne zasady Agile do TDD: Jeśli to nie powoduje problemu, nie naprawiaj tego. Nie przesadzaj z projektowaniem.

W praktyce uważam, że jeśli statyczne metody zostaną najpierw dobrze przetestowane, to nie będą przyczyną błędów u ich rozmówców.

Jeśli metody statyczne są wykonywane szybko, to nie potrzebują one próbnego.

Jeśli metody statyczne działają z materiałem spoza programu, może być potrzebna metoda próbna. W takim przypadku będziesz musiał symulować wiele różnych rodzajów zachowania funkcji.

Jeśli musisz wyśmiać statyczną metodę, pamiętaj, że istnieją sposoby na jej wykonanie: poza opcją programowania OO.

Na przykład można pisać skrypty w celu przetworzenia kodu źródłowego na formularz testowy, który wywołuje funkcję fałszywą.Można połączyć różne pliki obiektów, które mają różne wersje funkcji w programach testowych. Możesz użyć trików łącznika, aby zastąpić definicję funkcji (jeśli nie została wbudowana). Jestem pewien, że jest jeszcze kilka sztuczek, których tu nie wymieniłem.

+0

Zgodziłbym się z tobą w prostych przypadkach. Wiele metod statycznych to proste wywołania narzędziowe, które są statyczne, ponieważ nie mają stanu. Jednak inne wywołania statyczne odwołują się do globalnych (statycznych) zmiennych lub innych wywołań statycznych, a to może być bardzo trudne w zarządzaniu w środowisku testowania jednostkowego. Musisz upewnić się, że stan globalny jest poprawny dla każdego uruchomienia testu - albo otrzymujesz łuszczenie (testy, które działają w izolacji, ale zawodzą, gdy reszta pakietu działa). Może to być robak, ale zgadzam się, że powinieneś być pragmatyczny. – sheikhjabootie

0

Ta opinia jest prawdziwa w większości .. ale nie zawsze. Moje komentarze są nie C++ .. specyficzne testy

  1. pisania dla metod statycznych (które są pure/bezpaństwowców funkcje): to jest praca przy wejściach do wytworzenia spójnego rezultatu. na przykład Dodaj poniżej - zawsze da taką samą wartość przy danym zestawie wejść. Istnieje bez problemu w pisaniu testów dla tych lub kodu, który wywołuje takie czyste metody statyczne.
  2. Testy pisania dla metod statycznych, które zużywają statyczny stan: np. GetAddCount() poniżej. Wywołanie go w wielu testach może przynieść różne wartości. Dlatego jedno badanie może potencjalnie zaszkodzić wykonaniu innego testu - testy muszą być niezależne. Teraz musimy wprowadzić metodę resetowania stanu statycznego, aby każdy test mógł się rozpocząć od czystego arkusza (na przykład coś takiego jak ResetCount()).
  3. Pisanie testów kodu, który uzyskuje dostęp do metod statycznych , ale brak dostępu do zależności kodu źródłowego: Ponownie zależy od właściwości samych metod statycznych. Jednak jeśli są gnarly, masz trudną zależność. Jeśli zależność jest obiektem, możesz dodać setera do typu zależnego i ustawić/wstrzyknąć fałszywy obiekt do testów. Gdy zależność jest statyczna, możesz potrzebować znacznego refaktoryzacji, zanim będziesz mógł wykonać testy niezawodnie. (Np Dodawanie zależność middle-man obiektu, który deleguje do metody statycznej. Teraz wtyczki fałszywy środkowy-man dla testów)

Weźmy Przykładem

public class MyStaticClass 
{ 
    static int __count = 0; 
    public static int GetAddCount() 
    { return ++__count; } 

    public static int Add(int operand1, int operand2) 
    { return operand1 + operand2; } 

    // needed for testability 
    internal static void ResetCount() 
    { 
    __count = 0; 
    } 
} 

... 

//test1 
MyStaticClass.Add(2,3);  // => 5 
MyStaticClass.GetAddCount(); // => 1 

// test2 
MyStaticClass.Add(2,3); // => 5 
//MyStaticClass.ResetCount(); // needed for tests 
MyStaticClass.GetAddCount(); // => unless Reset is done, it can differ from 1