Jedną z rzeczy związanych z automatycznym testowaniem jest to, że wymaga ono napisania kodu, aby można go było przetestować. Nie jest to samo w sobie złe (w rzeczywistości jest dobre, ponieważ zniechęca do wielu praktyk, których z reguły należy unikać), ale jeśli próbujesz zastosować testy jednostkowe do istniejącego kodu, prawdopodobnie nie zostało napisane w sposób sprawdzalny.
Rzeczy takie jak singletony, metody statyczne, rejestry, lokalizatory usług itp. Wprowadzają zależności, które bardzo trudno wyśmiewać. Naruszenie prawa Demeter oznacza, że zbyt wiele części twojej bazy kodu wie zbyt wiele o tym, jak działają inne części twojej bazy kodu, wprowadzając kolejne ukryte zależności, które mogą być trudne do złamania. Wszystkie te rzeczy utrudniają izolowanie modułu od reszty podstawy kodu, a jeśli nie możesz przetestować modułów w izolacji, testy jednostkowe tracą wiele z ich wartości. Jeśli test się nie powiedzie, czy to z powodu usterki testowanego urządzenia, czy z powodu jednej z jego zależności, a może dlatego, że dane pobierane przez zależne źródło danych nie są tym, czego oczekiwał pisarz testu ? Jeśli możesz'
Większość baz kodu, które widziałem, a które nie zostały zbudowane z myślą o testowaniu jednostkowym, są z natury niestabilne, ponieważ koderzy skupiają się na tym, aby kod działał tak, jak tego oczekują, niż na wykonywaniu pracy niezbędnej do luźnego łączenia i jawnego określania zależności . Kod napisany z myślą o testowaniu jednostkowym ma zwykle inny wygląd.
Wiele osób naiwnie podchodzi do testowania jednostkowego, kiedy zaczynają to robić po raz pierwszy, myślą, że mogą po prostu napisać mnóstwo testów dla istniejącej bazy kodu i wszystko będzie dobrze, ale to nigdy nie działa tak z powodu wyżej wymienione problemy. Zaczynają odkrywać, że muszą przesadzić z konfiguracją w testach jednostkowych, aby w ogóle je uruchomić, a wyniki często są wątpliwe, ponieważ brak izolacji w kodzie oznacza, że nie można wyśledzić, co spowodowało błąd testu. Zaczynają też od próby napisania „sprytnych” testów, które pokazują bardzo abstrakcyjny aspekt działania systemu. Zwykle kończy się to niepowodzeniem, ponieważ „sprytny” test jednostkowy sam w sobie jest potencjalnym źródłem błędów. Czy test zakończył się niepowodzeniem z powodu błędu w testowanym module, lub z powodu błędu w teście? Test powinien być tak strasznie prosty, że oczywiście nie ma możliwości ukrycia się w nim błędu. W rzeczywistości najlepsze testy rzadko mają więcej niż 2 linie, pierwsza linia instruuje testowaną jednostkę, aby coś zrobiła, a druga zapewnia, że to, co zrobiła, było zgodne z oczekiwaniami.
Jeśli Twój zespół poważnie podchodzi do testowania jednostkowego, nierozsądne byłoby rozpoczęcie od istniejącego projektu. Istniejące projekty twojego zespołu są prawdopodobnie niemożliwe do przetestowania bez poważnego refaktoryzacji. Lepiej jest użyć nowego projektu jako podstawy do nauki o testach jednostkowych, ponieważ masz czystą kartę do pracy. Możesz zaprojektować nową bazę kodu, aby faworyzować wstrzykiwanie zależności w stosunku do singletonów, rejestrów i innych takich ukrytych zależności, możesz napisać ją tak, aby zależała od interfejsów zamiast implementacji i tak dalej. Możesz także (i powinieneś) napisać testy obok testowanego kodu, ponieważ późniejsze pisanie testów skutkuje testami jednostkowymi, które upewniają się, że testowany moduł robi to, co Twoim zdaniem powinno być przeznaczone, a nie testuje to, co robi co mówią specyfikacje.
Gdy już nabędziesz pewności co do testów jednostkowych, Twój zespół prawdopodobnie zacznie zdawać sobie sprawę z wad w istniejącym kodzie, które będą przeszkodą w testach jednostkowych. Wtedy możesz rozpocząć pracę nad refaktoryzacją istniejącego kodu, aby był bardziej testowalny. Nie bądź ambitny i staraj się zrobić to wszystko na raz, albo spróbuj zastąpić system, który działa całkowicie nowym, po prostu zacznij od znalezienia bitów bazy kodu, które można łatwo przetestować (tych, które nie mają wszelkie zależności lub jeśli zależności są oczywiste) i napisz dla nich testy. Wiem, że powiedziałem, że napisanie testu obok kodu jest lepsze niż pisanie testów po, ale nawet test napisany później nadal ma wartość jako punkt wyjścia. Napisz testy, jakbyś nic nie wiedział o tym, jak działa klasa, poza tym, co mówi jej specyfikacja. Po uruchomieniu testów i uzyskaniu błędów może to oznaczać, że specyfikacja lub implementacja są nieprawidłowe. Sprawdź dokładnie oba, aby ustalić, który jest zły, i odpowiednio zaktualizuj test lub kod.
Po zerwaniu nisko wiszących owoców rozpoczyna się prawdziwa praca. Musisz zacząć znajdować ukryte zależności w bazie kodu i poprawiać je pojedynczo. Nie bądź zbyt ambitny w tym momencie, po prostu trzymaj się jednego modułu na raz, lub nawet tylko jednego problemu w jednym module, dopóki przeszkody w testowaniu nie zostaną naprawione i możesz przejść do następnego.
TL: DR: Większość ludzi uważa, że testowanie jest łatwe i można łatwo modyfikować testy w istniejącym kodzie. Oba te założenia są błędne. Jeśli zdecydujesz się na testowanie jednostkowe w swoich projektach, mając na uwadze oba te fakty, bardziej prawdopodobne jest, że odniesiesz sukces.