Przejdź do treści

Definicje testów

Często spotykam się z niepoprawnym nazywaniem testów wykonywanych w procesie wytwarzania oprogramowania. Tym wpisem chciałbym przedstawić Ci sześć podstawowych typów testów. Mam nadzieje, że będziemy od teraz porozumiewać się tą samą terminologią (przynajmniej jeżeli chodzi o testy).

Baner promujący artykuł

Testy w Inżynierii Oprogramowania

Testy jednostkowe (unit testing)

Testy stworzone przez autorów kodu, które testują pojedyncze funkcje. Czasami można pod tą definicje zalicza się także klasa.

Bardzo lubię pisać testy jednostkowe, ponieważ po ich napisaniu dla danej funkcji, mam pewność poprawności jej działania. Podnosi to mój komfort podczas pracy twórczej (implementacji).

Każdy z testów powinien być uruchomiony w izolowanym środowisku. Co to oznacza? A no tyle że wynika działania jednego testu NIE MOŻE wpływać na drugi. W tym miejscu warto poznać mocki.

Narzędzia

Jakich narzędzi używam do pisania testów jednostkowych?

Bardzo lubię składnie i idee, które są zaaplikowane w bibliotece Jasmine ale też Mocha świetnie się spisuje jako test runner.

Pół roku temu stworzyłem na GitHubie projekt, gdzie wykorzystałem Jasmine oraz transpiler Babel - https://github.com/piecioshka/test-jasmine-babel. Niestety projekt ten nie zawiera większej definicji testów - nie ma punktu odniesienia. Jest on zrobiony tylko w celu udowodnienia (samemu sobie), że można wykorzystywać Babel.js, aby tworzyć testy.

Projekt opisany poniżej już może bardziej zaciekawić.

Dobrym przykładem z większą ilością testów jest biblioteka https://github.com/piecioshka/super-event-emitter.
Na dzień 2016-04-16 W katalogu test/unit/specs/ ich liczba wynosi 32.

Ci z Was, którzy nie tworzyli wcześniej testów, to jest to najlepszy moment, aby w swoim projekcie (tak naprawdę w dowolnym) spróbować napisać kilka testów jednostkowych.

Pokrycie kodu (code coverage)

Podczas pisania testów jednostkowych ważne jest tzw. pokrycie kodu. Mam tutaj na myśli, stosunek procentowy: ile linijek kodu aplikacji zostało uruchomionych podczas testów do całości kodu. Jeśli coś zostało uruchomione, to TAK JAKBY zostało przetestowane.

Warto napisać kilka asercji to każdego wyrażenia, które coś modyfikuje.

Wskaźnik pokrycia kodu na poziomie 100%, mówi, że cały kod aplikacji został uruchomiony podczas testów. Ale proszę nie mylcie tego z tym, że każda linijka została przetestowana.

Testy integracyjne (integration testing)

Testy stworzone przez developerów. Zweryfikowane są połączenia między modułami.

Testy integracyjne to trudniejszy temat. Tutaj pojawia się stworzenie sztucznego (laboratoryjnego) środowiska, gdzie takie testy można uruchomić.

Narzędzia

Podobnie jak w przypadku testów jednostkowych możemy wykorzystać te same narzędzia, aczkolwiek będziemy potrzebowali sprawdzić nie tylko poprawne działanie pojedynczej funkcji, ale połączenie jej z inną.

Testy end-to-end (e2e testing)

Testy stworzone przez developerów. Testują one procesy biznesowe w sposób emulujący zachowanie użytkownika. Celem jest przejście przez dowolny proces z logiki biznesowej w celu potwierdzenia poprawnej implementacji.

Najczęściej aby przeprowadzić testy E2E należy posiadać rzeczywiste dane. Przykładem niech będzie posiadanie loginu i hasła użytkownika, aby przetestować mechanizm logowania użytkownika.

Narzędzia

Ostatnio chętnie używam narzędzia Nightwatch.js. Korzystnym przykładem takich testów jest bardzo znany sposób nagrywania scenariusza, takiego jaki tester realizuje podczas swoich testów funkcjonalnych, a potem ich automatycznego odtwarzania.

Najpopularniejsze narzędzie do takich testów nosi nazwę Selenium. Jednak wyżej wymienione przeze mnie narzędzie jest o wiele lepsze dla nas (developerów JavaScriptu) ponieważ testy tworzymy w języku, który używamy na co dzień.

Testy funkcjonalne (black-box testing)

Testy przeprowadzane przez osoby z zewnątrz (nie autorów kodu).

Testy takie są wykonywane najczęściej przez testerów - osobny dział weryfikujący poprawność działania aplikacji. Developer oddaje aplikację do testów uruchamiając ją na środowisku stagingowym, po to aby testerzy mogli ją “przeklikać”.

Testy strukturalne (white-box testing)

Testy przeprowadzane przez osoby z zewnątrz tak, aby przetestować wszystkie przypadki kodu, przy tego rodzaju testach pomagają programiści, aby móc przetestować każdą linijkę.

Specjalny rodzaj testów funkcjonalnych, gdzie programiści modyfikują kod aplikacji, aby przetestować przypadki, które ciężko zreprodukować w środowisku uruchomionej aplikacji (na przykład modyfikacja czasu na urządzeniach takich jak telewizory).

Testy statyczne

Autorzy kodu, czytają kod źródłowy w poszukiwaniu błędów składni, ale też procesów biznesowych.

Takie testy realizowane są najczęściej podczas code review innego developera. Z mojego doświadczenia są to testy bardzo pomocne w zakończeniu zadania - na Twój kod patrzy cały zespół projektowy.

Moje doświadczenie pokazuje, że warto spotkać się jako zespół i porozmawiać o konkretnej zmianie, przed wdrożeniem.

Jeśli realizujecie swoje projekty na GitHubie (albo GitLabie) to świetnie jest spotkać się zespołem na omawianiu danego Pull Request-u. Wszyscy skupiają się tylko na tej jednej zmianie (która może oczywiście dotyczyć wielu plików).

Testy dynamiczne

Porównywanie danych wyjściowych z oczekiwanymi.

Na analizowanym kodzie (w testach statycznych) dorzucamy testowanie kodu uruchamiając z przykładowymi danymi w oczekiwaniu na dane wyjściowe, które to powinny być zgodne z flow implementacji logiki biznesowej (albo algorytmu).

Podsumowanie

Wystarczy zapamiętanie tych kilku typów testów, wśród których najważniejsze są 3 pierwsze, a komunikacja w zespołach projektowych może się poprawić.

Zachęcam wszystkich, którzy jeszcze nie pisali testów jednostkowych albo integracyjnych do spróbowania. Możecie się wzorować na moich projektach: