Nette Documentation Preview

syntax
Rozpoczęcie pracy z Nette Tester
********************************

<div class=perex>

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)

</div>

Czy kiedykolwiek pisałeś podobny kod w PHP?

```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? .[#toc-what-makes-tester-unique]
======================================================================

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 .{file: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 |assertions], 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:

/--pre .[terminal]
$ php ArrayTest.php

<span style="color:#FFF; background-color:#090">OK</span>
\--

Spróbuj zmienić oświadczenie w teście na fałszywe `Assert::contains('XXX', $stack);` i obserwuj, co się stanie, gdy go uruchomisz:

/--pre .[terminal]
$ php ArrayTest.php

<span style="color: #FFF">Failed: </span><span style="color: #FF0">['foo']</span><span style="color: #FFF"> should contain </span><span style="color: #FF0">'XXX'</span>

<span style="color: #CCC">in </span><span style="color: #FFF">ArrayTest.php(17)</span><span style="color: #808080"> Assert::contains('XXX', $stack);</span>

<span style="color: #FFF; background-color: #900">FAILURE</span>
\--

Więcej informacji na ten temat znajduje się w rozdziale Pisanie [testów |writing-tests].


Instalacja i wymagania .[#toc-installation-and-requirements]
============================================================

Minimalna wersja PHP wymagana przez Tester to 7.1 (szczegóły w tabeli [obsługiwanych wersji PHP |#Supported-PHP-Versions]). Preferowaną metodą instalacji jest użycie [Composera |best-practices:composer]:

/--pre .[terminal]
composer require --dev nette/tester
\--

Spróbuj uruchomić Nette Tester z linii poleceń (bez parametrów wypisuje tylko pomoc):

/--pre .[terminal]
vendor/bin/tester
\--


Przeprowadzanie testów .[#toc-running-tests]
============================================

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.

/--pre .[terminal]
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:

- <code style="color: #CCC; background-color: #000">.</code> - test zaliczony
- <code style="color: #CCC; background-color: #000">s</code> - test został pominięty
- <code style="color: #FFF; background-color: #900">F</code> - test nie powiódł się

Dane wyjściowe mogą wyglądać tak:

/--pre .[terminal]
 _____ ___  ___ _____ ___  ___
|_   _/ __)( __/_   _/ __)| _ )
  |_| \___ /___) |_| \___ |_|_\  v2.5.2

Note: No php.ini is used.
PHP 8.3.2 (cli) | php -n | 8 threads

........s................<span style="color: #FFF; background-color: #900">F</span>.........

<span style="color: #F00">-- FAILED: greeting.phpt</span>
<span style="color: #CCC">   </span><span style="color: #FFF">Failed: </span><span style="color: #FF0">'Hello John'</span><span style="color: #FFF"> should be</span>
<span style="color: #FFF">       ... </span><span style="color: #FF0">'Hello Peter'</span>

<span style="color: #CCC">   in </span><span style="color: #FFF">greeting.phpt(19)</span><span style="color: #808080"> Assert::same('Hello Peter', $o->say('John'));</span>

<span style="color: #FFF; background-color: #900">FAILURES! (35 tests, 1 failures, 1 skipped, 1.7 seconds)</span>
\--

Przeprowadzono 35 testów, jeden się nie powiódł, jeden został pominięty.

Kontynuujemy w rozdziale [Uruchamianie testów |running-tests].


Tryb oglądania .[#toc-watch-mode]
=================================

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 |running-tests#w-watch-path].


Raporty CodeCoverage .[#toc-codecoverage-reports]
=================================================

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":https://files.nette.org/tester/coverage.html z pokryciem kodu.


Obsługiwane wersje PHP .[#toc-supported-php-versions]
=====================================================

| 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 |https://hhvm.com] 3.3.0 lub wyższy (poprzez `tester -p hhvm`). Wsparcie zostało przerwane od wersji Tester 2.0.

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 zaliczony
  • s – test został pominięty
  • F – 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.