W mojej firmie kilkakrotnie próbowaliśmy wprowadzić automatyczne testy programistyczne. Nasz zespół kontroli jakości używa Selenium do automatyzacji testów interfejsu użytkownika, ale zawsze chciałem wprowadzić testy jednostkowe i testy integracyjne. W przeszłości za każdym razem, gdy próbowaliśmy, wszyscy byli podekscytowani przez pierwszy miesiąc lub dwa. Po kilku miesiącach ludzie po prostu przestają to robić.
Kilka uwag i pytań:
Czy testy automatyczne faktycznie działają? Większość moich kolegów, którzy pracowali w innych firmach, próbowało i nie wdrożyło automatycznej strategii testowania. Nadal nie widziałem prawdziwej firmy programistycznej, która faktycznie z niej korzysta i nie mówi tylko o tym. Tak wielu programistów postrzega automatyczne testowanie jako coś, co jest świetne w teorii, ale nie działa w rzeczywistości. Nasz zespół biznesowy chciałby, aby programiści zrobili to nawet kosztem 30% dodatkowego czasu (przynajmniej tak twierdzą). Ale programiści są sceptyczni.
Nikt tak naprawdę nie wie, jak prawidłowo przeprowadzić automatyczne testy. Tak, wszyscy przeczytaliśmy przykłady testów jednostkowych w Internecie, ale użycie ich do dużego projektu to coś zupełnie innego. Głównym winowajcą jest wyśmiewanie / kasowanie bazy danych lub wszystkiego innego, co nie jest trywialne. W końcu spędzasz więcej czasu na kpinach niż pisanie rzeczywistych testów. Wtedy, kiedy zaczyna pisać dłużej niż test, wtedy się poddajesz.
Czy są jakieś dobre przykłady testów jednostkowych / testów integracji systemu stosowanych w złożonych aplikacjach internetowych zorientowanych na dane? Jakieś projekty open source? Nasza aplikacja jest skoncentrowana na danych, ale ma również wiele logiki domeny. W pewnym momencie wypróbowałem podejście do repozytorium i okazało się, że jest całkiem dobre do testowania jednostkowego, ale kosztowało to możliwość łatwej optymalizacji dostępu do danych i dodało kolejną warstwę złożoności.
Mamy duży projekt realizowany przez 20 doświadczonych programistów. Wydaje się, że jest to idealne środowisko do wprowadzenia testów jednostkowych / testów integracyjnych.
Dlaczego to nie działa dla nas? Jak sprawiłeś, że działało w Twojej firmie?
źródło
Odpowiedzi:
Najtrudniejszą częścią robienia testów jednostkowych jest sprawienie, by dyscyplina pisała testy najpierw / wcześnie. Większość programistów jest przyzwyczajona do nurkowania w kodzie. Spowalnia również proces programowania na wczesnym etapie, gdy próbujesz dowiedzieć się, jak napisać test dla kodu. Jednak w miarę doskonalenia się w testach przyspiesza to. A z powodu testów pisania początkowa jakość kodu zaczyna się od wyższej.
Na początku staraj się pisać testy. Na początku nie przejmuj się tak bardzo kpiną / karczowaniem rzeczy. Uprość testy. Testy są kodem i mogą / powinny być refaktoryzowane. Mimo tego, jeśli coś jest trudne do przetestowania, może to być również projekt. TDD dąży do wykorzystywania większości wzorców projektowych (z mojego doświadczenia, szczególnie wzorca fabrycznego).
Upewnij się, że testy uzyskują poziom widoczności. Zintegruj je w procesie wydania, podczas przeglądu kodu zapytaj o nie. Wszelkie znalezione błędy powinny przejść test. Te rzeczy świecą TDD.
Oto kilka zasobów, które uznałem za przydatne:
http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
http://www.agitar.com/downloads/TheWayOfTestivus.pdf
Edytować:
Jedną z rzeczy, o których należy pamiętać, pisząc testy. Nie próbujesz nic określać na temat implementacji kodu, tylko zachowanie. Kiedy piszesz kod, cały czas go testujesz. Próba wykonania go za pomocą instrukcji debugowania i tak dalej. Pisanie testów formalizuje to i zapewnia zapis posiadanych testów. W ten sposób możesz pewnie sprawdzić swoją funkcjonalność bez przypadkowego pominięcia przypadku testowego, który zapamiętałeś w połowie procesu programowania.
źródło
Pod wieloma względami zgadzam się z twoim zespołem.
Większość testów jednostkowych ma wątpliwą wartość. Ponieważ zdecydowana większość testów wydaje się zbyt prosta.
O wiele trudniej jest napisać dobry testowalny kod niż tylko działający kod. Istnieje duży odsetek społeczności programistów, która wierzy w to, że po prostu działa, a sama jakość kodu / projektu. I jeszcze większy odsetek, który nawet nie wie, co to jest kod jakości.
Napisanie kodu testu jednostkowego może potrwać znacznie dłużej niż samego kodu.
Wymyślenie, jak odpowiednio przetestować bardziej skomplikowany kod (tj. Rzeczy, które naprawdę chcesz dokładnie przetestować) wykracza poza możliwości wielu programistów.
Utrzymanie testów jednostkowych zajmuje zbyt dużo czasu. Małe zmiany mogą mieć duże efekty tętnienia. Głównym celem automatycznych testów jednostkowych jest ustalenie, czy zmiany złamały kod. Jednak 99% przypadków, w których zerwanie kończy się, to testy, a nie kod.
Mimo wszystkich powyższych problemów nadal nie ma lepszego sposobu na wprowadzenie zmian w kodzie i mieć pewien poziom pewności, że coś nie niespodziewanie się zepsuło, niż automatyzacja testów.
Niektóre z powyższych można w pewnym stopniu złagodzić, nie przechodząc do podręcznika testów jednostkowych.
Wiele typów projektów / aplikacji jest lepiej testowanych poprzez automatyzację testów na poziomie modułu / pakietu. Z mojego doświadczenia wynika, że większość błędów kodowania nie wynika z tego, że kod w klasie został nieprawidłowo zakodowany, ale dlatego, że koder nie rozumiał, w jaki sposób ich klasa powinna współpracować z innymi klasami. W tego typu testach widziałem dużo plusów. Ale jeszcze raz testy te są trudniejsze do napisania niż testy jednostkowe (na poziomie klasy).
To naprawdę sprowadza się do tego, czy programiści wierzą w ten proces, czy nie. Jeśli tak, to napiszą dobre testy jednostkowe, wcześnie znajdą błędy i zostaną zwolennikami. Jeśli tego nie zrobią, wówczas ich testy jednostkowe będą zasadniczo bezużyteczne i nie znajdą żadnych błędów, a ich teoria testów jednostkowych bezużyteczności zostanie udowodniona (ich zdaniem).
Najważniejsze jest to, że nigdy nie widziałem, aby w pełni stosowane automatyczne testy jednostkowe działały przez ponad kilka miesięcy, ale pomysł automatycznych testów jednostkowych wciąż się utrzymuje, chociaż jesteśmy selektywni w tym, co naprawdę wymaga testowania. Podejście to ma zwykle mniej krytyków i jest bardziej akceptowane przez wszystkich programistów niż tylko kilku.
źródło
Frobinate()
metodę najwyższego poziomu (zamiast kilkudziesięciu mniejszych metod nazywanych poniżej) po zweryfikowaniu systemu innymi metodami jako test dymu, że żadna zmiana niższego poziomu niczego nie zepsuła. Zasadniczo w tych testach wykorzystano te same dane, które były częścią funta w testach użytkownika klawiatury, aby klient mógł zobaczyć, że system robi to, co chce. Następnie narzędzia pokrycia kodu mogą zidentyfikować przypadki, w których przypadki krawędzi nie są jeszcze uwzględniane.I jest twój problem.
Wszyscy dobrze oceniają integrację testów jednostkowych w swoim środowisku. Jak zmusić ludzi do zrobienia tego na tyle, aby dostrzegli wartość praktyczną i „przykleiła się”. Ale jeśli jest to bardzo bolesne i / lub nie przynosi żadnych korzyści, nie będzie się trzymać.
Stubbing bazy danych powinien być bardzo prosty. Zamiast interfejsu przechodzić do kopii zapasowej bazy danych w celu zapewnienia jej wyników, wstawiasz prosty obiekt zakodowany na stałe. Jeśli nie możesz tego zrobić, Twój projekt / architektura ma problemy. Twój kod zakłada, że trafia on do bazy danych, lub nie masz abstrakcji interfejsu, aby go różnicować.
To nie jest tylko kwestia testowania / jakości. Gdy tylko chcesz zmienić dostawców DB lub przejść do chmury lub obsługiwać niepowiązane aplikacje mobilne, Twój projekt po prostu kończy się niepowodzeniem. Jeśli nie możesz obsłużyć najprostszych przypadków elastyczności, z pewnością nie możesz obsłużyć bardziej złożonych rzeczy, których Twoja firma nieuchronnie będzie wymagać.
źródło
Musisz zacząć od czegoś małego, łatwego do zautomatyzowania i wysokiej wartości. Ściągnij słodkie, nisko wiszące owoce, a będziesz mógł sprzedać cały proces. Pokaż, jak uratowało to kogoś późną noc lub połączenie weekendowe. Następnie możesz rozwinąć się stamtąd.
Aby dobrze przeprowadzić automatyczne testowanie, potrzebujesz kogoś, kto jest zasobem i ewangelistą i który dokonał zakupu od kierownictwa wyższego poziomu.
Traktuj swój rozwój testów automatycznych jak każdy inny zwinny projekt. Regularnie produkuj ukończone testy.
Dodanie z komentarza: To bardziej problem zarządzania. Czy kod jest uważany za „gotowy”, zanim zostanie udokumentowany? Przed odprawą? Czy obejmuje i przechodzi testy jednostkowe?
To, jak do tego podejdziesz, zależy od twojej roli. Jesteś rówieśnikiem? Jeśli tak, pokaż innym, w jaki sposób ułatwia im ponowne użycie i utrzymanie kodu. Czy jesteś liderem? Wybierz swojego programistę, który ma najwięcej problemów z kodem i pomóż mu dodać testy, aby uniknąć tych problemów. Jesteś szefem? Ustaw jako standard, że „kod nie jest wykonywany, dopóki testy jednostkowe nie zostaną zakończone pomyślnie.
źródło
Postępuj zgodnie z tymi podstawowymi zasadami. Testy:
musi biec regularnie! Możesz uruchamiać testy na każdej kompilacji, przed / po każdym zameldowaniu lub po prostu każdego ranka. Wyzwalanie automatyczne jest wysoce zalecane niż uruchamianie ręczne. Ponieważ choć teoretycznie możesz sprawić, że wszyscy członkowie zespołu będą odpowiedzialni za przeprowadzenie testów, jeśli nie jest zautomatyzowany, prawdopodobnie nie dzieje się to wystarczająco często! A jeśli nie uruchamiasz wystarczająco często swoich testów, oba znajdują błędy zbyt późno, zachęcając do wielu zepsutych testów, co prowadzi do punktu 2:
Nadal odniesiesz sukces tylko wtedy, gdy te testy, teraz regularnie przeprowadzane, nie przeszkadzają . Rozumiemy przez to testy:
za. nie może zająć zbyt długo (subiektywnie) dla wartości, którą zapewniają! Spraw, by Twoje testy płonęły szybko. Nie pozwól ludziom sprawdzać testów, które będą stratą twojego czasu, aby pozwolić im działać!
b. nie może być zawodny. Jeśli to możliwe, unikaj testów wielowątkowych. Zastosuj praktyki inżynierskie do swoich testów, tak jak twój drugi kod: w szczególności - sprawdź swoje testy!
do. nie może być trudniejsze do naprawienia i utrzymania niż rzeczywisty testowany kod. Twoja prędkość kodowania naprawdę będzie do bani, jeśli drobna zmiana linii bazowej w jednej linii wymaga naprawy 10 różnych testów.
I wreszcie reguła numer 3. Testy muszą nie tylko nie dawać wartości ujemnej, ponieważ w regule 2 muszą zapewniać wartość dodatnią. Testy ...
Jednym z popularnych sposobów na złamanie zasady nr 3 jest przetestowanie niewłaściwej rzeczy . Jest to czasami spowodowane tym, że test jest zbyt duży lub zbyt nieostry. Zazwyczaj jednak wynika to z nie testowania czegoś, na czym będzie dbał klient, i testowania nieistotnych szczegółów implementacji. (Czasami jednak testowanie szczegółów implementacji jest również skutecznym testem - IMO po prostu podejmuje decyzję, które z nich.)
Wniosek: te podstawowe zasady wskazują ogólny kierunek zrównoważonej dyscypliny testowania, której desperacko pragniesz. Podczas testowania zadaj sobie pytanie, czy ten test jest naprawdę trwały i łatwy do utrzymania. Zapamiętaj:
Testowanie jest w rzeczywistości trudne. Powinieneś oczekiwać, że testy twojego zespołu będą w zasadzie ssać, kiedy zaczniesz pisać testy . Nie zniechęcaj się. Nie wyrzucaj starych testów, gdy zauważysz, że ssać i są nie do utrzymania.
źródło
Tak, jeśli tak, to właściwie. Chodzi o to, że testerzy muszą dostosować i rozszerzyć swoje automatyczne skrypty po tym, jak inżynierowie wdrożą nowe funkcje.
Poproś o konsultanta (kogoś, kto wie, jak to zrobić poprawnie). Lub zainwestuj więcej czasu. Alternatywą jest posiadanie większego zespołu testującego, który wykonuje te same testy ręcznie (co jest podatne na błędy).
Nie nazwałbym ich „dobrymi doświadczonymi programistami”, gdyby odmówili wykonania testów jednostkowych. Jest wiele świetnych artykułów o pozytywnych korzyściach z testowania (zarówno testowanie jednostkowe, jak i integracyjne), a na koniec sprowadza się to do tego, ile błąd kosztuje Twoja firma . Na przykład pracuję w firmie, w której liczy się jakość, dlatego testy jednostkowe i integracyjne są nieuniknione. Możesz łatwo znaleźć wiele artykułów, które mówią, że tylko testy jednostkowe zmniejszają liczbę błędów o 30%! (W rzeczywistości mieści się w przedziale 20–90%, średnio 30%, ale wciąż dużo.)
Aby działało w Twojej firmie, zatrudnij konsultanta lub powierz to zadanie starszemu inżynierowi (wykonanie go zajmie mu trochę czasu). A potem zmuś wszystkich do przestrzegania zasad.
źródło
Jest wiele powodów, dla których wprowadzenie testów automatycznych może się nie powieść. Myślę, że sprowadza się to do tego, że programiści nie zmieniają swoich zwyczajów kodowania i nie są w pełni zdolni do przyjęcia testów jednostkowych.
Wiele osób, które chcą rozpocząć od automatycznego testowania, próbuje wprowadzić je do istniejącej bazy kodu. Spróbują napisać testy integracyjne, które testują jednocześnie wiele funkcjonalności istniejącej aplikacji. Takie testy integracyjne są notorycznie zbyt trudne i zbyt drogie w utrzymaniu. Rada: Wprowadź automatyczne testy dla nowej bazy kodu.
Testy jednostkowe to dobre testy do zautomatyzowania. Wszystko powyżej (testy integracyjne, testy komponentów, testy systemowe) można również testować automatycznie, ale stosunek kosztów do korzyści gwałtownie spada, im więcej funkcji jest testowanych jednocześnie. Ten negatywny efekt zostanie wzmocniony, jeśli zbudujesz takie testy na słabo przetestowanych jednostkowo funkcjach. Rada: Wprowadź zautomatyzowane testy na poziomie testów jednostkowych i zbuduj automatyczne testy integracyjne na solidnych podstawach testów jednostkowych .
Z powyższych punktów wiele sukcesów testów automatycznych zależy od skuteczności testów jednostkowych. Masz skuteczne testy jednostkowe, jeśli czujesz się produktywny dzięki testom jednostkowym. Kiedy ludzie zaczynają od testowania jednostkowego, mają tendencję do modyfikowania istniejącego kodu i nawyków kodowania w testach jednostkowych. Jak na ironię jest to najtrudniejszy sposób na naukę testów jednostkowych. Również testowanie jednostkowe wymaga zmiany sposobu kodowania (na przykład stosowania zasad SOLID ). Większość programistów wkrótce przestaje pisać testy jednostkowe, ponieważ uważa, że krzywa uczenia się jest zbyt stroma i trudno jest owijać testy jednostkowe wokół niezbyt testowalnego kodu. Rada: Naucz się testowania jednostkowego od podstaw z nowym kodem i poradzić sobie z faktem, że musisz zmienić swoje nawyki kodowania.
Istnieje wiele innych czynników, ale zauważyłem, że dla większości programistów zmiana sposobu pisania kodu jest trudna. Kod napisany bez testu wygląda po prostu inaczej. Jeśli nie możesz wycisnąć kodu do projektu, który można przetestować, najprawdopodobniej nie uda Ci się napisać skutecznych testów jednostkowych. To niszczy grunt pod skuteczne testy automatyczne.
Sam tego doświadczyłem i cieszę się, że mogę pracować w firmie, która z powodzeniem wprowadziła zautomatyzowane testy. Mógłbym napisać dużo więcej o innych czynnikach, ale myślę, że najważniejsze są nawyki kodowania i testowanie jednostkowe. Na szczęście są inni, którzy mają więcej doświadczenia niż ja i wypełniają książki swoją wiedzą. Jedną z tych książek jest Brownfield Application Development w .NET, którą naprawdę mogę polecić, ponieważ używasz stosu technologii Microsoft.
źródło
Introduce automated tests on the unit test level and build automated integration tests on a solid foundation of unit tests.
+1Jedną z rzeczy, których nie widziałem wyraźnie w powyższych odpowiedziach, jest to, że testy jednostkowe są zasadniczo dobrem publicznym i prywatnym kosztem. Pisałem na blogu o tym tutaj .
Sprowadza się to do tego, że chociaż zestaw testów przynosi korzyści zespołowi lub indywidualnemu deweloperowi, napisanie testu jest kosztem dla tego, który to robi, przez większość czasu.
Krótko mówiąc, chyba że pisanie testu jest w jakiś sposób wymuszone - a powyższe odpowiedzi zawierają szereg różnych sposobów na wykonanie tego - indywidualny programista nie ma powodu, aby to robić.
W jednej firmie, w której pracowałem, pisanie testów jednostkowych było wymaganą częścią dostarczania funkcji. Nowy kod nie został zaakceptowany, chyba że test jednostkowy był częścią zatwierdzenia lub nową funkcją - były krótkie recenzje kodu dla każdego „zadania” otrzymanego od programisty. Warto wdrożyć podobną politykę w swoim miejscu pracy.
źródło
Interesujące jest to, że firma jest bardziej pro-testująca niż deweloperzy! Wydaje mi się, że twoim największym wyzwaniem będzie przezwyciężenie oporności programistów na zmiany; muszą ponownie zdefiniować swoje rozumienie swoich zadań, aby uwzględnić testy jednostkowe.
Nic nie może pomóc bardziej niż wczesne sukcesy w testowaniu jednostkowym, aby pomóc programistom przezwyciężyć ich odporność na pisanie tych testów. Jeśli popchniesz ich, aby zrobili coś nowego, upewnij się, że najpierw naciskasz na coś z prawie gwarantowaną nagrodą.
@ SkipHuffman poruszył ten temat, ale powiem to wprost. Niektóre rzeczy są znacznie bardziej dostosowane do testów automatycznych niż inne. W przypadku pierwszego przejścia NIE przetestowałbym bazy danych ani interfejsu użytkownika. Dane wejściowe z bazy danych mogą być bardzo trudne do skonfigurowania i wyburzenia. Testy wyjściowe interfejsu użytkownika są zwykle niszczone przez zmiany wyglądu, które są całkowicie nieistotne dla twoich testów.
To, co nazwałbym „oprogramowaniem pośrednim”, jest idealne do testowania jednostkowego. Kod, który ma jasno zdefiniowane warunki wejściowe i wyjściowe. Jeśli będziesz przestrzegać zasady DRY (Don't Repeat Yourself), napisałeś kilka małych klas lub funkcji, aby rozwiązać powtarzające się problemy, które są unikalne dla twojej aplikacji.
Testy jednostkowe są doskonałym narzędziem do ograniczenia ryzyka zmiany istniejących komponentów wewnętrznych. Napisz testy jednostkowe przed zmianą wewnętrznego komponentu, który działał przez długi czas. Testy te dowodzą, że obecnie działająca funkcjonalność jest zachowana. Po dokonaniu zmiany i przejściu wszystkich testów jednostkowych wiesz, że nic nie zniszczyłeś „na dole”. Jeśli znajdziesz problem związany z dalszym rozwojem, dodaj test jednostkowy!
Ron Heifitz powiedziałby, że „rozwiązuje konflikty w wartościach, które wyznają ludzie, lub w celu zmniejszenia luki między wartościami, które wyznają, a rzeczywistością, z którą się spotykają. Praca adaptacyjna wymaga zmiany wartości, przekonań lub zachowania”. Po przezwyciężeniu ludzkiego oporu przed zmianami możesz odpowiednio rozgałęzić się w trudniejsze obszary testowe.
źródło
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.
źródło
Jeśli nie, inicjatywy automatycznego testowania prawdopodobnie się nie powiodą. Automatyczne testowanie to umiejętność, podobnie jak wiele innych umiejętności programowania, a jeśli nie masz nikogo z tym doświadczeniem, nie jest łatwo stwierdzić, czy test automatyczny jest dobrym testem automatycznym o rzeczywistej wartości, czy złym, który będzie kończy się przypadkowo / wymaga częstych aktualizacji / nie wykonuje żadnego interesującego kodu.
Jeśli nikt nie słucha, nie ma znaczenia, czy twierdzą, że test nie jest dobry. (Należy pamiętać, że siła przywódcza nie musi być sformalizowana. Dobrze mieć też zespół, który się tym przejmuje).
Programiści są leniwi. Musisz sprawić, by rzeczy, które chcesz, aby były łatwe do osiągnięcia, a rzeczy, których nie chcesz, by były trudniejsze do osiągnięcia. Należy upewnić się, że biblioteki testowe ułatwiają wykonywanie zadań związanych z konfiguracją testu i porzucaniem, szczególnie konfiguracją związaną ze środowiskiem, taką jak testowe bazy danych lub tym podobne. (Wyśmiewanie bazy danych jest omówione w niektórych z tych komentarzy, ale powinno się z niej korzystać ostrożnie. Prawdziwa baza danych powinna być łatwa do rozszyfrowania i umożliwia testowanie interakcji komponentów i cykli życia procesów, często ważniejsze i bardziej skuteczne niż testy jednostkowe indywidualny moduł dostępu do danych).
Powinieneś także upewnić się, że twoje IDE mają dobry sposób na uruchomienie pakietu testowego. Powinieneś często uruchamiać zestaw testowy, aby ludzie zauważyli jego awarię, zamiast pozwalać mu pozostać w nieszczęściu. Programiści reagują również dobrze na opinie, np. Zautomatyzowany system integracji cofa swoje zmiany, jeśli przerwie test. Lub, lepiej, pozytywne opinie: zautomatyzowany system integracji, który wyłapuje błędy i chroni Cię przed rozbijaniem rzeczy.
źródło
Po pierwsze, jeśli twoi programiści nie widzą wartości twoich testów, to prawdopodobnie dlatego, że twoje testy nie są cenne, a nie dlatego, że twoi programiści są ślepi na ich wartość lub na ogólną wartość testów. Wśród jego ewangelistów istnieje tendencja, by wierzyć, że rozwój oparty na testach nie może zawieść, a jedynie leniwi i leniwi programiści. Myślę, że to źle i przynosi efekt przeciwny do zamierzonego.
Kiedy zostałem wprowadzony do programowania opartego na testach, oznaczało to, skutecznie napisanie testu, aby sprawdzić, czy metoda, która nigdy nie zawiedzie, nigdy nie zawiedzie. Co na początku jest fajne, ponieważ dostajesz piękny zielony czek i poczucie spełnienia. Później, po przebudowaniu kodu, masz dziesiątki irytujących czerwonych X, z których żaden nie mówi nic więcej, że kod się zmienił, że testy nie są już ważne i że zmarnowałeś dużo czasu na ich pisanie.
Chcesz tego uniknąć.
Od tego czasu zastosowałem inne podejście do testów. Zamiast pary implementacji interfejsu mam interfejs, implementację, potrójny test . Interfejs określa zachowanie, implementacja wykonuje zachowanie, test sprawdza zachowanie.
Wydaje mi się, że wydaje się to oczywiste, ale dla mnie rozróżnia kod, który musisz udowodnić, działa zgodnie ze specyfikacją i kod, który możesz przetestować tyle, ile uważasz za stosowne. Kod, który musisz udowodnić, to interfejs, który oferujesz na zewnątrz; reszta jest twoją troską.
W takim przypadku zapytam programistów, czy widzą naturalny podział w kodzie, w którym ten rodzaj testu byłby odpowiedni. Czy istnieje interfejs wdrożony przez Zespół A i używany przez Zespół B? W takim przypadku w interesie zespołu B leży zapewnienie, aby interfejs zachowywał się zgodnie z oczekiwaniami. Poproś Zespół B o napisanie testu, a następnie powiedz Zespołowi A, aby upewnić się, że ich wdrożenie jest zgodne z testem; lub, jeśli nie, i celowo nie, aby omówić nieoczekiwaną zmianę z innym zespołem, aby mogli się na to przygotować.
Myślę, że to zilustruje wartość testu. To nie jest cel sam w sobie, pomimo pięknych zielonych czeków. Istnieje, aby jednoznacznie wyrazić obietnicę złożoną przez jednego programistę drugiemu i zapewnić, że obietnica dotrzymana będzie dla obu.
źródło
Dodanie wielu testów jednostkowych do dużego, wcześniej istniejącego projektu jest ciężką pracą. Jeśli już znalazłeś dobrą frameworkę, która Ci odpowiada, powinieneś rozwiązać najtrudniejszy problem.
Proponuję próbować dodawać testy w miarę dodawania funkcji / naprawiania błędów. Naprawianie błędów jest najłatwiejsze. Napisz test, który się nie powiedzie z powodu twojego błędu, a następnie napraw błąd. W tym samym czasie prawdopodobnie będziesz musiał napisać kilka prostszych testów, które przejdą pomyślnie. Oczywiście naprawdę chcesz do tego użyć małego i łatwego do przetestowania fragmentu kodu.
Kiedy ludzie zaczną przyzwyczajać się do pisania testów dla łatwiejszych rzeczy, powinniśmy mieć nadzieję, że napiszą swój kod, aby był bardziej testowalny.
Polecam również zmierzenie pokrycia kodu twoich testów ( w przeszłości korzystałem z cobertura dla Javy). Będziesz chciał mieć serwer ciągłej integracji, który będzie regularnie testował i generował metryki (codziennie, przy każdym zameldowaniu). Jeśli Twoi znajomi programiści są zainteresowani, będą chcieli zobaczyć wzrost zasięgu w miarę upływu czasu i mogą zobaczyć luki w niektórych obszarach
źródło
Myślę, że być może będziesz musiał zagrać w długą grę. Jedną rzeczą, którą możesz zrobić, aby uzyskać akceptację, jest próba wyczerpującego przetestowania jednostki kolejnej pisanej funkcji, a następnie śledzenie liczby błędów w czasie. Miejmy nadzieję, że powinieneś przekonać się, że główne błędy zostaną wyłapane wcześnie (szczególnie jeśli połączysz to z Test-Driven Design), a liczba regresji powinna być bardzo mała. Po pewnym czasie, powiedzmy 1 rok, porównaj statystyki z testami niejednostkowymi o podobnej złożoności. Jeśli potrafisz wykazać, że liczba nowych błędów i regresji jest znacznie niższa, podałeś uzasadnienie finansowe i trudniej jest ignorować zespół produktu.
Miałem sytuację, w której mogłem użyć TDD i testów jednostkowych dla ważnej funkcji. Po zakończeniu fazy rozwoju przez ponad 5 lat nie zgłoszono żadnego błędu. Kiedy zażądano nowego - i ryzykownego - rozszerzenia, byłem w stanie je wdrożyć i wyłapać wszystkie regresje w testach jednostkowych.
źródło
Uważam, że wiele zespołów nie docenia wartości testów jednostkowych ze względu na kilka czynników, z których wiele zostało już podkreślonych w odpowiedziach.
Często programiści są pod presją „załatwiania spraw”, więc udowodnienie, że blok kodu działa, jest wystarczającym dowodem dla klienta. Dotyczy to prawie zawsze firmy konsultingowej i kontroli jakości kierowanej przez człowieka: jeśli klient nie wymaga testowania jednostkowego i wystarczającą ilość demonstracji na żywo, to klient całkowicie poniósł porażkę, ponieważ zamierza podpisać zgodę na kod, który może ukrywać błędy.
Często programiści są sfrustrowani. Bycie programistą to ciężka praca: ukończenie zadania i przejście do następnego jest satysfakcjonujące, więc każdy chce się spieszyć i skończyć. Dopóki nie zostanie potrącony przez autobus z poważnym błędem, który rośnie miesiącami po oryginalnej kontroli jakości. W tym scenariuszu zautomatyzowana i ciągła kontrola jakości stanowi problem zarządzania, a nie programistów (nadal będą otrzymywać wynagrodzenie za swoją pracę, być może za nadgodziny).
Ale jest wyjątek
Mocno wierzę, że akceptacja modelu testów automatycznych jest funkcją „ludzkości” przeprowadzanych testów. Jeśli testujesz moduł internetowy z interfejsem, jest bardziej prawdopodobne, pomimo narzędzi takich jak Selenium, wypełnienie formularza samodzielnie, zobacz wynik i uwierz w determinizm. Zapomnisz o ponownym uruchomieniu testów później lub po prostu będziesz zbyt leniwy, aby ponownie wykonać stare testy, i dlatego czasami błędy są wykrywane później. Aby to wykorzystać, silna modularyzacja kodu i surowe zasady dotyczące „modyfikowania starego kodu” okazały się akceptowalne w środowisku bankowym (z mojego osobistego doświadczenia zawodowego).
Zamiast tego, jeśli programista jest odpowiedzialny za opracowanie wysoce zautomatyzowanego modułu danych o dużej objętości, będzie bardziej prawdopodobne, że napisze dokładne testy jednostkowe i prześle je do partii testowych. Wynika to z faktu, że wypełnienie dużego ładunku XML danymi przekonwertowanymi z zewnętrznego źródła danych (wyśmiewanego lub nie) nie jest zadaniem podatnym na człowieka. Niektórzy programiści testowi ostatecznie stworzą mały i zabawny interfejs dla tego rodzaju testów. Kiedy pracowałem nad pracą magisterską, pracowałem nad magistralą rejestrującą, która obsługiwała ponad 6000 komunikatów syslog na sekundę i musiałem mierzyć utratę i uszkodzenie pakietów: naturalnie napisałem testy jednostkowe i stresowe dla prawie wszystkich komponentów, zwłaszcza parsera Syslog.
Aby deweloperzy byli bardziej podatni na testy jednostkowe
Wierzę, że muszą być do tego zmuszeni. Jeśli jesteś inteligentnym klientem, będziesz wymagał od konsultantów uruchomienia pełnego zestawu testów przy każdej kontroli jakości. Jeśli jesteś dobrym liderem zespołu, możesz pomyśleć o przydzieleniu inteligentnego programisty następującego zadania: zbuduj platformę do testowania wewnętrznego. Nie ma nic do zobaczenia z antypaterami platformy z efektem wewnętrznym, ale zamiast tego jest zestaw klas pomocników, makiet baz danych, konfiguracji, parserów, konwerterów, szwajcarskich noży wojskowych, aby pomóc programistom budować testy w krótkim czasie.
Obecne platformy testowe, takie jak NUnit, są uniwersalne i umożliwiają weryfikację ogólnych twierdzeń. Prawidłowe użycie wstrzykiwania zależności i fabryk specyficznych dla projektu pomaga programistom pisać mniej kodu do testów i być szczęśliwszym. Nie miałem jeszcze okazji eksperymentować z tym przy pełnym projekcie, nie mogę zapewnić prawdziwej informacji zwrotnej.
źródło
Zautomatyzowane testowanie przypomina tworzenie oprogramowania. Niestety, osoby zatrudnione do testowania są pierwotnie przeznaczone do pisania przypadków testowych, planów, strategii, śledzenia procesu, ręcznego testowania i rejestrowania błędów.
Gdy tylko powierzone im zostaną zautomatyzowane obowiązki testowania, obejmuje to również pewien rozwój oprogramowania. Problem polega na tym, że zautomatyzowane testowanie, bez względu na to, jakich narzędzi używasz (i na litość boską, nie dyskutuj o tym), wymaga codziennej konserwacji i aktualizacji. Gdy programiści zmieniają kod,
non-functional
testy osobno i nie oczekuj, że będą je uruchamiać codziennie, potrzeba czasu, aby były one aktualne i dobre. Ale nie poddawaj się, upewnij się, że są one utrzymane.Nie udaje ci się z tych powodów
if
awhile
. Ponieważ szczerze mówiąc żaden kurs nie uczy testów automatycznych, uczą tylko testów ręcznych.Są one z mojego doświadczenia w pracy dla firm, które bardzo poważnie podchodzą do automatycznych testów i rozumieją, że deweloper jest ważny jako inżynier automatyczny. I z mojego doświadczenia pracy dla ludzi, którzy nie wiedzą, zrozum różnicę, bez względu na to, jak wiele im wyjaśnisz.
źródło