Nette Documentation Preview

syntax
Začínáme s Nette Tester
***********************

<div class=perex>

I dobří programátoři dělají chyby. Rozdíl mezi dobrým a špatným programátorem je v tom, že ten dobrý ji udělá jen jednou a příště ji odhalí pomocí automatizovaných testů.

- "Kdo netestuje, je odsouzen opakovat své chyby." (přísloví)
- "Jakmile se zbavíme jedné chyby, objeví se další." (Murphyho zákon)
- "Kdykoliv máte nutkání vypsat si na obrazovku proměnou, napište raději test." (Martin Fowler)

</div>

Už jste někdy napsali v PHP podobný kód?

```php
$obj = new MyClass;
$result = $obj->process($input);

var_dump($result);
```

Tedy vypsali jste si výsledek volání funkce jen proto, abyste okem ověřili, zda vrací to, co má? Určitě to děláte mnohokrát denně. Ruku na srdce: v případě, že vše funguje správně, smažete tento kód? Očekáváte, že se třída v budoucnu nerozbije? Murphyho zákony garantují opak :-)

V podstatě jste napsali test. Jen ho stačí mírně upravit, aby nevyžadoval oční kontrolu, ale aby se zkontroloval sám. A když test nesmažete, můžete jej spustit kdykoliv v budoucnu a ověřit, že vše stále funguje, jak má. Časem takových testů vytvoříte velké množství, tudíž by se hodilo je spouštět automatizovaně.

A s tím vším vám pomůže právě Nette Tester.


Čím je Tester unikátní?
=======================

Psaní testů pro Nette Tester je unikátní v tom, že **každý test je běžný PHP skript, který lze samostatně spustit.**

Tedy když píšete test, můžete jej jednoduše spouštět a zjišťovat, jestli v něm třeba není programátorská chyba. Jestli funguje správně. Pokud ne, můžete jej snadno krokovat ve svém IDE a hledat chybu. Můžete jej dokonce otevřít v prohlížeči.

