テストの書き方

zfコマンドを使ってアプリケーションのスケルトンを生成すると、testsディレクトリが生成され、


tests
|-- application
| `-- bootstrap.php
|-- library
| `-- bootstrap.php
`-- phpunit.xml

みたいな配置になっているんだけど、そこにどんな感じで記述すればいいのかよくわからない。phpunit.xmlが1個しかないのに、applicationとlibraryにそれぞれbootstrap.phpがあるって、どういう感じで使うイメージなんだろう?

公式ドキュメントのテスト周りの部分とか、具体的な手順を説明している「Set up a Zend Framework application using Zend_Application (including PHPUnit setup) - mafflog」とかを参考に、コントローラのテストを追加してみた。applicationとlibraryの分かれている部分をどうやって活かすイメージなのかよくわからなかったんで、試行錯誤しつつ。ひとまずはこんな感じになった。

基本的には、「Set up a Zend Framework application using Zend_Application (including PHPUnit setup) - mafflog」で紹介されているやり方をほぼそのまま使いつつ、PHPUnitのブートストラップファイルは、tests/bootstrap.phpとして記述。その中から、tests/application/bootstrap.phpとtests/library/bootstrap.phpをそれぞれ読み込んでいる。つまり、共通のブートストラップはtests/bootstrap.phpに、application、libraryに特化したブートストラップは各ディレクトリ以下に書くイメージ。

主だった部分をコピペしておくと、

tests/phpunit.xml

<phpunit bootstrap="bootstrap.php" colors="true">
  <testsuite name="NetJockey Application">
    <directory>.</directory>
  </testsuite>
</phpunit>

tests/bootstrap.php

<?php 
define('BASE_PATH', realpath(dirname(__FILE__) . '/../'));
define('APPLICATION_PATH', BASE_PATH . '/application');

// Include path
set_include_path(
    '.'
    . PATH_SEPARATOR . BASE_PATH . '/library'
    . PATH_SEPARATOR . get_include_path()
);

// Define application environment
define('APPLICATION_ENV', 'testing');

require_once 'application/bootstrap.php';
require_once 'library/bootstrap.php';

tests/application/bootstrap.php

<?php 
require_once dirname(__FILE__) . '/controllers/ControllerTestCase.php';

tests/application/controllers/ControllerTestCase.php

<?php
require_once 'Zend/Application.php';
require_once 'Zend/Test/PHPUnit/ControllerTestCase.php';

abstract class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase
{
    public $application;

    public function setUp()
    {
        $this->application = new Zend_Application(
            APPLICATION_ENV,
            APPLICATION_PATH . '/configs/application.ini'
        );

        $this->bootstrap = array($this, 'appBootstrap');
        parent::setUp();
    }

    public function appBootstrap()
    {
        $this->application->bootstrap();
    }
}

tests/application/controllers/IndexControllerTest.php

<?php
class IndexControllerTest extends ControllerTestCase
{
    public function testIndexAction()
    {
        $this->dispatch('/');
        $this->assertRoute('top');
        $this->assertController('index');
        $this->assertAction('index');
        
        $this->assertResponseCode('200');
        $this->assertQueryContentContains('title', 'NetJockey');
    }

    public function testErrorURL()
    {
        $this->dispatch('/not/exists/path/');
        $this->assertRoute('default');
        $this->assertController('error');
        $this->assertAction('error');
        
        $this->assertResponseCode('404');
    }
}

コントローラ用のテストケースのベースクラスを作ったりする部分は、「Set up a Zend Framework application using Zend_Application (including PHPUnit setup) - mafflog」の内容をそのまま借用。Zend Frameworkには専用のテストクラスとかも追加されていたんで。MVC周りのテストがナチュラルに書けて結構便利そう。コントローラ(MVC)周り以外のテストに関しては、ふつうにPHPUnitらしいテストを書いていけばいいんだろう。