Jeżeli mamy kod na przykład do skomplikowanych obliczeń, to możemy go przetestować w sposób manualny, czyli poprzez uruchomienie aplikacji, zalogowanie się, przejście do odpowiedniej zakładki gdzie wykonywane są obliczenia, następnie musimy wypełnić formularz i kliknąć odpowiedni przycisk - dopiero wtedy sprawdzimy wynik. Taki sam zabieg trzeba przeprowadzić dziesiątki razy, dla różnych wartości. Krótko mówiąc, nie jest to dość przyjemne zadanie i zajmuje to dużo czasu. Dlatego właśnie powstały testy automatyczne.
Dzięki testom automatycznym możemy ten sam proces przetestować dużo szybciej. Wystarczy napisać zwykłą metodę testującą skomplikowane obliczenia, które chcemy sprawdzić. Następnie odpalamy i po ułamku sekundy (w zależności jaki to test) znamy już wynik. W ten sposób możemy testować nasze obliczenia dla różnych parametrów wejściowych.
Jakie są zalety testów automatycznych?
#1 Testowanie kodu częściej oraz szybciej.
Jeżeli testy automatyczne wykonują się szybciej niż manualne, to możemy je testować dużo częściej. Nie musimy przeklikiwać całej aplikacji, żeby przetestować odpowiednią funkcję.
#2 Wyłapywanie błędów przed wdrożeniem na produkcję.
Dzięki dobrym testom już przed wdrożeniem na produkcję wyłapujemy dużo błędów. Oczywiście nie jesteśmy w stanie wyłapać wszystkich błędów, ale na pewno (mówią o tym przeprowadzone badania) ilość błędów w projektach, gdzie pisane są testy automatyczne, jest mniejsza, niż w projektach bez takich testów.
#3 Łatwiejsza refaktoryzacja kodu.
Refaktoryzacja to proces, który ciężko przeprowadzić bez testów. Nie mając testów po przeprowadzonej refaktoryzacji powinniśmy przeklikać całą aplikację w obawie przed błędami regresyjnymi. Jeżeli jednak mamy testy, to bez obaw możemy podjąć się refaktoryzacji kodu i jeżeli będą jakieś błędy regresyjne to nasze testy, powinny je wyłapać (jeżeli są dobrze napisane).
#4 Lepsza jakość kodu.
Aby móc pisać testy automatyczne, nasz kod musi trzymać się pewnych zasad. Między innymi zasad SOLID oraz wzorców projektowych.
#5 Łatwiejsze utrzymywanie kodu.
Dodawanie nowych funkcjonalności do naszej aplikacji jest łatwiejsze, po każdej zmianie możemy sprawdzić, czy kod nie zepsuł się w jakimś innym miejscu. Stosujemy się do dobrych praktyk, przez co z definicji nasz kod powinien być łatwiejszy do utrzymywania.
#6 Dokumentacja kodu.
Dość ważny punkt, o którym nie możemy zapomnieć. Dzięki stosowaniu prawidłowych konwencji nazewniczych nasze testy powinny być dobrą dokumentacją. Dzięki temu, jeżeli nowy programista dołączy do zespołu i nie będzie rozumiał jakiegoś kawałka kodu, wystarczy, że spojrzy do dobrze opisanych metod testowych.
Jakie są wady testów automatycznych?
#1 Dwukrotnie dłuższy czas na napisanie kodu.
Mówi się, o tym, że największą wadą pisania testów automatycznych jest to, że przynajmniej na początku około dwukrotnie wydłuża się czas pisania naszego kodu, ponieważ do nowej metody musimy pisać równolegle testy. Nie jest to do końca prawdą, ponieważ czasu pisania kodu faktycznie może się trochę wydłużyć, ale nie aż dwukrotnie. Rozwijając kod produkcyjny, musimy również rozwijać kod testów (który również powinien być traktowany jak kod produkcyjny). Należy jednak na to patrzeć trochę inaczej, ponieważ faktycznie czas pisania kodu się wydłuża, ale w perspektywie długofalowej, dzięki testom zyskujemy ten czas w późniejszym terminie - podczas wdrażania. Po wdrożeniu mamy około 90% mniej błędów na produkcji i dzięki temu w praktyce, dzięki testom czas powinien być krótszy, a nie dłuższy.
#2 Skupianie się na lepszej jakości kodu.
Tak naprawdę to powinna być zaleta (i faktycznie tak jest!), ale zależy z której strony na to spojrzeć. Stosowanie się do dobrych zasad programowania wymaga jednak odpowiedniej wiedzy, przez co próg wejścia może być trochę wyższy.
Jakie są rodzaje testów automatycznych?
#1 Testy jednostkowe.
Testowanie bez zewnętrznych zależności (takich jak pliki, baza danych, webserwis itp). Małe testy, które testują pojedyncze jednostki. Takich testów pisze się najwięcej, są bardzo szybkie.
#2 Testy integracyjne.
Testowanie kilku jednostek, metod z zewnętrznymi zależnościami. Są wolniejsze od testów jednostkowych.
#3 Testy end-to-end.
Testowanie aplikacji poprzez interfejs użytkownika, np. Selenium. Testy E2E są najwolniejsze.
Techniki pisania testów
Są 2 techniki pisania testów:
-Pisanie testów zaraz po napisaniu kodu.
-Pisanie testów przed napisaniem kodu - TDD (Test Driven Development, czyli kod sterowany testami).
Zalecane jest stosowanie techniki TDD, czyli pisanie testów przed napisaniem oprogramowania. Jednak pisanie testów po napisaniu kodu (to znaczy równoległe pisanie kodu i testów, ale najpierw kodu) jest lepsze niż brak pisania jakichkolwiek testów. Gdy piszemy testy po kodzie, dobrze jest sprawdzać, czy te testy sprawdzają to, co powinny. Najlepiej zrobić to poprzez chwilowe zakomentowanie kodu produkcyjnego i sprawdzenie, czy test pokazuje wtedy błąd (trzeba pamiętać, żeby kod następnie odkomentować, ale o tym przypomną nam testy).
Piramida testów
W aplikacjach najwięcej powinno być testów jednostkowych (łatwych do napisania i szybkich), mniej testów integracyjnych, a najmniej testów e2e (najwolniejszych) - jest to tak zwana "piramida testów".
Frameworki
Aby pisać testy jednostkowe i integracyjne potrzebujemy odpowiedniego frameworka. Programiści C# mają do wyboru dużo różnych frameworków (programiści innych języków również mają do wyboru różne frameworki, jednak ten artykuł piszę z myślą o programistach C#), jednak najpopularniejsze z nich to MSTest, xUnit.net, NUnit. Ja jednak zalecam użyć NUnit lub xUnit, oba mają wszystkie potrzebne funkcjonalności do pisania dobrych testów. MSTest jest dobry dla prostych testów, ale brakuje mu bardziej zaawansowanych funkcjonalności, które mają oba pozostałe. Frameworki NUnit i xUnit.net różnią się jedynie składnią, nie ma znaczenia, na który z tych dwóch frameworków się zdecydujesz - oba są dobre. W kolejnych artykułach moje przykłady będę przedstawiał w NUnit.
Konwencja nazewnicza
Najlepszą praktyką do pisania testów jest dodanie do solucji dwóch nowych projektów. Jeden z nich dla testów jednostkowych, a drugi do testów integracyjnych. Na przykład dla projektu o oryginalnej nazwie "Project" nasza struktura może wyglądać następująco:
-Project
-Project.UnitTests
-Project.IntegrationTests
Zazwyczaj jednej klasie testowanej, powinna odpowiadać jedna klasa testowa. Do nazwy dopisując Tests, na przykład dla klasy Calculator, klasa testująca powinna się nazywać CalculatorTests.
Nazewnictwo metod jest różne. Ważne żeby było spójne dla całego projektu. Najbardziej popularna konwencja jest taka:
MetodaTestowana_Scenariusz_OczekiwaneZachowanie
Czyli chcąc testować metodę Add w klasie Calculator, metoda testująca może mieć taką nazwę:
Add_WhenCalled_ReturnSumOfArguments
PODSUMOWANIE
Testy automatyczne są dość obszernym tematem. Moim zdaniem warto zaznajomić się z tematem testów, bo w większości firm, w których będziecie pracować, będą wymagać znajomości testów automatycznych, co jest bardzo dobre. Dzięki testom nasz kod jest lepszej jakości. Przy okazji, rekruterzy na rozmowach kwalifikacyjnych lubią zadawać pytania o testy automatyczne. W najbliższym czasie postaram się na blogu dodać kilka artykułów o testach jednostkowych, a także integracyjnych.
Poprzedni artykuł - Programowanie Zgodne z Regułami SOLID - Poradnik Dla Początkujących Programistów.
Następny artykuł - Testy Jednostkowe 100% Tego, Co Musisz O Nich Wiedzieć.