A především - tím, že jej spustíte, tak test vykonáte. Okamžitě zjistíte, jestli prošel, nebo selhal. Jak? Pojďme si to ukázat. Napíšeme triviální test práce s PHP polem a uložíme do souboru `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 vidíte, tzv. [aserční metody|assertions] jako `Assert::same()` se používají k potvrzení, že skutečná hodnota odpovídá očekávané hodnotě.

Test máme napsaný a můžeme ho spustit z příkazové řádky. První spuštění nám odhalí případné syntaktické chyby a pokud jste nikde neudělali překlep, vypíše se:

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

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

Zkuste v testu změnit tvrzení na nepravdivé `Assert::contains('XXX', $stack);` a sledujte, co se při spuštění stane:

/--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>
\--

Dále o psaní pokračujeme v kapitole [Psaní testů|writing-tests].


Instalace a požadavky
=====================

Minimální verze PHP vyžadována Testerem je 7.1 (detailněji v tabulce [#podporované verze PHP]). Preferovaný způsob instalace je pomocí [Composer |best-practices:composer]:

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

Zkuste si z příkazové řádky spustit Nette Tester (bez parametrů pouze vypíše nápovědu):

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


Spuštění testů
==============

Jak aplikace roste, počet testů roste s ní. Nebylo by praktické spouštět testy po jednom. Proto Tester disponuje hromadným spouštěčem testů, který voláme z příkazové řádky. Jako parametr uvedeme adresář, ve kterém se testy nacházejí. Tečka znamená aktuální adresář.

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

Spouštěč testů prohledá zadaný adresář a všechny podadresáře a vyhledá testy, což jsou soubory `*.phpt` a `*Test.php`. Najde tak i náš test `ArrayTest.php`, jelikož vyhovuje masce.

Poté odstartuje testování. Každý test spustí jako nový PHP proces, takže probíhá zcela izolovaně od ostatních. Spouští je paralelně ve více vláknech a díky tomu je nesmírně rychlý. A jako první spouští testy, které při předchozím běhu selhaly, takže se okamžitě dozvíte, jestli se vám chybu podařilo opravit.

Během provádění testů vypisuje Tester průběžně výsledky na terminál jako znaky:

- <code style="color: #CCC; background-color: #000">.</code> – test prošel
- <code style="color: #CCC; background-color: #000">s</code> – test byl přeskočen (skipped)
- <code style="color: #FFF; background-color: #900">F</code> – test selhal (failed)

Výstup může vypadat takto:

/--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>
\--

Bylo spuštěno 35 testů, jeden selhal, jeden byl přeskočen.

Dále pokračujeme v kapitole [Spouštění testů|running-tests].


Watch režim
===========

Refaktorujete kód? Nebo dokonce vyvíjíte podle metodiky TDD (Test Driven Development)? Pak se vám bude líbit watch režim. Tester v něm sleduje zdrojové kódy a při změně se sám spouští.

Při vývoji tak máte v rohu monitoru terminál, kde na vás svítí zelený stavový řádek, a když se náhle změní na červený, víte, že jste právě něco neudělali úplně dobře. Je to vlastně skvělá hra, kdy programujete a snažíte se držet barvu.

Watch režim se spouští parametrem [--watch|running-tests#w-watch-path].


CodeCoverage reporty
====================

Tester umí generovat reporty s přehledem, kolik zdrojového kódu testy pokrývají. Report může být buď v lidsky čitelném formátu HTML, nebo Clover XML pro další strojové zpracování.

Podívejte se na "ukázku HTML reportu":https://files.nette.org/tester/coverage.html s pokrytím kódu.


Podporované verze PHP
=====================

| verze            | kompatibilní s 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

Platí pro poslední patch verze.

Tester do verze 1.7 podporoval také [HHVM |https://hhvm.com] 3.3.0 nebo vyšší (přes `tester -p hhvm`). Podpora byla od verze Testeru 2.0 ukončena.

Začínáme s Nette Tester

I dobří programátoři dělají chyby. Rozdíl mezi dobrým a špatným programátorem je v tom, že ten dobrý ji udělá jen jednou a příště ji odhalí pomocí automatizovaných testů.

  • „Kdo netestuje, je odsouzen opakovat své chyby.“ (přísloví)
  • „Jakmile se zbavíme jedné chyby, objeví se další.“ (Murphyho zákon)
  • „Kdykoliv máte nutkání vypsat si na obrazovku proměnou, napište raději test.“ (Martin Fowler)

Už jste někdy napsali v PHP podobný kód?

$obj = new MyClass;
$result = $obj->process($input);

var_dump($result);

Tedy vypsali jste si výsledek volání funkce jen proto, abyste okem ověřili, zda vrací to, co má? Určitě to děláte mnohokrát denně. Ruku na srdce: v případě, že vše funguje správně, smažete tento kód? Očekáváte, že se třída v budoucnu nerozbije? Murphyho zákony garantují opak :-)

V podstatě jste napsali test. Jen ho stačí mírně upravit, aby nevyžadoval oční kontrolu, ale aby se zkontroloval sám. A když test nesmažete, můžete jej spustit kdykoliv v budoucnu a ověřit, že vše stále funguje, jak má. Časem takových testů vytvoříte velké množství, tudíž by se hodilo je spouštět automatizovaně.

A s tím vším vám pomůže právě Nette Tester.

Čím je Tester unikátní?

Psaní testů pro Nette Tester je unikátní v tom, že každý test je běžný PHP skript, který lze samostatně spustit.

Tedy když píšete test, můžete jej jednoduše spouštět a zjišťovat, jestli v něm třeba není programátorská chyba. Jestli funguje správně. Pokud ne, můžete jej snadno krokovat ve svém IDE a hledat chybu. Můžete jej dokonce otevřít v prohlížeči.

A především – tím, že jej spustíte, tak test vykonáte. Okamžitě zjistíte, jestli prošel, nebo selhal. Jak? Pojďme si to ukázat. Napíšeme triviální test práce s PHP polem a uložíme do souboru 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 vidíte, tzv. aserční metody jako Assert::same() se používají k potvrzení, že skutečná hodnota odpovídá očekávané hodnotě.

Test máme napsaný a můžeme ho spustit z příkazové řádky. První spuštění nám odhalí případné syntaktické chyby a pokud jste nikde neudělali překlep, vypíše se:

$ php ArrayTest.php

OK

Zkuste v testu změnit tvrzení na nepravdivé Assert::contains('XXX', $stack); a sledujte, co se při spuštění stane:

$ php ArrayTest.php

Failed: ['foo'] should contain 'XXX'

in ArrayTest.php(17) Assert::contains('XXX', $stack);

FAILURE

Dále o psaní pokračujeme v kapitole Psaní testů.

Instalace a požadavky

Minimální verze PHP vyžadována Testerem je 7.1 (detailněji v tabulce podporované verze PHP). Preferovaný způsob instalace je pomocí Composer:

composer require --dev nette/tester

Zkuste si z příkazové řádky spustit Nette Tester (bez parametrů pouze vypíše nápovědu):

vendor/bin/tester

Spuštění testů

Jak aplikace roste, počet testů roste s ní. Nebylo by praktické spouštět testy po jednom. Proto Tester disponuje hromadným spouštěčem testů, který voláme z příkazové řádky. Jako parametr uvedeme adresář, ve kterém se testy nacházejí. Tečka znamená aktuální adresář.

vendor/bin/tester .

Spouštěč testů prohledá zadaný adresář a všechny podadresáře a vyhledá testy, což jsou soubory *.phpt a *Test.php. Najde tak i náš test ArrayTest.php, jelikož vyhovuje masce.

Poté odstartuje testování. Každý test spustí jako nový PHP proces, takže probíhá zcela izolovaně od ostatních. Spouští je paralelně ve více vláknech a díky tomu je nesmírně rychlý. A jako první spouští testy, které při předchozím běhu selhaly, takže se okamžitě dozvíte, jestli se vám chybu podařilo opravit.

Během provádění testů vypisuje Tester průběžně výsledky na terminál jako znaky:

  • . – test prošel
  • s – test byl přeskočen (skipped)
  • F – test selhal (failed)

Výstup může vypadat takto:

 _____ ___  ___ _____ ___  ___
|_   _/ __)( __/_   _/ __)| _ )
  |_| \___ /___) |_| \___ |_|_\  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)

Bylo spuštěno 35 testů, jeden selhal, jeden byl přeskočen.

Dále pokračujeme v kapitole Spouštění testů.

Watch režim

Refaktorujete kód? Nebo dokonce vyvíjíte podle metodiky TDD (Test Driven Development)? Pak se vám bude líbit watch režim. Tester v něm sleduje zdrojové kódy a při změně se sám spouští.

Při vývoji tak máte v rohu monitoru terminál, kde na vás svítí zelený stavový řádek, a když se náhle změní na červený, víte, že jste právě něco neudělali úplně dobře. Je to vlastně skvělá hra, kdy programujete a snažíte se držet barvu.

Watch režim se spouští parametrem –watch.

CodeCoverage reporty

Tester umí generovat reporty s přehledem, kolik zdrojového kódu testy pokrývají. Report může být buď v lidsky čitelném formátu HTML, nebo Clover XML pro další strojové zpracování.

Podívejte se na ukázku HTML reportu s pokrytím kódu.

Podporované verze PHP

verze kompatibilní s 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

Platí pro poslední patch verze.

Tester do verze 1.7 podporoval také HHVM 3.3.0 nebo vyšší (přes tester -p hhvm). Podpora byla od verze Testeru 2.0 ukončena.