PageRenderTime 40ms CodeModel.GetById 30ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/lastcraft/simpletest/docs/source/it/first_test_tutorial.xml

https://bitbucket.org/mjmeintjes/mattsum-datafeed-helpers
XML | 448 lines | 434 code | 13 blank | 1 comment | 0 complexity | f972dc2ac2fdb69cffad2149ab7034ac MD5 | raw file
  1<?xml version="1.0"?>
  2<!-- $Id$ -->
  3<page title="Tutorial: unit testing con SimpleTest" here="Tutorial: unit testing con SimpleTest">
  4    <synchronisation lang="en" version="0" date="08/06/2011" maintainer="arialdomartini" />
  5    <long_title>PHP unit testing tutorial - Creating an example test case in PHP</long_title>
  6    <content>
  7        <introduction>
  8            <p>
  9				Nel caso tu sia inesperto di unit testing, la raccomandazione è
 10				di provare di volta in volta il codice che si incontrerà durante lettura del tutorial:
 11                non richiede molto da scrivere e fornisce la sensazione di quale sia il ritmo
 12				della programmazione guidata dal collaudo.
 13            </p>
 14            <p>
 15				Per eseguire gli esempi è necessaria una directory vuota contenente
 16				le directory <em>classes</em>, <em>tests</em> e <em>temp</em>.
 17				Decomprimere quindi il framework <a href="download.php">SimpleTest</a>
 18				in <em>tests</em> ed assicurarsi che il web server possa raggiungere
 19				le varie posizioni.
 20            </p>
 21        </introduction>
 22        <section name="new" title="Un nuovo test case">
 23            <p>
 24				Nel <a href="start-testing.html">tutorial rapido</a>
 25				è stato mostrato il collaudo di unità applicato ad una semplice classe di log.
 26				In questo tutorial su SimpleTest ho intenzione di provare
 27				a raccontare l'argomento dello sviluppo della classe nella sua interezza.
 28				La classe dell'esempio è piccola e semplice e nel corso dell'introduzione
 29				riceverà probabilmente più attenzione di quanta ne riceverebbe
 30				realmente in produzione.
 31				Ma perfino una classe minuscola come questa richiederà decisioni sul
 32				design di soprendente difficoltà.
 33            </p>
 34            <p>
 35				Può darsi decisioni fin troppo difficili?
 36                Piuttosto che tentare di disegnare il tutto fin dall'inizio,
 37				si partirà con un requisito noto: il fatto che si vuole
 38				scrivere un messaggio su un file.
 39				Il messaggio deve essere accodato al file se questo esiste.
 40				Successivamente ci si porrà ilproblema di gestire le
 41				priorità, i filtraggi etc, ma per adesso posizioneremo
 42				il requisito della scrittura del file in cima ai nostri pensieri.
 43				Per paura di confonderci non penseremo a nient'altro.
 44				Ok, scriviamo un test:
 45<php><![CDATA[
 46<strong><?php
 47require_once(dirname(__FILE__) . '/simpletest/autorun.php');
 48
 49class TestOfLogging extends UnitTestCase {
 50    function testFirstLogMessagesCreatesFileIfNonexistent() {
 51    }
 52}
 53?></strong>
 54]]></php>
 55				Vediamo, passo passo, cosa significa.
 56            </p>
 57            <p>
 58				Il costrutto <code>dirname(__FILE__)</code> si limita a garantire
 59				che il path venga interpretato relativamente alla posizione del file corrente.
 60            </p>
 61            <p>
 62				Cos'è il file <em>autorun.php</em>?
 63                Questo file si occupa di rendere disponibile la definizione di
 64                <code>UnitTestCase</code>.
 65				Recupera tutte le classi dei test definite nel file corrente
 66				e le esegue automagicamente.
 67				Per ottenere questo risultato, imposta un handler di uscita dallo
 68				script PHP.
 69				Approfondiremo il discorso più tardi quando si affronterà
 70				l'argomento della modifica dell'output.
 71            </p>
 72            <p>
 73				I test stessi sono raccolti in classi di test case.
 74				La classe dell'esempio, <code>TestOfLogging</code>, estende, come nel caso
 75				più tipico, <code>UnitTestCase</code>.
 76				Quando il test case viene invocato, l'autorunner si metterà alla ricerca
 77				dei metodi della classe il cui nome inizi per &quot;test&quot;.
 78				Ciascuno di questi metodi verrà eseguito nell'ordine in cui è
 79				definito nella classe.
 80            </p>
 81            <p>
 82				L'unico metodo attualmente presente nella classe è 
 83                <code>testFirstLogMessagesCreatesFileIfNonexistent()</code>.
 84                Non contiene ancora niente.
 85            </p>
 86            <p>
 87				Adesso, la definizione vuota del metodo non può eseguire alcunché.
 88				Abbiamo bisogno di riempirla con del codice.
 89				La classe <code>UnitTestCase</code>, normalmente, è
 90				pensata per generare durante il suo funzionamento degli eventi  che 
 91				vengono inviati ad un reporter in attesa, attraverso i metodi ereditati da
 92				<code>UnitTestCase</code>.
 93            </p>
 94            <p>
 95				Adesso, aggiungiamo il codice di test:
 96<php><![CDATA[
 97<?php
 98require_once(dirname(__FILE__) . '/simpletest/autorun.php');
 99require_once('../classes/log.php');</strong>
100
101class TestOfLogging extends UnitTestCase {
102    function testFirstLogMessagesCreatesFileIfNonexistent() {<strong>
103        @unlink(dirname(__FILE__) . '/../temp/test.log');
104        $log = new Log(dirname(__FILE__) . '/../temp/test.log');
105        $log->message('Should write this to a file');
106        $this->assertTrue(file_exists(dirname(__FILE__) . '/../temp/test.log'));</strong>
107    }
108}
109?>
110]]></php>
111            </p>
112            <p>
113				Starai probabilmente pensando che si tratti di troppo codice
114				per un singolo collaudo e su questo concordo.
115				Non temere. Questo è un costo una tantum a da questo momento in poi
116				i test saranno uno scherzo da aggiungere.
117				E saranno ancora più semplici con i meccanismi che vedremo
118				più avanti.
119            </p>
120            <p>
121				Può anche darsi che tu abbia pensato che
122                <code>testFirstLogMessagesCreatesFileIfNonexistent</code>
123				sia un nome orribile e troppo lungo per un metodo.
124				Generalmente questo sarebbe vero, ma in questo contesto è una
125				buona scelta.
126				Non capiterà mai più di dover digitare nuovamente questa stringa ed
127				il nome lungo permette di risparmiare commenti e specifiche.
128            </p>
129            <p>
130				Adesso è il momento della nostra prima decisione.
131				Il nostro file si chiama <em>log_test.php</em> (qualsiasi nome sarebbe
132				andato bene) e si trova in una directory chiamata <em>tests</em> (qualsiasi
133				posizione sarebbe andata ugualmente bene).
134				Abbiamo chiamato il file del codice da collaudare <em>log.php</em> e
135				lo abbiamo posizionato in una directory chiamata <em>classes</em>, il che
136				significa che ci apprestiamo a scrivere una classe, ok?
137            </p>
138            <p>
139				In questo esempio è quello che faremo, ma lo unit tester non
140				è limitato al solo collaudo delle classi.
141				Il fatto è che il codice orientato agli oggetti e semplice
142				da decomporre e da ridisegnare per permettere i collaudi.
143                Non è un caso che lo stile di collaudo granulare degli unit test
144				sia storicamente emerso dalla comunità degli sviluppatori object
145				oriented.
146            </p>
147            <p>
148				Il test di per se' è minimale.
149				Per prima cosa elimina qualsiasi file di test dovesse
150				essere rimasto da precedenti esecuzioni.
151				Le decisioni di design sopraggiungono rapidamente e tutte insieme.
152				
153				La nostra classe si chiama <code>Log</code> ed
154				accetta il path del file nel costruttore.
155				Noi creiamo un log ed immediatamente gli inviamo
156				un messaggio con il metodo
157                <code>message()</code>.
158				Sfortunatamente, la capacità di scegliere nomi originali
159				non è una caratteristica molto richiesta agli sviluppatori
160				software.
161            </p>
162            <p>
163				L'elemento base di uno unit test è l'assert.
164				Qui si desidera assicurarsi che il log file al quale si è
165				inviato il messaggio venga veramente creato.
166				
167                <code>UnitTestCase::assertTrue()</code>
168				invia un evento di successo se la condizione viene valutata come
169				vera ed un evento di fallimento in caso contrario.
170				Disponiamo di una varietà di differenti assert e di un insieme ancor
171				più grande se estendiamo i nostri test case.
172            </p>
173            <p>
174                Questa è una lista base:
175                <table><tbody>
176					 <tr><td><code>assertTrue($x)</code></td><td>Fallisce se $x è falso</td></tr>
177                    <tr><td><code>assertFalse($x)</code></td><td>Fallisce se $x è vero</td></tr>
178                    <tr><td><code>assertNull($x)</code></td><td>Fallisce se $x è impostato</td></tr>
179                    <tr><td><code>assertNotNull($x)</code></td><td>Fallisce se $x è non impostato</td></tr>
180                    <tr><td><code>assertIsA($x, $t)</code></td><td>Fallisce se $x non è una classe del tipo $t</td></tr>
181                    <tr><td><code>assertNotA($x, $t)</code></td><td>Fallisce se $x è una classe del tipo $t</td></tr>
182                    <tr><td><code>assertEqual($x, $y)</code></td><td>Fallisce se $x == $y è falso</td></tr>
183                    <tr><td><code>assertNotEqual($x, $y)</code></td><td>Fallisce se $x == $y è vero</td></tr>
184                    <tr><td><code>assertWithinMargin($x, $y, $m)</code></td><td>Fallisce se abs($x - $y) &lt; $m è falso</td></tr>
185                    <tr><td><code>assertOutsideMargin($x, $y, $m)</code></td><td>Fallisce se abs($x - $y) &lt; $m è vero</td></tr>
186                    <tr><td><code>assertIdentical($x, $y)</code></td><td>Fallisce se $x == $y è falso or se i tipi differiscono</td></tr>
187                    <tr><td><code>assertNotIdentical($x, $y)</code></td><td>Fallisce se $x == $y è vero ed i tipi sono uguali</td></tr>
188                    <tr><td><code>assertReference($x, $y)</code></td><td>Fallisce a meno che $x e $y siano la stessa variabile</td></tr>
189                    <tr><td><code>assertCopy($x, $y)</code></td><td>Fallisce a meno che $x e $y siano copie identiche</td></tr>
190					<tr><td><code>assertSame($x, $y)</code></td><td>Fallisce a meno che $x e $y siano lo stesso oggetto</td></tr>
191					<tr><td><code>assertClone($x, $y)</code></td><td>Fallisce a meno che $x e $y siano identici ma siano oggetti separati</td></tr>
192                    <tr><td><code>assertPattern($p, $x)</code></td><td>Fallisce a meno che l'espressione regolare $p soddisfi $x</td></tr>
193                    <tr><td><code>assertNoPattern($p, $x)</code></td><td>Fallisce se l'espressione regolare $p nonn soddisfi $x</td></tr>
194                    <tr><td><code>expectError($x)</code></td><td>Fallisce se non viene generato un errore che soddisfi il matching con $x</td></tr>
195                    <tr><td><code>expectException($x)</code></td><td>Fallisce se non viene lanciata un'eccezione che soddisfi il matching con $x</td></tr>
196                    <tr><td><code>ignoreException($x)</code></td><td>Ignora qualsiasi eccezione dovesse essere lanciata</td></tr>
197                </tbody></table>
198            </p>
199            <p>
200				Adesso siamo pronti ad eseguire lo script di test puntandovi il browser.
201                Cosa succederà?
202                Dovrebbe essere visualizzato un crash:
203                <div class="demo">
204                    <b>Fatal error</b>: Failed opening required '../classes/log.php' (include_path='') in <b>/home/marcus/projects/lastcraft/tutorial_tests/Log/tests/log_test.php</b> on line <b>7</b>
205                </div>
206				La ragione è che <em>log.php</em> non è ancora stato creato.
207            </p>
208            <p>
209				Aspetta, ma questo è assurdo!
210				Non starai mica cercando di costruire un collaudo senza ancora avere una sola riga del
211				codice che vuoi collaudare, vero?
212            </p>
213        </section>
214        <section name="tdd" title="Test Driven Development">
215            <p>
216				Il coinventore di <a href="http://www.extremeprogramming.org/">eXtreme Programming</a>,
217				Kent Beck, ha pubblicato un nuovo manifesto.
218				Il libro si intitola
219                <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321146530/ref=lib_dp_TFCV/102-2696523-7458519?v=glance&amp;s=books&amp;vi=reader#reader-link">Test driven development</a>
220				(TDD) e promuove lo unit testing ad una posizione chiave nel design di software.
221				In breve, l'idea è di scrivere  dei piccoli test prima e
222				solo dopo occuparsi della scrittura del codice.
223				Per qualsiasi codice.
224                Fidatevi, funziona.
225            </p>
226            <p>
227				Scrivi un nuovo test e fai in modo che passi con successo.
228				Quello che otterrai all'inizio è un po' di ridondanza e, generalmente, del codice
229				di qualità schifosa.
230				Assicurandoti che i test continuino a passare ti puoi preoccupare, allora, di ri-arrangiare 
231				il codice, cioè di fare il refactoring.
232				Questo ti garantisce di non compromettere le funzionalità.
233				Una volta che il codice è pulito quanto possibile sei pronto ad aggiungere
234				nuove funzionalità, ma non lo farai: aggiungerai, invece, un altro test
235				per la nuova feature e ricomincerai nuovamente il ciclo.
236				Le funzionalità verranno generate attraverso i tentativi di far
237				passare con successo i test che le definiscono.
238            </p>
239            <p>
240				Immagina il test come una specifica eseguibile che sia stata creata per l'occasione.
241            </p>
242            <p>
243				E' un approccio radicale e personalmente mi sembra incompleto ma
244				è molto efficace per spiegare cosa sia uno unit tester.
245				Nel nostro caso abbiamo un test che fallisce (per non dire che va in crash)
246				così avremo bisogno di scrivere del codice in <em>log.php</em>:
247<php><![CDATA[
248<strong><?php
249class Log {
250    
251    function __construct($path) {
252    }
253        
254    function message($message) {
255    }
256}
257?></strong>
258]]></php>
259				Questo è il minimo da fare per evitare fatal error di PHP.
260				Adesso recuperiamo il risultato:
261                <div class="demo">
262                    <h1>TestOfLogging</h1>
263                    <span class="fail">Fail</span>: testFirstLogMessagesCreatesFileIfNonexistent-&gt;True assertion failed.<br />
264                    <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete.
265                    <strong>0</strong> passes, <strong>1</strong> fails and <strong>0</strong> exceptions.</div>
266                </div>
267				&quot;TestOfLogging&quot; ha fallito.
268				SimpleTest, di default, utilizza i nomi delle classi per descrivere
269				i test ma è sempre possibile sostituire il nome con uno di nostra scelta:
270<php><![CDATA[
271class TestOfLogging extends UnitTestCase {
272    <strong>function __construct() {
273        parent::__construct('Log test');
274    }</strong>
275
276    function testFirstLogMessagesCreatesFileIfNonexistent() {<strong>
277        @unlink(dirname(__FILE__) . '/../temp/test.log');
278        $log = new Log(dirname(__FILE__) . '/../temp/test.log');
279        $log->message('Should write this to a file');
280        $this->assertTrue(file_exists(dirname(__FILE__) . '/../temp/test.log'));</strong>
281    }
282}
283]]></php>
284                Il che fornisce:
285                <div class="demo">
286                    <h1>Log test</h1>
287                    <span class="fail">Fail</span>: testFirstLogMessagesCreatesFileIfNonexistent-&gt;File created.<br />
288                    <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete.
289                    <strong>0</strong> passes, <strong>1</strong> fails and <strong>0</strong> exceptions.</div>
290                </div>
291				Se si ha intenzione di cambiare il nome del test si deve intervenire
292				modificando l'output del reporter, operazione che affronteremo più tardi.
293            </p>
294            <p>
295				Per far passare il test si potrebbe semplicemente creare il file
296				nel costruttore di <code>Log</code>.
297				Questa tecnica d'&quot;inganno&quot; è molto utile per controllare
298				che i test funzionino, a mali estremi.
299				Questo è particolarmente vero nel caso si siano registrati fallimenti dei 
300				test e ci si voglia assicurare di non aver dimenticato qualcosa di
301				stupido.
302				Non procederemo così lentamente, perciò:
303<php><![CDATA[
304<?php   
305class Log {<strong>
306    var $path;</strong>
307        
308    function __construct($path) {<strong>
309        $this->path = $path;</strong>
310    }
311        
312    function message($message) {<strong>
313        $file = fopen($this->path, 'a');
314        fwrite($file, $message . "\n");
315        fclose($file);</strong>
316    }
317}
318?>
319]]></php>
320				Ho dovuto incontrare non meno di quattro failure per raggiungere questo passo:
321				non avevo creato la directory temporanea, non l'avevo impostata come
322				pubblicamente accessibile in scrittura, avevo un errore di battitura e mi
323				ero dimenticato di aggiungere la nuova cartella sul CVS (questo l'ho scoperto più 
324				tardi).
325				Ognuno di questi problemi avrebbe potuto tenermi occupato per diverse ore
326				se solo si fosse manifestato in un secondo momento, ma è proprio per
327				questo che i test servono.
328                
329            </p>
330            <p>
331				Con le correzioni necessarie si è ottenuto:
332                <div class="demo">
333                    <h1>Log test</h1>
334                    <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
335                    <strong>1</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
336                </div>
337                Successo!
338            </p>
339            <p>
340				Può darsi che tu non gradisca lo stile di visualizzazione minimale.
341				Di default, i successi non vengono mostrati perché, generalmente, non c'è
342				bisogno di ulteriori informazioni quando si ha la situazione
343				sotto controllo.
344				Se non si sa come le cose stanno procedendo, allora è il caso di scrivere
345				ulteriori test.
346            </p>
347            <p>
348				Ok, qui sono stato fin troppo rigido.
349				Se desideri vedere anche i casi di successo allora ti basta
350				<a local="display_subclass_tutorial">estendere la classe
351                <code>HtmlReporter</code></a>
352                ed aggiungerla ai test al posto del reporter standard.
353				Anche io gradisco il comfort, ogni tanto.
354            </p>
355        </section>
356        <section name="doc" title="I test come documentazione">
357            <p>
358				Adesso una sottigliezza.
359                Non vogliamo che il file creato esista fino a che non
360				inviamo il messaggio.
361				Piuttosto che pensarci troppo sopra, aggiungeremo
362				intanto l'assert:
363<php><![CDATA[
364class TestOfLogging extends UnitTestCase {
365    function testFirstLogMessagesCreatesFileIfNonexistent() {
366        @unlink(dirname(__FILE__) . '/../temp/test.log');
367        $log = new Log(dirname(__FILE__) . '/../temp/test.log');<strong>
368        $this->assertFalse(file_exists(dirname(__FILE__) . '/../temp/test.log'));</strong>
369        $log->message('Should write this to a file');
370        $this->assertTrue(file_exists(dirname(__FILE__) . '/../temp/test.log'));
371
372    }
373}
374]]></php>
375                per scoprire che già funzionava così:
376                <div class="demo">
377                    <h1>TestOfLogging</h1>
378                    <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
379                    <strong>2</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
380                </div>
381				Ora, sapevo che avrebbe funzionato.
382				Ho aggiunto il test che lo conferma in parte per mettere in pace l'animo e in parte
383				per documentare questo comportamento.
384				Questa unica linea extra dice molto di più, in questo contesto, di dozzine
385				di righe di use case o di un intero diagramma di attività UML.
386				Che la test suite sia una sorgente di documentazione è un piacevole
387				effetto collaterale di tutti i test.
388                
389            </p>
390            <p>
391				Dovremmo pulire il file temporaneo alla fine del test?
392                Di solito faccio questa operazione quando ho terminato
393				il metodo di test e vedo che funziona.
394				Non ho voglia di inserire in CVS del codice che lasci in giro 
395				residui di file di test dopo i collaudi.
396                Non voglio farlo mentre scrivo i test, comunque.
397				Probabilmente dovrei, ma a volte ho bisogno di vedere come
398				le cose procedono e, poi, è una questione di comodità.
399            </p>
400            <p>
401				Nella progetti reali si produce più di un test case e, pertanto,
402				il prossimo argomento che dobbiamo trattare è
403				
404				<a local="group_test_tutorial">il raggruppamento dei test in test suite.</a>.
405            </p>
406        </section>
407    </content>
408    <internal>
409        <link>Creating a <a href="#new">new test case</a>.</link>
410        <link><a href="#tdd">Test driven development</a> in PHP.</link>
411        <link><a href="#doc">Tests as documentation</a> is one of many side effects.</link>
412    </internal>
413    <external>
414        <link>
415            The <a href="http://junit.sourceforge.net/doc/faq/faq.htm">JUnit FAQ</a>
416            has plenty of useful testing advice.
417        </link>
418        <link>
419            <a href="group_test_tutorial.php">Next</a> is grouping test
420            cases together.
421        </link>
422        <link>
423            You will need the <a href="simple_test.php">SimpleTest testing framework</a>
424            for these examples.
425        </link>
426    </external>
427    <meta>
428        <keywords>
429            software development,
430            php programming,
431            programming php,
432            software development tools,
433            php tutorial,
434            free php scripts,
435            architecture,
436            php resources,
437            mock objects,
438            junit,
439            php testing,
440            unit test,
441            automated php testing,
442            test cases tutorial,
443            explain unit test case,
444            unit test example,
445            unit test
446        </keywords>
447    </meta>
448</page>