Nette Documentation Preview

syntax
Primi passi con Nette Tester
****************************

<div class=perex>

Anche i bravi programmatori sbagliano. La differenza tra un bravo programmatore e uno scadente è che il bravo commette un errore una sola volta e la volta successiva lo scopre con i test automatici.

- "Chi non testa è condannato a ripetere i propri errori." (proverbio)
- "Appena ci sbarazziamo di un errore, ne compare un altro." (legge di Murphy)
- "Ogni volta che sei tentato di scrivere un print, scrivi invece un test." (Martin Fowler)

</div>

Avete mai scritto in PHP del codice come questo?

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

var_dump($result);
```

Cioè: avete mai stampato il risultato della chiamata di una funzione solo per controllare a occhio se restituisce quello che dovrebbe? Probabilmente lo fate più volte al giorno. Mano sul cuore: se tutto funziona correttamente, questo codice lo cancellate? Vi aspettate che la classe non si rompa in futuro? Le leggi di Murphy garantiscono il contrario :-)

In sostanza avete scritto un test. Basta una piccola modifica perché non richieda un controllo visivo, ma si controlli da sé. E se non cancellate il test, potete eseguirlo in qualsiasi momento in futuro per verificare che tutto funzioni ancora come deve. Con il tempo creerete un gran numero di test del genere, quindi tornerebbe utile eseguirli automaticamente.

E in tutto questo vi aiuterà Nette Tester.


Che cosa rende Tester unico?
============================

Scrivere test per Nette Tester è particolare perché **ogni test è un normale script PHP** che si può eseguire da solo.

Quando scrivete un test, potete quindi semplicemente eseguirlo e scoprire se contiene per esempio un errore di programmazione. Se funziona correttamente. In caso contrario potete percorrerlo comodamente passo passo nel vostro IDE e cercare l'errore. Potete perfino aprirlo nel browser.

E soprattutto: eseguendolo, eseguite il test. Scoprite subito se è passato o fallito. Come? Mostriamolo. Scriveremo un test banale sul lavoro con un array PHP e lo salveremo nel file `ArrayTest.php`:

```php .{file:ArrayTest.php}
<?php
use Tester\Assert;

require __DIR__ . '/vendor/autoload.php';  # carica l'autoloader di Composer
Tester\Environment::setup();               # inizializza Nette Tester

$stack = [];
Assert::same(0, count($stack));   # ci aspettiamo che count() restituisca zero

