I report

SimpleTest for PHP test runner and display documentation

SimpleTest abbraccia abbastanza fedelmente il pattern MVC (Model-View-Controller). Le classi reporter sono le viste mentre i test case e le loro gerarchie sono i modelli. I controller sono per lo più nascosti all'utente di SimpleTest a meno che si voglia modificare il meccanismo di esecuzione dei test, nel qual caso risulta possibile sovrascivere l'oggetto in esecuzione dall'interno del test case. Come accade di solito con l'MVC, il controller e per lo più vuoto e si controlla l'esecuzione del test da altri posti.

# html Visualizzare i report in HTML

Il sistema di visualizzazione standard è minimale. Si limita a riportare successi e fallimenti con le convenzionali barre verdi e rosse e mostra un percorso (breadcrumb) dei gruppi di test per ogni assert fallito. Un esempio di test fallito è:

# File test

Fail: createnewfile->True assertion failed.
1/1 test cases complete. 0 passes, 1 fails and 0 exceptions. Questo è il caso in cui tutti i test siano usciti con successo:

# File test

1/1 test cases complete. 1 passes, 0 fails and 0 exceptions. La buona notizia è che esistono molte classi della gerarchia del reporter da cui poter ereditare:

Per la visualizzazione su pagine web si può usare la classe `HtmlReporter` che ha la seguente interfaccia: class HtmlReporter extends SimpleReporter { public HtmlReporter($encoding) { ... } public makeDry(boolean $is_dry) { ... } public void paintHeader(string $test_name) { ... } public void sendNoCacheHeaders() { ... } public void paintFooter(string $test_name) { ... } public void paintGroupStart(string $test_name, integer $size) { ... } public void paintGroupEnd(string $test_name) { ... } public void paintCaseStart(string $test_name) { ... } public void paintCaseEnd(string $test_name) { ... } public void paintMethodStart(string $test_name) { ... } public void paintMethodEnd(string $test_name) { ... } public void paintFail(string $message) { ... } public void paintPass(string $message) { ... } public void paintError(string $message) { ... } public void paintException(string $message) { ... } public void paintMessage(string $message) { ... } public void paintFormattedMessage(string $message) { ... } protected string getCss() { ... } public array getTestList() { ... } public integer getPassCount() { ... } public integer getFailCount() { ... } public integer getExceptionCount() { ... } public integer getTestCaseCount() { ... } public integer getTestCaseProgress() { ... } } Di seguito si riporta il significato dei vari metodi. Sono stati riportati prima i metodi di visualizzazione dal momento che sono quelli che normalmente si vuole riscrivere:

- `HtmlReporter(string $encoding)`
  è il costruttore. Si noti che è lo unit test a conservare un riferimento al reporter, e non il contrario. Il reporter è sostanzialmente un ricevitore passivo di eventi di test. Questo garantisce un facile adattamento del display ad altri sistemi di test diversi dagli unit test, come ad esempio i server di monitoraggio. L'encoding è il sistema di codifica di caratteri che si vuole venga usato nella visualizzazione dei report. Per garantire che i messaggi di debug vengano visualizzati correttamento durante il web testing, ci si dovrebbe assicurare che la codifica dei caratteri coincida con quella usata nel sito che si sta collaudando. Le stringhe corrispondenti alle codifiche carattere sono descritte nella documentazione della funzione html_entities().
- `void paintHeader(string $test_name)`
  E' invocata all'inizio dei test non appena viene ricevuto il primo evento di inizio test. L'evento di inizio test è normalmente generato dal primo gruppo di test ed è questo che fornisce `$test_name`. Questo metodo visualizza il titolo della pagina, i CSS, il tag body e così via. Non restituisce niente.
- `void paintFooter(string $test_name)`
  Viene invocato al termine del test e si preoccupa di chiudere qualsiasi tag sia stato aperto dall'header della pagina. Di default, mostra anche le barre verdi e rosse e il conteggio finale dei risultati. Per essere più precisi, la fine dei test è individuata dalla ricezione di un evento di fine test avente lo stesso nome del test con il quale si è iniziato l'intero processo al medesimo livello. I test, infatti, possono essere annidati. La chiusura dell'ultimo test fa terminare il display.
- `void paintMethodStart(string $test_name)`
  Viene invocato all'inizio di ciascun metodo di test. Il nome, normalmente, coincide con il nome del metodo. Gli altri eventi di inizio test producono il medesimo comportamento tranne per il fatto che il primo gruppo di test comunica al reporter il numero di test case che contiene. In questo modo il reporter può essere in grado di visualizzare una barra di progressione mentre il motore macina i test case.
