Rozpoczęcie pracy z Nette Tester
Nawet dobrzy programiści popełniają błędy. Różnica między dobrym programistą a złym polega na tym, że ten dobry robi to tylko raz, a następnym razem jest wykrywany przez testy automatyczne.
- „Ci, którzy nie testują, są skazani na powtarzanie swoich błędów“. (przysłowie)
- „Jak tylko pozbędziemy się jednego błędu, pojawia się kolejny“. (Prawo Murphy'ego)
- „Zawsze, gdy czujesz potrzebę napisania transformacji na ekranie, napisz zamiast tego test“. (Martin Fowler)
Czy kiedykolwiek pisałeś podobny kod w PHP?
$obj = new MyClass;
$result = $obj->process($input);
var_dump($result);
To znaczy, czy wypisałeś wynik wywołania funkcji tylko po to, by sprawdzić na oko, czy zwraca to, co powinno? Jestem pewien, że robisz to wiele razy dziennie. Ręka na sercu: jeśli wszystko działa poprawnie, czy usunąć ten kod? Czy spodziewasz się, że w przyszłości klasa nie będzie się łamać? Prawa Murphy'ego gwarantują coś wręcz przeciwnego :-)
Zasadniczo napisałeś test. Trzeba go tylko lekko zmodyfikować, żeby nie wymagał sprawdzania na oko, tylko sprawdzał się sam. A jeśli nie usuniesz testu, możesz go uruchomić w dowolnym momencie w przyszłości i sprawdzić, czy wszystko nadal działa tak, jak powinno. Z czasem stworzysz dużą liczbę takich testów, więc przydałoby się je uruchamiać automatycznie.
W tym wszystkim może pomóc Nette Tester.
Co sprawia, że Tester jest wyjątkowy?
Pisanie testów dla Nette Tester jest o tyle wyjątkowe, że każdy test jest zwykłym skryptem PHP, który może być uruchamiany niezależnie.
Więc kiedy napiszesz test, możesz go po prostu uruchomić i zobaczyć, czy istnieje błąd programistyczny. Jeśli działa prawidłowo. Jeśli nie, możesz łatwo przejść przez to w swoim IDE i poszukać błędu. Można go nawet otworzyć w przeglądarce.
I co najważniejsze, uruchamiając go, wykonujesz test. Od razu dowiesz się, czy przeszedł, czy nie. Jak? Zobaczmy. Napiszmy
trywialny test pracy z tablicami w PHP i zapiszmy go do pliku ArrayTest.php
:
<?php
use Tester\Assert;
require __DIR__ . '/vendor/autoload.php'; # načtení Composer autoloaderu
Tester\Environment::setup(); # inicializace Nette Tester
$stack = [];
Assert::same(0, count($stack)); # očekáváme, že count() vrátí nulu
$stack[] = 'foo';
Assert::same(1, count($stack)); # očekáváme, že count() vrátí jedničku
Assert::contains('foo', $stack); # ověříme, že $stack obsahuje položku 'foo'
Jak widać, do potwierdzenia, że wartość rzeczywista zgadza się z wartością oczekiwaną, stosuje się tzw. metody asercyjne, takie jak Assert::same()
.
Napisaliśmy test i możemy go uruchomić z linii poleceń. Uruchomienie go po raz pierwszy ujawni wszelkie błędy składni i jeśli nie zrobiłeś literówki w dowolnym miejscu, zostanie wydrukowany:
$ php ArrayTest.php
OK
Spróbuj zmienić oświadczenie w teście na fałszywe Assert::contains('XXX', $stack);
i obserwuj, co się
stanie, gdy go uruchomisz:
$ php ArrayTest.php Failed: ['foo'] should contain 'XXX' in ArrayTest.php(17) Assert::contains('XXX', $stack); FAILURE
Więcej informacji na ten temat znajduje się w rozdziale Pisanie testów.
Instalacja i wymagania
Minimalna wersja PHP wymagana przez Tester to 7.1 (szczegóły w tabeli obsługiwanych wersji PHP). Preferowaną metodą instalacji jest użycie Composera:
composer require --dev nette/tester
Spróbuj uruchomić Nette Tester z linii poleceń (bez parametrów wypisuje tylko pomoc):
vendor/bin/tester
Przeprowadzanie testów
Wraz z rozwojem aplikacji rośnie liczba testów. Przeprowadzanie testów po kolei nie byłoby praktyczne. Dlatego Tester posiada masowy launcher testów, który wywołujemy z linii poleceń. Jako parametr podajemy katalog, w którym znajdują się testy. Kropka wskazuje na bieżący katalog.
vendor/bin/tester .
Test runner przeskanuje podany katalog i wszystkie podkatalogi i znajdzie testy, którymi są pliki *.phpt
i
*Test.php
. Znajdzie również nasz test ArrayTest.php
, ponieważ pasuje on do maski.
Następnie rozpocznie się testowanie. Każdy test rozpoczyna się jako nowy proces PHP, więc działa całkowicie odizolowany od pozostałych. Uruchamia je równolegle w wielu wątkach, dzięki czemu jest niezwykle szybki. I najpierw uruchamia testy, które nie powiodły się w poprzednim uruchomieniu, więc od razu będziesz wiedział, czy udało Ci się naprawić błąd.
Podczas wykonywania testów, Tester stale drukuje wyniki do terminala jako znaki:
.
– test zaliczonys
– test został pominiętyF
– test nie powiódł się
Dane wyjściowe mogą wyglądać tak:
_____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... -- FAILED: greeting.phpt Failed: 'Hello John' should be ... 'Hello Peter' in greeting.phpt(19) Assert::same('Hello Peter', $o->say('John')); FAILURES! (35 tests, 1 failures, 1 skipped, 1.7 seconds)
Przeprowadzono 35 testów, jeden się nie powiódł, jeden został pominięty.
Kontynuujemy w rozdziale Uruchamianie testów.
Tryb oglądania
Refaktoryzacja kodu? Albo nawet rozwijanie się zgodnie z metodologią TDD (Test Driven Development)? Wtedy spodoba ci się tryb zegarka. W tym trybie tester obserwuje kod źródłowy i uruchamia się sam, gdy wprowadzane są zmiany.
W ten sposób, gdy się rozwijasz, masz terminal w rogu monitora z zielonym paskiem stanu, który świeci, a kiedy nagle zmienia się na czerwony, wiesz, że właśnie zrobiłeś coś złego. To faktycznie świetna gra, w której programujesz i próbujesz trzymać się koloru.
Tryb Watch jest uruchamiany przez parametr –watch.
Raporty CodeCoverage
Tester może generować raporty z przeglądem tego, ile kodu źródłowego obejmują testy. Raport może być w formacie HTML czytelnym dla człowieka lub Clover XML do dalszego przetwarzania maszynowego.
Zobacz przykładowy raport HTML z pokryciem kodu.
Obsługiwane wersje PHP
wersje | kompatybilne z PHP |
---|---|
Tester 2.5 | PHP 8.0 – 8.3 |
Tester 2.4 | PHP 7.2 – 8.2 |
Tester 2.3 | PHP 7.1 – 8.0 |
Tester 2.1 – 2.2 | PHP 7.1 – 7.3 |
Tester 2.0 | PHP 5.6 – 7.3 |
Tester 1.7 | PHP 5.3 – 7.3 + HHVM 3.3+ |
Tester 1.6 | PHP 5.3 – 7.0 + HHVM |
Tester 1.3 – 1.5 | PHP 5.3 – 5.6 + HHVM |
Tester 0.9 – 1.2 | PHP 5.3 – 5.6 |
Ważne dla najnowszych wersji poprawek.
Do wersji 1.7 Tester wspierał również HHVM 3.3.0 lub wyższy (poprzez
tester -p hhvm
). Wsparcie zostało przerwane od wersji Tester 2.0.