1.1 Wprowadzenie do testowania
Rozwój aplikacji sprawia, że rośnie też prawdopodobieństwo pojawienia się błędów. Bez testowania aplikację często należałoby sprawdzać ręcznie, ale przy dużej ilości funkcjonalności będzie to pochłaniało ogromna ilość czasu.
Z pomocą przychodzi nam zautomatyzowane testowanie funkcjonalności aplikacji. Testowanie oznacza, że piszemy kod, który sprawdza, czy nie pojawiły się błędy przy wprowadzaniu zmian do naszej aplikacji.
Często to właśnie programiści piszą testy modułowe. Modułowe testowanie wykonuje sprawdzenie logiki aplikacji na poziomie funkcji lub metod.
Takie testowanie stosuje się do wszystkich rodzajów aplikacji.
Istnieją dwa podejścia do tworzenia nowych funkcjonalności:
- Code first. Najpierw programujemy, a potem testujemy. Oznacza to, że na początku pisze się kod, realizuje funkcjonalność naszej aplikacji, a później pisany jest test danej funkcjonalności, następnie albo dopracowujemy funkcjonalność, albo przechodzimy do kolejnego zadania jeśli wszystko jest w porządku.
- Test first. To drugie podejście. Jeszcze przed napisaniem funkcjonalności naszej aplikacji pisze się test, który sprawdza przyszłą funkcjonalność. Dopiero po stworzeniu testów, przechodzimy do napisania funkcjonalności naszej aplikacji.
Istnieją dwie popularne metodyki które wykorzystują jedno z powyższych podejść:
- TDD - programowanie przez testowanie (Test-Driven Development);
- BDD - programowanie przez realizację zachowania (Behavior-Driven Development).
Zarówno w podejściu TDD, jak i w BDD testy pisze się wcześniej, przed napisaniem faktycznego kodu implementującego daną funkcjonalność. Napisanie testów w pierwszej kolejności pomaga zastanowić się nad działaniem oprogramowania, co ostatecznie zapobiega pominięciu w funkcjonalności aplikacji wszystkich potrzebnych elementów. Jak widać na schemacie, BDD pracuje "ponad" TDD.
Algorytm pisania testów w podejściu TDD jest następujący: na początku pisze się kilka testów, następnie wykonuje się uruchomienie testów które, ponieważ funkcjonalność jeszcze nie jest realizowana, nie powodzą się. Przystępujemy więc do realizacji niezbędnej funkcjonalności aplikacji i stopniowo testy zaczynają przechodzić, aż do pełnej realizacji funkcjonalności.
Algorytm pisania testów w BDD jest prawie taki sam, pojawia się jednak różnica stylistyczna. BDD opisuje projektowanie oprogramowania komputerowego, faktycznie tworzymy więc plan przed napisaniem kodu. Testy pisane są z uwzględnieniem tego, czego oczekujemy od pracy całości jeszcze niezrealizowanej funkcjonalności w kontekście oprogramowania. Podejście takie stworzone zostało, aby naprawić problemy, które mogą pojawić się przy wykorzystaniu TDD, a konkretnie, ułatwić tworzenie kodu przez reprezentację wizualną jego funkcjonalności. Testy i ich wyniki wyglądają bardziej zrozumiale nie tylko dla programistów, lecz także dla klienta.
Ważna w zrozumieniu testowania jest piramida testowa. Wykorzystuje się ją do rozłożenia testów na różne poziomy aplikacji.
Każdą aplikację można podzielić na kilka warstw. Rozpatrzymy typowe rozwarstwienie z poziomem komponentów, serwisów i interfejsem użytkownika. Dolna część piramidy jest pokryta modułowymi (unit) testami. Napisane są przeważnie przez programistów i pokrywają komponenty atomowe, takie jak klasy, metody i funkcje. Włączane są bardzo często, pracują szybko, a ich ilość w danej aplikacji jest stosunkowo duża.
Testy integracyjne. To sprawdzenie, czy nowo realizowana funkcjonalność nie zepsuła kodu aplikacji. To scenariusz, który pokrywa bardziej skomplikowane funkcje, takie jak testy API. Uruchamiamy je dosyć rzadko, z reguły przy releasie i branch merges.
W górnej części znajdują się testy interfejsu użytkownika i ręcznego testowania, czyli End-to-End. Nie będziemy ich w poniższych przykładach analizować. Uruchamiane są rzadko i w kontekście całego systemu