1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 22236 -->
4 <sect2 id="zend.test.phpunit.examples">
8 テスト環境の設定方法とアサーションの作成方法を説明しましたが、
10 実際のテストシナリオをもとにテストの方法を確認していきましょう。
13 <example id="zend.test.phpunit.examples.userController">
14 <title>UserController のテスト</title>
18 ユーザ認証とユーザ登録について考えてみましょう。
19 今回の例では UserController でこれらを処理することにします。
27 常にコントローラのログインページにリダイレクトされる。
32 ログインフォームと新規登録フォームの両方が表示される。
42 ユーザのプロファイルページにリダイレクトされる。
46 プロファイルページには、そのユーザのユーザ名が表示される。
50 認証済みのユーザがログインフォームを訪れると、
51 そのユーザのプロファイルページにリダイレクトされる。
55 ログアウトしたら、ログインページにリダイレクトされる。
59 無効なデータが渡された場合は、登録に失敗する。
64 もちろんこれら以外にも別のテストも必要でしょうが、
65 今のところはひとまずこれだけにしておきます。
69 今回のアプリケーションでは、プラグイン 'Initialize'
70 を定義してそれを <methodname>routeStartup()</methodname> で実行します。
71 これによって起動処理をオブジェクト指向でカプセル化することができ、
73 それではまず、このクラスの基本部分を見ていきましょう。
76 <programlisting language="php"><![CDATA[
77 class Bugapp_Plugin_Initialize extends Zend_Controller_Plugin_Abstract
82 protected static $_config;
90 * @var Zend_Controller_Front
95 * @var string アプリケーションのルートパス
105 * @param string|null $root
108 public function __construct($env, $root = null)
110 $this->_setEnv($env);
111 if (null === $root) {
112 $root = realpath(dirname(__FILE__) . '/../../../');
114 $this->_root = $root;
116 $this->initPhpConfig();
118 $this->_front = Zend_Controller_Front::getInstance();
126 public function routeStartup(Zend_Controller_Request_Abstract $request)
129 $this->initHelpers();
131 $this->initPlugins();
133 $this->initControllers();
136 // この後にメソッド定義が続きます...
141 これで、起動用コールバックを次のように作れるようになります。
144 <programlisting language="php"><![CDATA[
145 class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
147 public function appBootstrap()
149 $controller = $this->getFrontController();
150 $controller->registerPlugin(
151 new Bugapp_Plugin_Initialize('development')
155 public function setUp()
157 $this->bootstrap = array($this, 'appBootstrap');
166 ここまでできたら、テストを書くことができます。
167 しかし、ユーザがログインした状態でのテストはどのように書けばいいでしょう?
168 簡単な方法は、アプリケーションのロジックを利用する方法です。
169 <methodname>resetRequest()</methodname> メソッドや
170 <methodname>resetResponse()</methodname> メソッドを使ってちょっとした細工を行い、
174 <programlisting language="php"><![CDATA[
175 class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
179 public function loginUser($user, $password)
181 $this->request->setMethod('POST')
184 'password' => $password,
186 $this->dispatch('/user/login');
187 $this->assertRedirectTo('/user/view');
189 $this->resetRequest()
192 $this->request->setPost(array());
205 <programlisting language="php"><![CDATA[
206 class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
210 public function testCallWithoutActionShouldPullFromIndexAction()
212 $this->dispatch('/user');
213 $this->assertController('user');
214 $this->assertAction('index');
217 public function testLoginFormShouldContainLoginAndRegistrationForms()
219 $this->dispatch('/user');
220 $this->assertQueryCount('form', 2);
223 public function testInvalidCredentialsShouldResultInRedisplayOfLoginForm()
225 $request = $this->getRequest();
226 $request->setMethod('POST')
228 'username' => 'bogus',
229 'password' => 'reallyReallyBogus',
231 $this->dispatch('/user/login');
232 $this->assertNotRedirect();
233 $this->assertQuery('form');
236 public function testValidLoginShouldRedirectToProfilePage()
238 $this->loginUser('foobar', 'foobar');
241 public function testAuthenticatedUserShouldHaveCustomizedProfilePage()
243 $this->loginUser('foobar', 'foobar');
244 $this->request->setMethod('GET');
245 $this->dispatch('/user/view');
246 $this->assertNotRedirect();
247 $this->assertQueryContentContains('h2', 'foobar');
251 testAuthenticatedUsersShouldBeRedirectedToProfileWhenVisitingLogin()
253 $this->loginUser('foobar', 'foobar');
254 $this->request->setMethod('GET');
255 $this->dispatch('/user');
256 $this->assertRedirectTo('/user/view');
259 public function testUserShouldRedirectToLoginPageOnLogout()
261 $this->loginUser('foobar', 'foobar');
262 $this->request->setMethod('GET');
263 $this->dispatch('/user/logout');
264 $this->assertRedirectTo('/user');
267 public function testRegistrationShouldFailWithInvalidData()
270 'username' => 'This will not work',
271 'email' => 'this is an invalid email',
272 'password' => 'Th1s!s!nv@l1d',
273 'passwordVerification' => 'wrong!',
275 $request = $this->getRequest();
276 $request->setMethod('POST')
278 $this->dispatch('/user/register');
279 $this->assertNotRedirect();
280 $this->assertQuery('form .errors');
286 これらは簡潔なものであり、大半は実際の中身までは見ていないことに注意しましょう。
287 その代わりに、レスポンスコードやヘッダ、そして DOM ノードを見ています。
288 これにより、期待通りの構造になっているかどうかを検証できるようになり、
289 新たなコンテンツが追加されるたびにテストを実行しなおすことが避けられます。
293 ドキュメントの構造を使用してテストを行なっていることに注目しましょう。
294 たとえば最後のテストでは、"errors"
295 というクラスが指定されているノードをフォームから探しました。
296 これにより、単にフォームの検証エラーが発生したかどうかだけを確認することができ、
297 どんなエラーが発生したのかという中身までは気にしなくてすむのです。
301 このアプリケーションでは、データベースを使うことがあるかもしれません。
302 そんな場合は、何らかの scaffold を使用してデータベースの初期状態を作成し、
303 テスト用の設定を行うという作業が各テストの最初に発生します。
304 PHPUnit にはそのための機能が既に用意されています。
306 url="http://www.phpunit.de/manual/3.4/en/database.html">
307 PHPUnit のドキュメントを参照ください</ulink>。
308 テスト時と実運用時には別のデータベースを使用することを推奨します。
309 また、特に (ファイルあるいはインメモリ形式の) SQLite
310 を使うことを推奨します。どちらも別のサーバを必要とせず、
311 大半の <acronym>SQL</acronym> 構文を使用できます。