- `void paintMethodEnd(string $test_name)`
  resti termina il test che era stato iniziato con il medesimo nome.
- `void paintFail(string $message)`
  visualizza una failure. Il comportamento standard è quello di visualizzare la parola fail, un indicatore della progressione indicante il test annidato ed il messaggio riportato dall'assert.
- `void paintPass(string $message)`
  Di default non fa niente.
- `string getCss()`
  restituisce gli stili CSS come un'unica striga per il metodo dell'header della pagina. Gli stili addizionali possono essere appesi qui a meno che non si voglia fare l'overriding dell'header della pagina. Se si è sovrascritto il page header, si può richiamare questo metodo per recuperare il CSS originale.

Ci sono a disposizione anche alcuni metodi get che permettono di recuperare informazioni sullo stato corrente della test suite. Si utilizzano per arricchire la visualizzazione:

- `array getTestList()`
  è il primo metodo di appoggio per il subclassing. Restituisce l'attuale struttura annidata dei test come un elenco di nomi di test. Il test più profondamente annidato risulterà il primo dell'elenco e il metodo correntemente eseguito l'ultimo.
- `integer getPassCount()`
  restituisce il numero di passi eseguiti. E' necessario per chiudere la visualizzazione.
- `integer getFailCount()`
  restituisce, analogamente, il numero dei fallimenti.
- `integer getExceptionCount()`
  Similmente a sopra, restituisce il numero delle eccezioni.
- `integer getTestCaseCount()`
  Restituisce il numero dei test case totale. Il conteggio include anche i gruppi di test.
- `integer getTestCaseProgress()`
  Restituisce il numero di test completati.

Una delle modifiche semplici da effettuare è quella di fare in modo che HtmlReported visualizzi anche i normali passi oltre che agli errori e alle failure: <strong>class ShowPasses extends HtmlReporter { function paintPass($message) { parent::paintPass($message); print "&<span class=\"pass\">Pass</span>: "; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print implode("-&gt;", $breadcrumb); print "-&gt;$message<br />\n"; } protected function getCss() { return parent::getCss() . ' .pass { color: green; }'; } }</strong>

Un metodo sul quale si è sorvolato è `makeDry()`. Quando viene invocato senza parametri prima del lancio dei test, la sua esecuzione inibisce l'avvio dei test. Tuttavia, si continueranno a ricevere gli eventi di inizio e fine dei test e dei test case, ma nessun evento di successo o fallimento, poichè il codice dei test non verrà fisicamente eseguito.d.

Il motivo per cui esiste un tale metodo è legato alla possibilità di costruire GUI particolarmente sofisticate che permettano di selezionare individualmente i case test. Con un reporter impostato in dry run cge unvia solo eventi di visualizzazione questo è facilmente ottenibile.

# other Visualizzare i risultati in altri formati

Piuttosto che modificare il display esistente si potrebbe desiderare di produrre un HTML completamente diverso o perfino generare un output testuale o in XML. Piuttosto che sovrascrivere ogni singolo metodi in, è possibile salire di un passo nella gerarchia delle classi ed estendere direttamente `SimpleReporter` dsel file simple_test.php.

Un esempio di display che non fa niente se non mostrare una pagina bianca potrebbe essere: <strong>require_once('simpletest/simple_test.php');</strong> class MyDisplay extends SimpleReporter {<strong> </strong> function paintHeader($test_name) { } function paintFooter($test_name) { } function paintStart($test_name, $size) {<strong> parent::paintStart($test_name, $size);</strong> } function paintEnd($test_name, $size) {<strong> parent::paintEnd($test_name, $size);</strong> } function paintPass($message) {<strong> parent::paintPass($message);</strong> } function paintFail($message) {<strong> parent::paintFail($message);</strong> } } Finché non si definisce un output questa classe non ne produrrà alcuno.

# cli Usare SimpleTest dalla riga di comando

SimpleTest è provvisto anche di un reporter minimale a riga di comando. L'interfaccia, fino ad un certo punto, imita quella di JUnit ma a differenza di questo visualizza i messaggi di failure non appena vengono ricevuti. Per utilizzare il reporter a riga di comando è sufficiente sostituirla a quella HTML: <?php require_once('simpletest/autorun.php'); $test = &new TestSuite('File test'); $test->addFile('tests/file_test.php'); $test->run(<strong>new TextReporter()</strong>); ?> Dopo di che, si invoca la test suite dalla command line:

    php file_test.php

