| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15617 -->
- <!-- Reviewed: no -->
- <sect2 id="zend.test.phpunit.examples">
- <title>Beispiele</title>
- <para>
- Zu wissen wir man die eigene Infrastruktur für Tests einstellt und wir Ausnahmen zu
- erstellen sind ist nur der halbe Kampf; jetzt ist es Zeit auf einige Testszenarien zu
- schauen und zu eruieren wie diese verwendet werden können.
- </para>
- <example id="zend.test.phpunit.examples.userController">
- <title>Den UserController testen</title>
- <para>
- Nehmen wir einen standard Task für eine Webseite an: Authentifizierung und Registrierung
- von Benutzern. In unserem Beispiel definieren wir einen UserController um das zu
- behandeln, und haben die folgenden Notwendigkeiten:
- </para>
- <itemizedlist>
- <listitem><para>
- Wenn ein Benutzer nicht authentifiziert ist, wird er immer zur Login Seite des
- Kontrollers umgeleitet, unabhängig von der spezifizierten Aktion.
- </para></listitem>
- <listitem><para>
- Die Login Formularseite wird beides zeigen, das Login Formular und das Registrations
- Formular.
- </para></listitem>
- <listitem><para>
- Die angabe von ungültigen Anmeldedaten sollte in der Rückgabe des Login Formulars
- resultieren.
- </para></listitem>
- <listitem><para>
- Das Ansehen der Anmeldedaten sollte in einer Umleitung zur Profilseite des Benutzers
- resultieren.
- </para></listitem>
- <listitem><para>
- Die Profilseite sollte verändert werden um den Benutzernamen des Benutzers zu
- enthalten.
- </para></listitem>
- <listitem><para>
- Authentifizierte Benutzer welche die Loginseite besuchen sollten zu Ihrer
- Profilseite umgeleitet werden.
- </para></listitem>
- <listitem><para>
- Bei der Abmeldung, sollten ein Benutzer zur Loginseite umgeleitet werden.
- </para></listitem>
- <listitem><para>
- Mit ungültigen Daten sollte die Registrierung fehlschlagen.
- </para></listitem>
- </itemizedlist>
- <para>
- Wir können, und sollten zusätzliche Tests definieren, aber diese reichen für jetzt.
- </para>
- <para>
- Für unsere Anwendung definieren wir ein Plugin, 'Initialisieren' es, damit es bei
- <code>routeStartup()</code> läuft. Das erlaubt es uns das Bootstrapping in einem OOP
- Interface zu kapseln, was auch einen einfachen Weg bietet um ein Callback zu
- ermöglichen. Schauen wir uns erstmals die Basics dieser Klasse an:
- </para>
- <programlisting language="php"><![CDATA[
- class Bugapp_Plugin_Initialize extends Zend_Controller_Plugin_Abstract
- {
- /**
- * @var Zend_Config
- */
- protected static $_config;
- /**
- * @var string Aktuelle Umgebung
- */
- protected $_env;
- /**
- * @var Zend_Controller_Front
- */
- protected $_front;
- /**
- * @var string Pfad zum Root der Anwendung
- */
- protected $_root;
- /**
- * Constructor
- *
- * Umgebung, Root Pfad und Konfiguration initialisieren
- *
- * @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 beginnen
- *
- * @return void
- */
- public function routeStartup(Zend_Controller_Request_Abstract $request)
- {
- $this->initDb();
- $this->initHelpers();
- $this->initView();
- $this->initPlugins();
- $this->initRoutes();
- $this->initControllers();
- }
- // Die Definition von Methoden würde hier folgen...
- }
- ]]></programlisting>
- <para>
- Das erlaubt es uns einen Bootstrap Callback wie folgt zu erstellen:
- </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>
- Sobald das fertig ist, können wir unsere Tests schreiben. Trotzdem, was ist mit den
- Tests die erfordern das der Benutzer angemeldet ist? Die einfache Lösung besteht darin
- das unsere Anwendungslogik das macht... und ein bischen trickst indem die
- <code>resetRequest()</code> und <code>resetResponse()</code> Methoden verwendet werden,
- die es uns erlauben eine andere Anfrage abzusetzen.
- </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>
- Jetzt schreiben wir 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
- testAuthenticatedUsersShouldBeRedirectedToProfileWhenVisitingLogin()
- {
- $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>
- Es ist zu beachten das die Tests knapp sind und, für die meisten von Ihnen, nicht den
- aktuellen Inhalt berücksichtigen. Stattdessen sehen Sie nach Teilen in der Anfrage --
- Anfrage Codes und Header sowie DOM Knoten. Das erlaubt es schnell zu prüfen das die
- Strukturen wie erwartet sind -- und verhinter das die Tests jedesmal wenn der Site neue
- Inhalte hinzugefügt werden darin ersticken.
- </para>
- <para>
- Es ist auch zu beachten das wir die Struktur des Dokuments in unseren Tests verwenden.
- Zum Beispiel schauen wir im letzten Test nach einer Form die einen Node mit der Klasse
- "errors" hat; das erlaubt es uns lediglich nach dem Vorhandensein von
- Form-Prüfungsfehlern zu testen, und uns keine Sorgen darüber zu machen warum spezielle
- Fehler überhaupt geworfen werden.
- </para>
- <para>
- Diese Anwendung <emphasis>könnte</emphasis> eine Datenbank verwenden. Wenn dem so ist,
- muß man warscheinlich einige Grundlagen ändern um sicherzustellen das die Datenbank am
- Anfang jeden Tests, in einer unverfälschten, testbaren Konfiguration ist. PHPUnit bietet
- bereits Funktionalität um das sicherzustellen; <ulink
- url="http://www.phpunit.de/pocket_guide/3.3/en/database.html">Lesen Sie darüber in
- der PHPUnit Dokumentation nach</ulink>. Wir empfehlen eine separate Datenbank für das
- Testen zu verwenden statt der Produktionsdatenbank, und entweder eine SQLite Datei oder
- eine Datenbank im Speicher zu verwenden, da beide Optionen sehr performant sind, keinen
- separaten Server benötigen, und die meisten SQL Syntaxe verwenden können.
- </para>
- </example>
- </sect2>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|