$stack[] = 'foo';
Assert::same(1, count($stack));   # ci aspettiamo che count() restituisca uno
Assert::contains('foo', $stack);  # verifichiamo che $stack contenga l'elemento 'foo'
```

Come vedete, per confermare che il valore reale corrisponde a quello atteso si usano i cosiddetti [metodi di asserzione|assertions] come `Assert::same()`.

Il test è scritto e possiamo eseguirlo dalla riga di comando. La prima esecuzione rivelerà eventuali errori di sintassi e, se non avete fatto refusi da nessuna parte, stamperà:

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

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

Provate a cambiare l'asserzione nel test in una falsa, per esempio `Assert::contains('XXX', $stack);`, e guardate cosa succede all'esecuzione:

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

Continuiamo a parlare di come scrivere i test nel capitolo [Scrivere i test |writing-tests].


Installazione e requisiti
=========================

La versione minima di PHP richiesta da Tester è la 8.0 (maggiori dettagli nella tabella [#Versioni di PHP supportate]). Il modo di installazione preferito è con [Composer |best-practices:composer]:

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

Provate a lanciare Nette Tester dalla riga di comando (senza argomenti stampa solo l'aiuto):

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


Eseguire i test
===============

Man mano che l'applicazione cresce, cresce con essa anche il numero di test. Eseguirli uno per uno non sarebbe pratico. Tester ha perciò un runner di test di massa, che richiamiamo dalla riga di comando. Come parametro indichiamo la directory in cui si trovano i test. Il punto indica la directory corrente.

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

Il runner esplora la directory indicata e tutte le sottodirectory e cerca i test, cioè i file `*.phpt` e `*Test.php`. Troverà anche il nostro test `ArrayTest.php`, perché corrisponde alla maschera.

Poi comincia a testare. Ogni test viene eseguito come un nuovo processo PHP, quindi gira completamente isolato dagli altri. Li esegue in parallelo su più thread, il che lo rende estremamente veloce. E per prima cosa esegue i test falliti nell'esecuzione precedente, così scoprite subito se siete riusciti a correggere l'errore.

Durante l'esecuzione dei test, Tester stampa via via i risultati nel terminale sotto forma di caratteri:

- <code style="color: #CCC; background-color: #000">.</code> - test passato
- <code style="color: #CCC; background-color: #000">s</code> - test saltato
- <code style="color: #FFF; background-color: #900">F</code> - test fallito

L'output può apparire così:

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

PHP 8.5.2 (cli) | php | 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>
\--

Sono stati eseguiti 35 test, uno è fallito, uno è stato saltato.

Continuiamo nel capitolo [Eseguire i test |running-tests].


Modalità watch
==============

State facendo il refactoring del codice? O magari sviluppate perfino secondo la metodologia TDD (Test Driven Development)? Allora vi piacerà la modalità watch. In questa modalità Tester sorveglia i codici sorgente e si riavvia automaticamente quando cambiano.

Durante lo sviluppo avete nell'angolo del monitor un terminale in cui vi brilla una barra di stato verde e, quando all'improvviso diventa rossa, sapete di aver appena fatto qualcosa che non va. È in realtà un bel gioco: programmate e cercate di mantenere il colore.

La modalità watch si avvia con il parametro [`--watch` |running-tests#-w --watch path].


Report sulla copertura del codice
=================================

Tester sa generare report con una panoramica di quanto codice sorgente è coperto dai test. Il report può essere in formato HTML leggibile dalle persone oppure in Clover XML per l'ulteriore elaborazione automatica.

Guardate un "report HTML di esempio":attachment:coverage.html con la copertura del codice.


Versioni di PHP supportate
==========================

| Versione         | Compatibile con PHP
|------------------|-------------------
| Tester 2.6       | PHP 8.0 - 8.5
| Tester 2.5       | PHP 8.0 - 8.5
| 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

Vale per l'ultima versione patch.

Tester fino alla versione 1.7 supportava anche [HHVM |https://hhvm.com] 3.3.0 o superiore (con `tester -p hhvm`). Il supporto è stato interrotto dalla versione 2.0 di Tester.

Primi passi con Nette Tester

Anche i bravi programmatori sbagliano. La differenza tra un bravo programmatore e uno scadente è che il bravo commette un errore una sola volta e la volta successiva lo scopre con i test automatici.

  • „Chi non testa è condannato a ripetere i propri errori.“ (proverbio)
  • „Appena ci sbarazziamo di un errore, ne compare un altro.“ (legge di Murphy)
  • „Ogni volta che sei tentato di scrivere un print, scrivi invece un test.“ (Martin Fowler)

Avete mai scritto in PHP del codice come questo?

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

var_dump($result);

Cioè: avete mai stampato il risultato della chiamata di una funzione solo per controllare a occhio se restituisce quello che dovrebbe? Probabilmente lo fate più volte al giorno. Mano sul cuore: se tutto funziona correttamente, questo codice lo cancellate? Vi aspettate che la classe non si rompa in futuro? Le leggi di Murphy garantiscono il contrario :-)

In sostanza avete scritto un test. Basta una piccola modifica perché non richieda un controllo visivo, ma si controlli da sé. E se non cancellate il test, potete eseguirlo in qualsiasi momento in futuro per verificare che tutto funzioni ancora come deve. Con il tempo creerete un gran numero di test del genere, quindi tornerebbe utile eseguirli automaticamente.

E in tutto questo vi aiuterà Nette Tester.

Che cosa rende Tester unico?

Scrivere test per Nette Tester è particolare perché ogni test è un normale script PHP che si può eseguire da solo.

Quando scrivete un test, potete quindi semplicemente eseguirlo e scoprire se contiene per esempio un errore di programmazione. Se funziona correttamente. In caso contrario potete percorrerlo comodamente passo passo nel vostro IDE e cercare l'errore. Potete perfino aprirlo nel browser.

E soprattutto: eseguendolo, eseguite il test. Scoprite subito se è passato o fallito. Come? Mostriamolo. Scriveremo un test banale sul lavoro con un array PHP e lo salveremo nel file ArrayTest.php:

<?php
use Tester\Assert;

require __DIR__ . '/vendor/autoload.php';  # carica l'autoloader di Composer
Tester\Environment::setup();               # inizializza Nette Tester

$stack = [];
Assert::same(0, count($stack));   # ci aspettiamo che count() restituisca zero

$stack[] = 'foo';
Assert::same(1, count($stack));   # ci aspettiamo che count() restituisca uno
Assert::contains('foo', $stack);  # verifichiamo che $stack contenga l'elemento 'foo'

Come vedete, per confermare che il valore reale corrisponde a quello atteso si usano i cosiddetti metodi di asserzione come Assert::same().

Il test è scritto e possiamo eseguirlo dalla riga di comando. La prima esecuzione rivelerà eventuali errori di sintassi e, se non avete fatto refusi da nessuna parte, stamperà:

$ php ArrayTest.php

OK

Provate a cambiare l'asserzione nel test in una falsa, per esempio Assert::contains('XXX', $stack);, e guardate cosa succede all'esecuzione:

$ php ArrayTest.php

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

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

FAILURE

Continuiamo a parlare di come scrivere i test nel capitolo Scrivere i test.

Installazione e requisiti

La versione minima di PHP richiesta da Tester è la 8.0 (maggiori dettagli nella tabella Versioni di PHP supportate). Il modo di installazione preferito è con Composer:

composer require --dev nette/tester

Provate a lanciare Nette Tester dalla riga di comando (senza argomenti stampa solo l'aiuto):

vendor/bin/tester

Eseguire i test

Man mano che l'applicazione cresce, cresce con essa anche il numero di test. Eseguirli uno per uno non sarebbe pratico. Tester ha perciò un runner di test di massa, che richiamiamo dalla riga di comando. Come parametro indichiamo la directory in cui si trovano i test. Il punto indica la directory corrente.

vendor/bin/tester .

Il runner esplora la directory indicata e tutte le sottodirectory e cerca i test, cioè i file *.phpt e *Test.php. Troverà anche il nostro test ArrayTest.php, perché corrisponde alla maschera.

Poi comincia a testare. Ogni test viene eseguito come un nuovo processo PHP, quindi gira completamente isolato dagli altri. Li esegue in parallelo su più thread, il che lo rende estremamente veloce. E per prima cosa esegue i test falliti nell'esecuzione precedente, così scoprite subito se siete riusciti a correggere l'errore.

Durante l'esecuzione dei test, Tester stampa via via i risultati nel terminale sotto forma di caratteri:

  • . – test passato
  • s – test saltato
  • F – test fallito

L'output può apparire così:

 _____ ___  ___ _____ ___  ___
|_   _/ __)( __/_   _/ __)| _ )
  |_| \___ /___) |_| \___ |_|_\  v2.6.0

PHP 8.5.2 (cli) | php | 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)

Sono stati eseguiti 35 test, uno è fallito, uno è stato saltato.

Continuiamo nel capitolo Eseguire i test.

Modalità watch

State facendo il refactoring del codice? O magari sviluppate perfino secondo la metodologia TDD (Test Driven Development)? Allora vi piacerà la modalità watch. In questa modalità Tester sorveglia i codici sorgente e si riavvia automaticamente quando cambiano.

Durante lo sviluppo avete nell'angolo del monitor un terminale in cui vi brilla una barra di stato verde e, quando all'improvviso diventa rossa, sapete di aver appena fatto qualcosa che non va. È in realtà un bel gioco: programmate e cercate di mantenere il colore.

La modalità watch si avvia con il parametro --watch.

Report sulla copertura del codice

Tester sa generare report con una panoramica di quanto codice sorgente è coperto dai test. Il report può essere in formato HTML leggibile dalle persone oppure in Clover XML per l'ulteriore elaborazione automatica.

Guardate un report HTML di esempio con la copertura del codice.

Versioni di PHP supportate

Versione Compatibile con PHP
Tester 2.6 PHP 8.0 – 8.5
Tester 2.5 PHP 8.0 – 8.5
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

Vale per l'ultima versione patch.

Tester fino alla versione 1.7 supportava anche HHVM 3.3.0 o superiore (con tester -p hhvm). Il supporto è stato interrotto dalla versione 2.0 di Tester.