Il testing con zend framework
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Il testing con zend framework

on

  • 787 views

 

Statistics

Views

Total Views
787
Views on SlideShare
787
Embed Views
0

Actions

Likes
0
Downloads
4
Comments
1

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Il testing con zend framework Presentation Transcript

  • 1. Il testing con ZendFrameworkEnrico ZimuelSenior Consultant & ArchitectZend Technologies © All rights reserved. Zend Technologies, Inc.
  • 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. Perchè testare il codice? © All rights reserved. Zend Technologies, Inc.
  • 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. 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. Benefici psicologici per gli sviluppatori Quando il test è ok, gli sviluppatori sono più confidenti e motivati!6 © All rights reserved. Zend Technologies, Inc.
  • 7. Testing non è … ricaricare una pagina7 © All rights reserved. Zend Technologies, Inc.
  • 8. Testing non è … var_dump()8 © All rights reserved. Zend Technologies, Inc.
  • 9. Testing è … riproducibile9 © All rights reserved. Zend Technologies, Inc.
  • 10. Testing è … automatizzabile10 © All rights reserved. Zend Technologies, Inc.
  • 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. 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. Le basi del testing13 © All rights reserved. Zend Technologies, Inc.
  • 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. 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. 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. 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. 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. 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. Alcuni termini del testing20 © All rights reserved. Zend Technologies, Inc.
  • 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. 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. 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. Testing semi-funzionale in Zend Framework24 © All rights reserved. Zend Technologies, Inc.
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Asserzioni su Redirect● assertRedirect($message = )● assertRedirectTo($url, $message = )● assertRedirectRegex($pattern, $message = )● ognuna ha una variante "Not" © All rights reserved. Zend Technologies, Inc.
  • 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. 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. 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. 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. Alcuni casi avanzati di testing41 © All rights reserved. Zend Technologies, Inc.
  • 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. 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. 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. 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. 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. 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. 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. Conclusioni49 © All rights reserved. Zend Technologies, Inc.
  • 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. Grazie!Per maggiori informazioni:http://www.zend.comhttp://framework.zend.com © All rights reserved. Zend Technologies, Inc.