[PHP][PHPUnit] 指定されたディレクトリ以下のすべてのテストを実行するスクリプト
問題点
このツールでは、テストを追加する場合、テストケースを書くだけではなく、ツールにテストケースがあることを教える必要があります。例えば、PHPUnit ポケットガイドの第7章 テストの構成では、以下のコードが例としてあげられています。
<?php (略) public static function suite() { $suite = new PHPUnit_Framework_TestSuite('PHPUnit Framework'); $suite->addTestSuite('Framework_AssertTest'); // ... return $suite; } (略) ?>
しかし、これは2度手間であり、うっかりテストツールを追加することを忘れることもありえるでしょう。できれば、RubyのTest::Unitのように、ファイルをディレクトリに置くだけでテストの対象になるようにしたいです。
解決方法
以下のスクリプトを使用します。
<?php require_once 'PHPUnit/Framework.php'; require_once 'PHPUnit/TextUI/TestRunner.php'; class AllTests { public static function main($directories) { $suite = self::suite($directories); PHPUnit_TextUI_TestRunner::run($suite); } public static function suite($directories) { $suite = new PHPUnit_Framework_TestSuite(); foreach ($directories as $directory) { $tests = self::collect_tests($directory); $suite->addTestFiles($tests); } return $suite; } private static function collect_tests($directory) { $tests = array(); $dir = dir($directory); while (($entry = $dir->read()) !== false) { if (($entry === '.') || ($entry === '..')) { continue; } $path = sprintf('%s/%s', $directory, $entry); if (is_dir($path)) { $tests_in_path = self::collect_tests($path); $tests = array_merge($tests, $tests_in_path); } else { if (ereg('^.*Test\\.php$', $entry)) { array_push($tests, $path); } } } return $tests; } } $directories; if (1 < $argc) { $directories = array_slice($argv, 1); } else { $directory = dirname($argv[0]); $directories = array($directory); } AllTests::main($directories); # vim: tabstop=2 shiftwidth=2 expandtab ?>
このスクリプトがtests/harness.phpであるとき、このスクリプトをコマンドラインから以下のようにして実行します。すると、スクリプトがあるディレクトリ(この例の場合はtestsディレクトリ)以下にあるすべてのテストを実行します。
$ $ php tests/harness.php [~/projects/PhosphorusRider] PHPUnit 3.0.0 by Sebastian Bergmann. (略) 3) testGetToken2(ScannerTest) Exception: This method is not implemented. /home/tom/projects/PhosphorusRider/tests/SchemaParser/ScannerTest.php:115 /home/tom/projects/PhosphorusRider/tests/harness.php:10 /home/tom/projects/PhosphorusRider/tests/harness.php:57 FAILURES! Tests: 4, Errors: 3.
テストケースのファイルの名前は、"*Test.php"である必要があります。
コマンドラインには、対象とするディレクトリを指定することもできます。その場合は、指定されたディレクトリ以下にあるすべてのテストが実行されます。
解決方法までの経緯
PHPUnitのAPIドキュメントのPHPUnit_Framework_TestSuiteクラスの項目をみると、PHPUnit_Framework_TestSuiteクラスには、ポケットリファレンスでは触れられていないaddTestFilesメソッドがあることが分かります。今回は、これを利用することにしました。
テストは、ディレクトリの処理ではありがちな再帰をして、集めています。
<?php private static function collect_tests($directory) { $tests = array(); $dir = dir($directory); while (($entry = $dir->read()) !== false) { if (($entry === '.') || ($entry === '..')) { continue; } $path = sprintf('%s/%s', $directory, $entry); if (is_dir($path)) { $tests_in_path = self::collect_tests($path); $tests = array_merge($tests, $tests_in_path); } else { if (ereg('^.*Test\\.php$', $entry)) { array_push($tests, $path); } } } return $tests; } ?>