| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect2 id="zend.test.phpunit.examples">
- <title>Exemples</title>
- <para>
- Savoir comment configurer votre infrastructure de tests et comment faire des
- assertions est seulement la moitié du travail ; maintenant il est temps de commencer à
- regarder quelques scénarios réels de test pour voir comment vous pouvez les étendre.
- </para>
- <example id="zend.test.phpunit.examples.userController">
- <title>Test d'un contrôleur "UserController"</title>
- <para>
- Considérons une tâche habituelle d'un site Web : l'authentification et
- l'enregistrement d'utilisateurs. Dans notre exemple, nous avons défini un contrôleur
- "<code>UserController</code>" pour gérer ceci, il requiert le conditions suivantes
- :
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Si un utilisateur n'est pas authentifié, il sera toujours redirigé vers la
- page de login, sans se soucier de l'action demandée.
- </para>
- </listitem>
- <listitem>
- <para>
- La page avec le formulaire de login présente à la fois le formulaire de
- login et le formulaire d'enregistrement.
- </para>
- </listitem>
- <listitem>
- <para>
- Fournir une identification invalide entraîne un retour au formulaire de
- login.
- </para>
- </listitem>
- <listitem>
- <para>
- Une identification valide entraîne une redirection vers la page avec le
- profil de l'utilisateur.
- </para>
- </listitem>
- <listitem>
- <para>
- La page de profil peut être personnalisée pour contenir le nom
- d'utilisateur.
- </para>
- </listitem>
- <listitem>
- <para>
- Les utilisateurs déjà authentifiés qui accèdent à la page de login sont
- redirigés vers leur page de profil.
- </para>
- </listitem>
- <listitem>
- <para>
- En cas de déconnexion, un utilisateur est redirigé vers la page de
- login.
- </para>
- </listitem>
- <listitem>
- <para>
- Avec des données invalides, l'enregistrement doit entraîner un
- échec.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Nous pourrions, et devrions définir d'autres tests, mais ceux-ci suffiront pour
- l'instant.
- </para>
- <para>
- Pour notre application, nous définirons un plugin "<code>Initialize</code>", qui
- fonctionne en <methodname>routeStartup()</methodname>. Ceci nous permet d'encapsuler notre fichier
- d'amorçage dans une interface POO, et qui nous permet aussi de fournir par une solution
- simple une fonction de rappel ("callback"). Regardons d'abord les bases de cette classe
- :
- </para>
- <programlisting language="php"><![CDATA[
- class Bugapp_Plugin_Initialize extends Zend_Controller_Plugin_Abstract
- {
- /**
- * @var Zend_Config
- */
- protected static $_config;
- /**
- * @var string Current environment
- */
- protected $_env;
- /**
- * @var Zend_Controller_Front
- */
- protected $_front;
- /**
- * @var string Path to application root
- */
- protected $_root;
- /**
- * Constructor
- *
- * Initialize environment, root path, and configuration.
- *
- * @param string $env
- * @param string|null $root
- * @return void
- */
- public function __construct($env, $root = null)
- {
- $this->_setEnv($env);
- if (null === $root) {
- $root = realpath(dirname(__FILE__) . '/../../../');
- }
- $this->_root = $root;
- $this->initPhpConfig();
- $this->_front = Zend_Controller_Front::getInstance();
- }
- /**
- * Route startup
- *
- * @return void
- */
- public function routeStartup(Zend_Controller_Request_Abstract $request)
- {
- $this->initDb();
- $this->initHelpers();
- $this->initView();
- $this->initPlugins();
- $this->initRoutes();
- $this->initControllers();
- }
- // definition of methods would follow...
- }
- ]]></programlisting>
- <para>Ceci nous permet de créer un callback d'amorçage comme ce qui suit :</para>
- <programlisting language="php"><![CDATA[
- class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
- {
- public function appBootstrap()
- {
- $controller = $this->getFrontController();
- $controller->registerPlugin(
- new Bugapp_Plugin_Initialize('development')
- );
- }
- public function setUp()
- {
- $this->bootstrap = array($this, 'appBootstrap');
- parent::setUp();
- }
- // ...
- }
- ]]></programlisting>
- <para>
- Une fois ceci en place, nous pouvons écrire nos tests. Cependant, combien de ces
- tests nécessiteront qu'un utilisateur soit connecté ? La solution la plus simple est
- d'utiliser la logique de votre application pour faire ceci... et d'esquiver un peu par
- l'utilisation des méthodes <methodname>resetResponse()</methodname> et <methodname>resetResponse()</methodname>,
- qui vous permettront de distribuer une nouvelle requête.
- </para>
- <programlisting language="php"><![CDATA[
- class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
- {
- // ...
- public function loginUser($user, $password)
- {
- $this->request->setMethod('POST')
- ->setPost(array(
- 'username' => $user,
- 'password' => $password,
- ));
- $this->dispatch('/user/login');
- $this->assertRedirectTo('/user/view');
- $this->resetRequest()
- ->resetResponse();
- $this->request->setPost(array());
- // ...
- }
- // ...
- }
- ]]></programlisting>
- <para>Écrivons maintenant les tests :</para>
- <programlisting language="php"><![CDATA[
- class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
- {
- // ...
- public function testCallWithoutActionShouldPullFromIndexAction()
- {
- $this->dispatch('/user');
- $this->assertController('user');
- $this->assertAction('index');
- }
- public function testLoginFormShouldContainLoginAndRegistrationForms()
- {
- $this->dispatch('/user');
- $this->assertQueryCount('form', 2);
- }
- public function testInvalidCredentialsShouldResultInRedisplayOfLoginForm()
- {
- $request = $this->getRequest();
- $request->setMethod('POST')
- ->setPost(array(
- 'username' => 'bogus',
- 'password' => 'reallyReallyBogus',
- ));
- $this->dispatch('/user/login');
- $this->assertNotRedirect();
- $this->assertQuery('form');
- }
- public function testValidLoginShouldRedirectToProfilePage()
- {
- $this->loginUser('foobar', 'foobar');
- }
- public function testAuthenticatedUserShouldHaveCustomizedProfilePage()
- {
- $this->loginUser('foobar', 'foobar');
- $this->request->setMethod('GET');
- $this->dispatch('/user/view');
- $this->assertNotRedirect();
- $this->assertQueryContentContains('h2', 'foobar');
- }
- public function testAuthenticatedUsersShouldBeRedirectedToProfilePageWhenVisitingLoginPage()
- {
- $this->loginUser('foobar', 'foobar');
- $this->request->setMethod('GET');
- $this->dispatch('/user');
- $this->assertRedirectTo('/user/view');
- }
- public function testUserShouldRedirectToLoginPageOnLogout()
- {
- $this->loginUser('foobar', 'foobar');
- $this->request->setMethod('GET');
- $this->dispatch('/user/logout');
- $this->assertRedirectTo('/user');
- }
- public function testRegistrationShouldFailWithInvalidData()
- {
- $data = array(
- 'username' => 'This will not work',
- 'email' => 'this is an invalid email',
- 'password' => 'Th1s!s!nv@l1d',
- 'passwordVerification' => 'wrong!',
- );
- $request = $this->getRequest();
- $request->setMethod('POST')
- ->setPost($data);
- $this->dispatch('/user/register');
- $this->assertNotRedirect();
- $this->assertQuery('form .errors');
- }
- }
- ]]></programlisting>
- <para>
- Notez que ces tests sont laconiques, et, pour la plupart, ne recherchent pas le
- contenu réel. Au lieu de cela, ils recherchent des objets construits dans la réponse -
- codes et en-têtes de réponse, et noeuds DOM. Ceci vous permet de vérifier que la
- structure est comme prévue - sans entraîner un échec dans vos tests à chaque fois qu'un
- contenu est ajouté au site.
- </para>
- <para>
- Notez également que nous utilisons la structure du document dans nos essais. Par
- exemple, dans le test final, nous recherchons un formulaire qui a un noeud avec la
- classe "errors" ; ceci nous permet de déterminer simplement la présence des erreurs de
- validation de formulaire, et sans nous inquiéter de quelles erreurs spécifiques
- pourraient avoir été levées.
- </para>
- <para>
- Cette application <emphasis>peut</emphasis> utiliser une base de données. Si oui,
- vous aurez besoin probablement d'un certain échafaudage pour s'assurer que la base de
- données est dans une configuration initiale et testable au début de chaque essai.
- PHPUnit fournit déjà une fonctionnalité pour faire ceci ; <ulink
- url="http://www.phpunit.de/manual/3.4/en/database.html">lisez ceci dans la
- documentation PHPUnit</ulink>. Nous recommandons d'utiliser une base de données séparée
- pour les tests et pour la production, et recommandons en particulier d'employer un
- fichier SQLite ou une base de données en mémoire, d'autant que les deux options
- s'exécutent très bien, sans nécessité d'un serveur séparé, et peuvent utiliser la
- plupart de la syntaxe <acronym>SQL</acronym>
- </para>
- </example>
- </sect2>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|