PHPUnit でモデルのテストクラスの雛形を生成してみる

PHPUnit には、既存のクラスからテストクラスの雛形を生成する機能がありますが、CodeIgniter の場合は、命名規則が合わないため、そのままではうまく動作しません。

phpunit に --skeleton-test オプションを付けて、第1引数にモデルクラス名、第2引数にモデルのファイルを指定すれば OK のはずですが、実行すると、以下のようにクラスが見つからないという Fatal error で動作しません。

$ cd tests
$ phpunit --skeleton-test Blog_model ../application/models/blog_model.php
PHPUnit 3.5.14 by Sebastian Bergmann.

PHP Fatal error:  Class 'CI_Model' not found in /home/kenji/workspace/blog/application/models/blog_model.php on line 9

Fatal error: Class 'CI_Model' not found in /home/kenji/workspace/blog/application/models/blog_model.php on line 9

そこで、autoloader を適当に書いて、モデルクラスを見つけられるようにします。ひとまず、モデルのみを見つけられればよいので、以下のようにしました。

autoload.php:

<?php

define('BASEPATH', dirname(__FILE__) . '/../system/');
define('APPPATH', dirname(__FILE__) . '/../application/');

function autoload_core($class_name)
{
	$file_name = $class_name;
	if (substr($class_name, 0, 3) === 'CI_')
	{
		$file_name = substr($file_name, 3);
	}
	$file = BASEPATH . 'core/' . $file_name . '.php';
	if (file_exists($file))
	{
		require_once $file;
	}
}

function autoload_model($class_name)
{	
	$file_name = strtolower($class_name);
	$file = APPPATH . 'models/' . $file_name . '.php';
	if (file_exists($file))
	{
		require_once $file;
	}
}

spl_autoload_register('autoload_core');
spl_autoload_register('autoload_model');

これで、phpunit の --bootstrap オプションでこの autoloader を指定して実行します。

$ phpunit --bootstrap autoload.php --skeleton-test Blog_model ../application/models/blog_model.php
PHPUnit 3.5.14 by Sebastian Bergmann.

Wrote skeleton for "Blog_modelTest" to "/home/kenji/workspace/blog/application/models/Blog_modelTest.php".

うまく雛形が作成できたようです。以下のようなファイルが生成されました。

Blog_modelTest.php:

<?php

require_once '/home/kenji/workspace/blog/application/models/blog_model.php';

/**
 * Test class for Blog_model.
 * Generated by PHPUnit on 2011-07-25 at 11:31:22.
 */
class Blog_modelTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Blog_model
     */
    protected $object;

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        $this->object = new Blog_model;
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
    }

    /**
     * @todo Implement testGet_all_posts().
     */
    public function testGet_all_posts()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }

    /**
     * @todo Implement testAdd_new_entry().
     */
    public function testAdd_new_entry()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }

    /**
     * @todo Implement testAdd_new_comment().
     */
    public function testAdd_new_comment()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }

    /**
     * @todo Implement testGet_post().
     */
    public function testGet_post()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }

    /**
     * @todo Implement testGet_post_comment().
     */
    public function testGet_post_comment()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }

    /**
     * @todo Implement testTotal_comments().
     */
    public function testTotal_comments()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }
}
?>

ただし、このままでは CIUnit ではうまく動きませんので、CIUnit で動作するように変更する必要があります。