CodeIgniter のユニットテストクラスのテストを PHPUnit から実行する
PHPUnit から CodeIgniter のユニットテストを実行する方法です。CIUnit は使っていません。
PHPUnit のインストール
$ sudo pear channel-discover pear.phpunit.de $ sudo pear channel-discover components.ez.no $ sudo pear channel-discover pear.symfony-project.com $ sudo pear install phpunit/PHPUnit
CodeIgniter のユニットテストを実行するテストケースの作成
まず、autoloader を作成します。
tests/autoload.php https://gist.github.com/1231528
<?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 の設定ファイルを作成します。
tests/phpunit.xml https://gist.github.com/1231533
<?xml version="1.0" encoding="UTF-8"?> <phpunit colors="true" stopOnFailure="false"> <php> <server name="SERVER_NAME" value="http://example.com" /> </php> <testsuites> <testsuite name="CI Unit Testing Class Tests"> <file>./CI_Unit_Test.php</file> </testsuite> </testsuites> </phpunit>
CodeIgniter のユニットテストを実際に実行するテストを作成します。
コンストラクタの $this->test_folder に CodeIgniter のユニットテストが保存されているフォルダを、$this->test_uri にユニットテストの URI (コントローラ名より前の部分)を設定します。
get_ci_unit_test() メソッドでテストの URI にアクセスし結果を取得しています。まず、ユニットテストが保存されているフォルダ内の *.php ファイルを解析し、「test」で始まるメソッド名の URI にアクセスします。テストメソッドの命名規則が異なる場合は、この部分のロジックを変更してください。
ユニットテストの URI にアクセスし、ページを取得し、「Failed」と「Passed」を探して保存しています。ユニットテストのテンプレートは英語であることを前提としています。
test() メソッドが PHPUnit のテストメソッドになります。失敗するアサーションがあった場合はメソッドが終了しますので、成功するメソッドを先に実行するようにしています。
tests/CI_Unit_Test.php https://gist.github.com/1231531
<?php require 'autoload.php'; class CI_Unit_Test extends PHPUnit_Framework_TestCase { private $test_folder; private $test_uri; private $count = 0; private $tests = array(); public function __construct() { $this->test_folder = APPPATH . 'controllers/tests'; $this->test_uri = 'http://localhost/ci/index.php/tests/'; if (is_dir($this->test_folder) === FALSE) { exit("$this->test_folder is not a folder!\n"); } if (parse_url($this->test_uri) === FALSE) { exit("$this->test_uri is not a valid URI!\n"); } $this->get_ci_unit_test(); } private function get_ci_unit_test() { $passed = 0; $failed = 0; foreach (glob("$this->test_folder/*.php") as $filename) { require $filename; $filename = basename($filename, '.php'); $class = ucfirst($filename); $methods = get_class_methods($class); $tests = array(); // access to all methods which begin with test foreach ($methods as $method) { if (substr($method, 0, 4) === 'test') { //echo "\n$class::$method()\n"; $test_uri = $this->test_uri . $filename . '/' . $method; $test_name = ' ' . $test_uri; $page = file_get_contents($test_uri); if ($page === FALSE) { exit("Can't get $test_uri\n"); } $lines = explode("\n", $page); foreach ($lines as $line) { if (preg_match('!<span style="color: #C00;">Failed</span>!u', $line)) { $tests[$test_name][] = 'Failed'; $failed = 1; // If there is a failed test, the test method ends } else if (preg_match('!<span style="color: #0C0;">Passed</span>!u', $line)) { $tests[$test_name][] = 'Passed'; $passed++; } } if ( ! array_key_exists($test_name, $tests)) { exit("No test results: $test_uri\n"); } } } } $this->count = $passed + $failed; $this->tests = $tests; } public function count() { return $this->count; } public function test() { // Passed tests foreach ($this->tests as $test_name => $tests) { foreach ($tests as $test) { $expected = 'Passed'; $actual = $test; if ($actual === $expected) { $this->setName($test_name); $this->assertSame($expected, $actual); } } } // Failed tests foreach ($this->tests as $test_name => $tests) { foreach ($tests as $test) { $expected = 'Passed'; $actual = $test; if ($actual !== $expected) { $this->setName($test_name); $this->assertSame($expected, $actual); } } } } }
テストの実行
$ cd tests $ phpunit