Your SlideShare is downloading. ×
0
Il testing con ZendFrameworkEnrico ZimuelSenior Consultant & ArchitectZend Technologies                                © A...
Sommario●   Introduzione allo Unit Testing in PHP●   Le funzionalità di base di test con ZF●   Alcuni scenari avanzati di ...
Perchè testare il codice?            © All rights reserved. Zend Technologies, Inc.
Semplificare la manutenzione●   Il testing definisce le aspettative●   Il testing descrive i comportamenti       dellappli...
Quantificare la qualità del codice●   Copertura del codice (code coverage)    effettuata dagli strumenti di testing●   I m...
Benefici psicologici per gli sviluppatori    Quando il test è ok, gli sviluppatori sono più    confidenti e motivati!6    ...
Testing non è … ricaricare una pagina7             © All rights reserved. Zend Technologies, Inc.
Testing non è … var_dump()8            © All rights reserved. Zend Technologies, Inc.
Testing è … riproducibile9              © All rights reserved. Zend Technologies, Inc.
Testing è … automatizzabile10             © All rights reserved. Zend Technologies, Inc.
In un buon testing …●   Si definiscono i comportamenti●   Si forniscono esempi su scenari dutilizzo●   Si definiscono le a...
PHP testing frameworks●   PHPT      ▶   Utilizzato da PHP, da PEAR e da alcune            librerie indipendenti●   SimpleT...
Le basi del testing13               © All rights reserved. Zend Technologies, Inc.
Scrivere unit test●   Creare una classe di test●   Creare uno o più metodi che definiscono dei    comportamenti       ▶   ...
Creare una classe di test●   Solitamente il nome termina per Test      class EntryTest       class EntryTest          exte...
Scrivere un metodo che definisce ilcomportamento ●   prefisso “test”class EntryTest class EntryTest    extends PHPUnit_Fra...
Scrivere il codice per il comportamentoclass EntryTest class EntryTest    extends PHPUnit_Framework_TestCase     extends P...
Scrivere asserzioni per uncomportamento attesoclass EntryTest class EntryTest    extends PHPUnit_Framework_TestCase     ex...
Eseguire il test●   Fallimento?      ▶   Verifica il test e le asserzioni per eventuali            errori di battitura o c...
Alcuni termini del testing20               © All rights reserved. Zend Technologies, Inc.
Test scaffolding●   Essere sicuri che lambiente di testing sia    libero da pre-requisiti●   Inizializzare le dipendenze n...
Test doubles●   Stubs    Sostituire un oggetto con un altro per    continuare il test●   Mock Objects    Sostituire un ogg...
Alcune tipologie di test●   Testing condizionali    Testing solo al verificarsi di alcune    condizioni dambiente●   Testi...
Testing semi-funzionale     in Zend Framework24              © All rights reserved. Zend Technologies, Inc.
Fasi principali●   Setup dellambiente phpUnit●   Creare uno scenario di test (TestCase)    basato su un Controller    (Con...
Lambiente PHPUnit●   Struttura delle directory              tests               tests              |-- application        ...
Lambiente PHPUnit (2)●    phpunit.xml    <phpunit bootstrap="./Bootstrap.php">     <phpunit bootstrap="./Bootstrap.php">  ...
Lambiente PHPUnit (3)●   Bootstrap.php     $rootPath == realpath(dirname(__DIR__));      $rootPath     realpath(dirname(__...
Creare una classe di test●   Estendere la Zend_Test_PHPUnit_ControllerTestCase    class ExampleControllerTest     class Ex...
Bootstrap dellapplicazione●   Creare unistanza di Zend_Application e    referenziarla nel setUp()    class ExampleControll...
Creazione e dispatch di una richiesta●   Metodo semplice: dispatch di una “url”class ExampleControllerTest class ExampleCo...
Creazione e dispatch di una richiesta (2)●   Avanzato: personalizzare loggetto della    richiesta prima di eseguire il dis...
Creare asserzioni●   Tipiche asserzioni:       ▶   Verifica della struttura della risposta e dei             markup       ...
Asserzioni con selettori CSS●   assertQuery($path, $message = )●   assertQueryContentContains(      $path, $match, $messag...
Asserzioni con selettori XPath●   assertXpath($path, $message = )●   assertXpathContentContains(      $path, $match, $mess...
Asserzioni su Redirect●   assertRedirect($message = )●   assertRedirectTo($url, $message = )●   assertRedirectRegex($patte...
Asserzioni sulle risposte●   assertResponseCode($code, $message = )●   assertHeader($header, $message = )●   assertHeaderC...
Asserzioni sulle richieste●   assertModule($module, $message = )●   assertController($controller, $message = )●   assertAc...
Esempi di asserzionipublic function testSomeStaticPageHasGoodStructure() public function testSomeStaticPageHasGoodStructur...
Esempi di asserzioni (2)   public function testXhrRequestReturnsJson()    public function testXhrRequestReturnsJson()   {{...
Alcuni casi avanzati di testing41               © All rights reserved. Zend Technologies, Inc.
Testing di modelli e risorse●   Problema:    Queste classi non vengono caricate con il    sistema di autoloading●   Soluzi...
Esempio class Blog_Model_EntryTest  class Blog_Model_EntryTest     extends PHPUnit_Framework_TestCase      extends PHPUnit...
Testing con autenticazione●   Problema:    Alcune azioni possono richiedere    unautenticazione utente, come emularla    i...
Esempio class ExampleControllerTest  class ExampleControllerTest     extends Zend_Test_PHPUnit_ControllerTestCase      ext...
Esempio (2) class ExampleControllerTest  class ExampleControllerTest     extends Zend_Test_PHPUnit_ControllerTestCase     ...
Testing di pagine che dipendono daaltre azioni●   Problema:    Alcune azioni possono dipendere    dallesito di altre, ad e...
Esempioclass ExampleControllerTest class ExampleControllerTest    extends Zend_Test_PHPUnit_ControllerTestCase     extends...
Conclusioni49                 © All rights reserved. Zend Technologies, Inc.
Eseguire sempre il test!●   Test dei modelli, dei livelli di servizio, etc●   Eseguire test funzionali e di accettazione  ...
Grazie!Per maggiori informazioni:http://www.zend.comhttp://framework.zend.com              © All rights reserved. Zend Tec...
Upcoming SlideShare
Loading in...5
×

Il testing con zend framework

554

Published on

Published in: Technology
1 Comment
0 Likes
Statistics
Notes
  • Be the first to like this

No Downloads
Views
Total Views
554
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
5
Comments
1
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Il testing con zend framework"

  1. 1. Il testing con ZendFrameworkEnrico ZimuelSenior Consultant & ArchitectZend Technologies © All rights reserved. Zend Technologies, Inc.
  2. 2. Sommario● Introduzione allo Unit Testing in PHP● Le funzionalità di base di test con ZF● Alcuni scenari avanzati di testing con ZF © All rights reserved. Zend Technologies, Inc.
  3. 3. Perchè testare il codice? © All rights reserved. Zend Technologies, Inc.
  4. 4. Semplificare la manutenzione● Il testing definisce le aspettative● Il testing descrive i comportamenti dellapplicazione● Il testing identifica i cambiamenti nel codice sorgente che violano (“rompono”) i comportamenti attesi del software © All rights reserved. Zend Technologies, Inc.
  5. 5. Quantificare la qualità del codice● Copertura del codice (code coverage) effettuata dagli strumenti di testing● I metodi di test documentano i comportamenti attesi del software © All rights reserved. Zend Technologies, Inc.
  6. 6. Benefici psicologici per gli sviluppatori Quando il test è ok, gli sviluppatori sono più confidenti e motivati!6 © All rights reserved. Zend Technologies, Inc.
  7. 7. Testing non è … ricaricare una pagina7 © All rights reserved. Zend Technologies, Inc.
  8. 8. Testing non è … var_dump()8 © All rights reserved. Zend Technologies, Inc.
  9. 9. Testing è … riproducibile9 © All rights reserved. Zend Technologies, Inc.
  10. 10. Testing è … automatizzabile10 © All rights reserved. Zend Technologies, Inc.
  11. 11. In un buon testing …● Si definiscono i comportamenti● Si forniscono esempi su scenari dutilizzo● Si definiscono le aspettative © All rights reserved. Zend Technologies, Inc.
  12. 12. PHP testing frameworks● PHPT ▶ Utilizzato da PHP, da PEAR e da alcune librerie indipendenti● SimpleTest ▶ Un framework di testing in stile JUnit● PHPUnit ▶ Un framework di testing in stile JUnit ▶ De facto lo standard di testing in PHP © All rights reserved. Zend Technologies, Inc.
  13. 13. Le basi del testing13 © All rights reserved. Zend Technologies, Inc.
  14. 14. Scrivere unit test● Creare una classe di test● Creare uno o più metodi che definiscono dei comportamenti ▶ Descrivere il comportamento in un linguaggio naturale● Scrivere codice che definisce il comportamento ▶ Scrivere codice utilizzando lAPI● Scrivere le asserzioni per definire il comportamento atteso © All rights reserved. Zend Technologies, Inc.
  15. 15. Creare una classe di test● Solitamente il nome termina per Test class EntryTest class EntryTest extends PHPUnit_Framework_TestCase extends PHPUnit_Framework_TestCase {{ }} © All rights reserved. Zend Technologies, Inc.
  16. 16. Scrivere un metodo che definisce ilcomportamento ● prefisso “test”class EntryTest class EntryTest extends PHPUnit_Framework_TestCase extends PHPUnit_Framework_TestCase{{ public function testMaySetTimestampWithString() public function testMaySetTimestampWithString() {{ }}}} © All rights reserved. Zend Technologies, Inc.
  17. 17. Scrivere il codice per il comportamentoclass EntryTest class EntryTest extends PHPUnit_Framework_TestCase extends PHPUnit_Framework_TestCase{{ public function testMaySetTimestampWithString() public function testMaySetTimestampWithString() {{ $string = Fri, 7 May 2010 09:26:03 -0700; $string = Fri, 7 May 2010 09:26:03 -0700; $ts $ts = strtotime($string); = strtotime($string); $this->entry->setTimestamp($string); $this->entry->setTimestamp($string); $setValue = $this->entry->getTimestamp(); $setValue = $this->entry->getTimestamp(); }}}} © All rights reserved. Zend Technologies, Inc.
  18. 18. Scrivere asserzioni per uncomportamento attesoclass EntryTest class EntryTest extends PHPUnit_Framework_TestCase extends PHPUnit_Framework_TestCase{{ public function testMaySetTimestampWithString() public function testMaySetTimestampWithString() {{ $string = Fri, 7 May 2010 09:26:03 -0700; $string = Fri, 7 May 2010 09:26:03 -0700; $ts $ts = strtotime($string); = strtotime($string); $this->entry->setTimestamp($string); $this->entry->setTimestamp($string); $setValue = $this->entry->getTimestamp(); $setValue = $this->entry->getTimestamp(); $this->assertSame($ts, $setValue); $this->assertSame($ts, $setValue); }}}} © All rights reserved. Zend Technologies, Inc.
  19. 19. Eseguire il test● Fallimento? ▶ Verifica il test e le asserzioni per eventuali errori di battitura o casi duso ▶ Verifica la classe che si stà testando ▶ Eseguire le correzioni e rilanciare il test● Successo? ▶ Creare il prossimo test di comportamento o continuare con le modifiche sul codice del software © All rights reserved. Zend Technologies, Inc.
  20. 20. Alcuni termini del testing20 © All rights reserved. Zend Technologies, Inc.
  21. 21. Test scaffolding● Essere sicuri che lambiente di testing sia libero da pre-requisiti● Inizializzare le dipendenze necessarie per eseguire il test● Di solito linizializzazione dellambiente di test avviene nel metodo setUp() © All rights reserved. Zend Technologies, Inc.
  22. 22. Test doubles● Stubs Sostituire un oggetto con un altro per continuare il test● Mock Objects Sostituire un oggetto con un altro forzandone le aspettative (restituendo valori prestabiliti per i metodi) © All rights reserved. Zend Technologies, Inc.
  23. 23. Alcune tipologie di test● Testing condizionali Testing solo al verificarsi di alcune condizioni dambiente● Testing funzionali e dintegrazione Testing del sistema per verificare i comportamenti attesi; testing delle unità e delle loro interazioni © All rights reserved. Zend Technologies, Inc.
  24. 24. Testing semi-funzionale in Zend Framework24 © All rights reserved. Zend Technologies, Inc.
  25. 25. Fasi principali● Setup dellambiente phpUnit● Creare uno scenario di test (TestCase) basato su un Controller (ControllerTestCase)● Bootstrap dellapplicazione● Creazione di una richiesta e dispatch● Eseguire asserzioni sulle risposte © All rights reserved. Zend Technologies, Inc.
  26. 26. Lambiente PHPUnit● Struttura delle directory tests tests |-- application |-- application || `-- controllers `-- controllers |-- Bootstrap.php |-- Bootstrap.php |-- library |-- library || `-- Custom `-- Custom `-- phpunit.xml `-- phpunit.xml 4 directories, 2 files 4 directories, 2 files © All rights reserved. Zend Technologies, Inc.
  27. 27. Lambiente PHPUnit (2)● phpunit.xml <phpunit bootstrap="./Bootstrap.php"> <phpunit bootstrap="./Bootstrap.php"> <testsuite name="Test Suite"> <testsuite name="Test Suite"> <directory>./</directory> <directory>./</directory> </testsuite> </testsuite> <filter> <filter> <whitelist> <whitelist> <directory <directory suffix=".php">../library/</directory> suffix=".php">../library/</directory> <directory <directory suffix=".php">../application/</directory> suffix=".php">../application/</directory> <exclude> <exclude> <directory <directory suffix=".phtml">../application/</directory> suffix=".phtml">../application/</directory> </exclude> </exclude> </whitelist> </whitelist> </filter> </filter> </phpunit> </phpunit> © All rights reserved. Zend Technologies, Inc.
  28. 28. Lambiente PHPUnit (3)● Bootstrap.php $rootPath == realpath(dirname(__DIR__)); $rootPath realpath(dirname(__DIR__)); if (!defined(APPLICATION_PATH)) {{ if (!defined(APPLICATION_PATH)) define(APPLICATION_PATH, define(APPLICATION_PATH, $rootPath .. /application); $rootPath /application); }} if (!defined(APPLICATION_ENV)) {{ if (!defined(APPLICATION_ENV)) define(APPLICATION_ENV, testing); define(APPLICATION_ENV, testing); }} set_include_path(implode(PATH_SEPARATOR, array( set_include_path(implode(PATH_SEPARATOR, array( ., ., $rootPath .. /library, $rootPath /library, get_include_path(), get_include_path(), ))); ))); require_once Zend/Loader/Autoloader.php; require_once Zend/Loader/Autoloader.php; $loader == Zend_Loader_Autoloader::getInstance(); $loader Zend_Loader_Autoloader::getInstance(); $loader->registerNamespace(Custom_); $loader->registerNamespace(Custom_); © All rights reserved. Zend Technologies, Inc.
  29. 29. Creare una classe di test● Estendere la Zend_Test_PHPUnit_ControllerTestCase class ExampleControllerTest class ExampleControllerTest extends Zend_Test_PHPUnit_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {{ }} © All rights reserved. Zend Technologies, Inc.
  30. 30. Bootstrap dellapplicazione● Creare unistanza di Zend_Application e referenziarla nel setUp() class ExampleControllerTest class ExampleControllerTest extends Zend_Test_PHPUnit_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {{ public function setUp() public function setUp() {{ $this->bootstrap = new Zend_Application( $this->bootstrap = new Zend_Application( APPLICATION_ENV, APPLICATION_ENV, APPLICATION_PATH APPLICATION_PATH . /configs/application.ini . /configs/application.ini ); ); parent::setUp(); parent::setUp(); }} }} © All rights reserved. Zend Technologies, Inc.
  31. 31. Creazione e dispatch di una richiesta● Metodo semplice: dispatch di una “url”class ExampleControllerTest class ExampleControllerTest extends Zend_Test_PHPUnit_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase{{ // ... // ... public function testStaticPageHasGoodStructure() public function testStaticPageHasGoodStructure() {{ $this->dispatch(/example/page); $this->dispatch(/example/page); // ... // ... }}}} © All rights reserved. Zend Technologies, Inc.
  32. 32. Creazione e dispatch di una richiesta (2)● Avanzato: personalizzare loggetto della richiesta prima di eseguire il dispatch class ExampleControllerTest class ExampleControllerTest extends Zend_Test_PHPUnit_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {{ // ... // ... public function testXhrRequestReturnsJson() public function testXhrRequestReturnsJson() {{ $this->getRequest() $this->getRequest() ->setHeader(X-Requested-With, ->setHeader(X-Requested-With, XMLHttpRequest) XMLHttpRequest) ->setQuery(format, json); ->setQuery(format, json); $this->dispatch(/example/xhr-endpoint); $this->dispatch(/example/xhr-endpoint); // ... // ... }} }} © All rights reserved. Zend Technologies, Inc.
  33. 33. Creare asserzioni● Tipiche asserzioni: ▶ Verifica della struttura della risposta e dei markup Utilizzando selettori CSS o query XPath ▶ Verificare il codice della risposta HTTP o lheader di pagina ▶ Verificare artefatti sulla richiesta e sulla risposta © All rights reserved. Zend Technologies, Inc.
  34. 34. Asserzioni con selettori CSS● assertQuery($path, $message = )● assertQueryContentContains( $path, $match, $message = )● assertQueryContentRegex( $path, $pattern, $message = )● assertQueryCount($path, $count, $message = )● assertQueryCountMin($path, $count, $message = )● assertQueryCountMax($path, $count, $message = )● ognuna ha una variante "Not" © All rights reserved. Zend Technologies, Inc.
  35. 35. Asserzioni con selettori XPath● assertXpath($path, $message = )● assertXpathContentContains( $path, $match, $message = )● assertXpathContentRegex( $path, $pattern, $message = )● assertXpathCount($path, $count, $message = )● assertXpathCountMin($path, $count, $message = )● assertXpathCountMax($path, $count, $message = )● ognuna ha una variante "Not" © All rights reserved. Zend Technologies, Inc.
  36. 36. Asserzioni su Redirect● assertRedirect($message = )● assertRedirectTo($url, $message = )● assertRedirectRegex($pattern, $message = )● ognuna ha una variante "Not" © All rights reserved. Zend Technologies, Inc.
  37. 37. Asserzioni sulle risposte● assertResponseCode($code, $message = )● assertHeader($header, $message = )● assertHeaderContains($header, $match, $message = )● assertHeaderRegex($header, $pattern, $message = )● ognuna ha una variante "Not" © All rights reserved. Zend Technologies, Inc.
  38. 38. Asserzioni sulle richieste● assertModule($module, $message = )● assertController($controller, $message = )● assertAction($action, $message = )● assertRoute($route, $message = )● ognuna ha una variante "Not" © All rights reserved. Zend Technologies, Inc.
  39. 39. Esempi di asserzionipublic function testSomeStaticPageHasGoodStructure() public function testSomeStaticPageHasGoodStructure(){{ $this->dispatch(/example/page); $this->dispatch(/example/page); $this->assertResponseCode(200); $this->assertResponseCode(200); $this->assertQuery(div#content p); $this->assertQuery(div#content p); $this->assertQueryCount(div#sidebar ul li, 3); $this->assertQueryCount(div#sidebar ul li, 3);}} © All rights reserved. Zend Technologies, Inc.
  40. 40. Esempi di asserzioni (2) public function testXhrRequestReturnsJson() public function testXhrRequestReturnsJson() {{ // ... // ... $this->assertNotRedirect(); $this->assertNotRedirect(); $this->assertHeaderContains( $this->assertHeaderContains( Content-Type, application/json); Content-Type, application/json); }} © All rights reserved. Zend Technologies, Inc.
  41. 41. Alcuni casi avanzati di testing41 © All rights reserved. Zend Technologies, Inc.
  42. 42. Testing di modelli e risorse● Problema: Queste classi non vengono caricate con il sistema di autoloading● Soluzione: Utilizzare il bootstrap di Zend_Application per caricare manualmente le risorse durante il setUp() © All rights reserved. Zend Technologies, Inc.
  43. 43. Esempio class Blog_Model_EntryTest class Blog_Model_EntryTest extends PHPUnit_Framework_TestCase extends PHPUnit_Framework_TestCase {{ public function setUp() public function setUp() {{ $this->bootstrap = new Zend_Application( $this->bootstrap = new Zend_Application( APPLICATION_ENV, APPLICATION_ENV, APPLICATION_PATH APPLICATION_PATH . /configs/application.ini . /configs/application.ini ); ); $this->bootstrap->bootstrap(modules); $this->bootstrap->bootstrap(modules); $this->model = new Blog_Model_Entry(); $this->model = new Blog_Model_Entry(); }} }} © All rights reserved. Zend Technologies, Inc.
  44. 44. Testing con autenticazione● Problema: Alcune azioni possono richiedere unautenticazione utente, come emularla in fase di testing?● Soluzione: Eseguire unautenticazione manuale utilizzando Zend_Auth prima di eseguire il dispatch() © All rights reserved. Zend Technologies, Inc.
  45. 45. Esempio class ExampleControllerTest class ExampleControllerTest extends Zend_Test_PHPUnit_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {{ // ... // ... public function loginUser($user) public function loginUser($user) {{ $params = array(user => $user); $params = array(user => $user); $adapter = new Custom_Auth_TestAdapter( $adapter = new Custom_Auth_TestAdapter( $params); $params); $auth $auth = Zend_Auth::getInstance(); = Zend_Auth::getInstance(); $auth->authenticate($adapter); $auth->authenticate($adapter); $this->assertTrue($auth->hasIdentity()); $this->assertTrue($auth->hasIdentity()); }} }} © All rights reserved. Zend Technologies, Inc.
  46. 46. Esempio (2) class ExampleControllerTest class ExampleControllerTest extends Zend_Test_PHPUnit_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {{ // ... // ... public function testAdminUserCanAccessAdmin() public function testAdminUserCanAccessAdmin() {{ $this->loginUser(admin); $this->loginUser(admin); $this->dispatch(/example/admin); $this->dispatch(/example/admin); $this->assertQuery(div#content.admin); $this->assertQuery(div#content.admin); }} © All rights reserved. Zend Technologies, Inc.
  47. 47. Testing di pagine che dipendono daaltre azioni● Problema: Alcune azioni possono dipendere dallesito di altre, ad esempio una pagina che evidenzia I risultati di unoperazione di ricerca● Soluzione: Eseguire un doppio dispatch, resettando la richiesta tra una chiamata e laltra © All rights reserved. Zend Technologies, Inc.
  48. 48. Esempioclass ExampleControllerTest class ExampleControllerTest extends Zend_Test_PHPUnit_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase{{ // ... // ... public function testHighlightedTextAfterSearch() public function testHighlightedTextAfterSearch() {{ $this->getRequest()->setQuery( $this->getRequest()->setQuery( search, foobar); search, foobar); $this->dispatch(/search); $this->dispatch(/search); $this->resetRequest(); $this->resetRequest(); $this->resetResponse(); $this->resetResponse(); $this->dispatch(/example/page); $this->dispatch(/example/page); $this->assertQueryContains( $this->assertQueryContains( span.highlight, foobar); span.highlight, foobar); }} © All rights reserved. Zend Technologies, Inc.
  49. 49. Conclusioni49 © All rights reserved. Zend Technologies, Inc.
  50. 50. Eseguire sempre il test!● Test dei modelli, dei livelli di servizio, etc● Eseguire test funzionali e di accettazione per il workflow dellapplicazione, per la struttura delle pagine, etc● Testing = Scrivere codice migliore, più affidabile e di qualità © All rights reserved. Zend Technologies, Inc.
  51. 51. Grazie!Per maggiori informazioni:http://www.zend.comhttp://framework.zend.com © All rights reserved. Zend Technologies, Inc.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×