Začenjamo z Nette Tester
Tudi dobri programerji delajo napake. Razlika med dobrim in slabim programerjem je v tem, da jo dober naredi samo enkrat in jo naslednjič odkrije s pomočjo avtomatiziranih testov.
- “Kdor ne testira, je obsojen ponavljati svoje napake.” (pregovor)
- “Takoj ko se znebimo ene napake, se pojavi druga.” (Murphyjev zakon)
- “Kadarkoli imate potrebo izpisati si na zaslon spremenljivko, raje napišite test.” (Martin Fowler)
Ste že kdaj napisali v PHP podobno kodo?
$obj = new MyClass;
$result = $obj->process($input);
var_dump($result);
Torej ste si izpisali rezultat klica funkcije samo zato, da bi z očmi preverili, ali vrača to, kar naj bi? Zagotovo to počnete večkrat na dan. Roko na srce: v primeru, da vse deluje pravilno, izbrišete to kodo? Pričakujete, da se razred v prihodnosti ne bo pokvaril? Murphyjevi zakoni zagotavljajo nasprotno :-)
V bistvu ste napisali test. Samo malo ga je treba urediti, da ne bo zahteval očesne kontrole, ampak da se bo preveril sam. In če testa ne izbrišete, ga lahko zaženete kadarkoli v prihodnosti in preverite, ali vse še vedno deluje, kot mora. Sčasoma boste ustvarili veliko takšnih testov, zato bi bilo dobro, da jih zaženete avtomatizirano.
In pri vsem tem vam bo pomagal prav Nette Tester.
V čem je Tester edinstven?
Pisanje testov za Nette Tester je edinstveno v tem, da vsak test je običajen PHP skript, ki ga je mogoče samostojno zagnati.
Torej, ko pišete test, ga lahko preprosto zaženete in ugotovite, ali je v njem morda programska napaka. Ali deluje pravilno. Če ne, ga lahko enostavno korakate v svojem IDE in iščete napako. Lahko ga celo odprete v brskalniku.
In predvsem – s tem, ko ga zaženete, test izvedete. Takoj ugotovite, ali je uspel ali ne. Kako? Poglejmo si. Napišimo
trivialen test dela s PHP poljem in ga shranimo v datoteko ArrayTest.php
:
<?php
use Tester\Assert;
require __DIR__ . '/vendor/autoload.php'; # nalaganje Composer autoloaderja
Tester\Environment::setup(); # inicializacija Nette Tester
$stack = [];
Assert::same(0, count($stack)); # pričakujemo, da count() vrne nič
$stack[] = 'foo';
Assert::same(1, count($stack)); # pričakujemo, da count() vrne ena
Assert::contains('foo', $stack); # preverimo, da $stack vsebuje postavko 'foo'
Kot vidite, se t.i. asercijske metode kot Assert::same()
uporabljajo za potrditev, da dejanska vrednost ustreza pričakovani vrednosti.
Test imamo napisan in ga lahko zaženemo iz ukazne vrstice. Prvi zagon nam bo razkril morebitne sintaktične napake in če niste nikjer naredili tipkarske napake, se bo izpisalo:
$ php ArrayTest.php
OK
Poskusite v testu spremeniti trditev na neresnično Assert::contains('XXX', $stack);
in opazujte, kaj se zgodi ob
zagonu:
$ php ArrayTest.php Failed: ['foo'] should contain 'XXX' in ArrayTest.php(17) Assert::contains('XXX', $stack); FAILURE
Nadalje o pisanju nadaljujemo v poglavju Pisanje testov.
Namestitev in zahteve
Minimalna različica PHP, ki jo zahteva Tester, je 7.1 (podrobneje v tabeli podporované verze PHP). Prednostni način namestitve je s pomočjo Composer:
composer require --dev nette/tester
Poskusite si iz ukazne vrstice zagnati Nette Tester (brez parametrov samo izpiše pomoč):
vendor/bin/tester
Zagon testov
Ko aplikacija raste, število testov raste z njo. Ne bi bilo praktično zaganjati testov enega za drugim. Zato Tester razpolaga z množičnim zaganjalnikom testov, ki ga kličemo iz ukazne vrstice. Kot parameter navedemo imenik, v katerem se nahajajo testi. Pika pomeni trenutni imenik.
vendor/bin/tester .
Zaganjalnik testov preišče navedeni imenik in vse podimenike ter poišče teste, kar so datoteke *.phpt
in
*Test.php
. Najde tako tudi naš test ArrayTest.php
, ker ustreza maski.
Nato zažene testiranje. Vsak test zažene kot nov PHP proces, tako da poteka popolnoma izolirano od ostalih. Zažene jih vzporedno v več nitih in zato je izjemno hiter. In kot prve zažene teste, ki so pri prejšnjem zagonu spodleteli, tako da takoj izveste, ali ste napako uspeli popraviti.
Med izvajanjem testov Tester sproti izpisuje rezultate na terminal kot znake:
.
– test je uspels
– test je bil preskočen (skipped)F
– test je spodletel (failed)
Izpis lahko izgleda takole:
_____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) |_| \___ /___) |_| \___ |_|_\ 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)
Zagnanih je bilo 35 testov, eden je spodletel, eden je bil preskočen.
Nadalje nadaljujemo v poglavju Zagon testov.
Watch način
Refaktorirate kodo? Ali celo razvijate po metodologiji TDD (Test Driven Development)? Potem vam bo všeč watch način. Tester v njem spremlja izvorne kode in ob spremembi se sam zažene.
Pri razvoju tako imate v kotu monitorja terminal, kjer na vas sveti zelena statusna vrstica, in ko se nenadoma spremeni v rdečo, veste, da ste pravkar nekaj naredili ne povsem dobro. Je pravzaprav odlična igra, kjer programirate in poskušate ohraniti barvo.
Watch način se zažene s parametrom –watch.
CodeCoverage poročila
Tester zna generirati poročila s pregledom, koliko izvorne kode testi pokrivajo. Poročilo je lahko bodisi v človeško berljivem formatu HTML ali Clover XML za nadaljnjo strojno obdelavo.
Poglejte si vzorec HTML poročila s pokritostjo kode.
Podprte različice PHP
različica | združljivo 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 |
Velja za zadnjo patch različico.
Tester do različice 1.7 je podpiral tudi HHVM 3.3.0 ali višji (preko
tester -p hhvm
). Podpora je bila od različice Testerja 2.0 ukinjena.