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šels
– 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.