Naturalmente, ci sarà bisogno della versione CLI di PHP. Un test passato con successo assomiglierà a:

    File test
    OK
    Test cases run: 1/1, Failures: 0, Exceptions: 0

Un test fallito, invece, visualizzerà:

    File test
    1) True assertion failed.
        in createnewfile
    FAILURES!!!
    Test cases run: 1/1, Failures: 1, Exceptions: 0

Uno dei motivi per cui si può desiderare di usare una test suite a linea di comando è per l'integrazione del tester all'intero di qualche processo automatizzato. Per un funzionamento corretto negli script shell, il test dovrebbe restituire un codice diverso di zero in caso di fallimento. Quando una test suite fallisce, il metodo `SimpleTest::run()` restituisce `false`. E' possibile usaere questo risultato per far produrre allo script l'adeguato codice di uscita: <?php require_once('simpletest/autorun.php'); $test = &new TestSuite('File test'); $test->addFile('tests/file_test.php'); <strong>exit ($test->run(new TextReporter()) ? 0 : 1);</strong> ?> Ovviamente, non si vuole dover scrivere davvero due script di test separati per ogni test suite, uno per la riga di comando ed uno per il browser. Per questo, il reporter a riga di comando include un metodo per intercettare l'ambiente di runtime: <?php require_once('simpletest/autorun.php'); $test = &new TestSuite('File test'); $test->addFile('tests/file_test.php'); <strong>if (TextReporter::inCli()) {</strong> exit ($test->run(new TextReporter()) ? 0 : 1); <strong>}</strong> $test->run(new HtmlReporter()); ?> Questo è il sistema usato dentro SimpleTest stesso.

# xml Usare l'XML per i collaudi in remoto

SimpleTest viene fornito con una classe `XmlReporter` utilizzata per comunicazioni interne. Quando viene eseguita, produce un output di questo tipo:

    <?xml version="1.0"?>
    <run>
      <group size="4">
        <name>Remote tests</name>
        <group size="4">
          <name>Visual test with 48 passes, 48 fails and 4 exceptions</name>
          <case>
            <name>testofunittestcaseoutput</name>
            <test>
              <name>testofresults</name>
              <pass>This assertion passed</pass>
              <fail>This assertion failed</fail>
            </test>
            <test>
              ...
            </test>
          </case>
        </group>
      </group>
    </run>

E' possibile utilizzare questo formato con il parser di cui è provvisto SimpleTest, chiamato `SimpleTestXmlParser` e memorizzato nel file xml.php del pacchetto SimpleTest: <?php require_once('simpletest/xml.php'); ... $parser = &new SimpleTestXmlParser(new HtmlReporter()); $parser->parse($test_output); ?> `$test_output` dovrebbe essere il testo XML prodotto dal reporter XML e potrebbe giungere dall'esecuzione di un test case da riga di comando. Il parser invia gli eventi al reporter esattamente come in ogni altra esecuzione di test. Ci sono alcuni casi particolari dove questo può risultare utile.

Un problema con test suite particolarmente grandi è che possono esaurire il limite standard di 8Mb a disposizione del processo PHP. Con un output in XML e l'esecuzione in processi separati, l'output può essere inviato successivamente al parser affinché produca un risultato molto più leggero ad un test a livello più alto.

Dal momento che il risultato XML può essere stato prodotto ovunque, questo apre la possibilità di aggregare i risultati delle esecuzioni di test di server remoti. Esiste un test case all'interno di SimpleTest che realizza questo risultato, ma è ancora alla fase sperimentale:

<?php <strong>require_once('../remote.php');</strong> require_once('../reporter.php'); $test_url = ...; $dry_url = ...; $test = &new TestSuite('Remote tests'); $test->addTest(<strong>new RemoteTestCase($test_url, $dry_url)</strong>); $test->run(new HtmlReporter()); ?> `RemoteTestCase` richiede l'url del test, cioè fondamentalmente della pagina web in formato XML contenente il test. Richiede inoltre l'url di un reporter impostato come dry run. Questo è richiesto per visualizzare l'avanzamento dei test in modo corretto. `RemoteTestCase` può essere aggiunto alle test suite esattamente come ogni altro gruppo di test.

Visualizzare i report in HTML Visualizzare i risultati in altri formati Usare SimpleTest dalla riga di comando Usare l'XML per i collaudi in remoto
SimpleTest project page on SourceForge. SimpleTest download page on LastCraft. The developer's API for SimpleTest gives full detail on the classes and assertions available.
php unit testing, documentation, marcus baker, simpletest, remote testing, xml tests, automated testing