PHPUnit2 - 最強のユニットテスト自動化ツール for PHP5
PHPUnit2 ver.2.3.0 β1からPHP5.1.0β1以降が必要になりますので要注意。
PHP5が正式リリースされてしばらく経ち、実際の開発で使われているという話もぼちぼち聞くようになりましたが、「開発」とくれば「テスト」は避けされませんね。最近の流行(?)としてはxUnitシリーズを利用して単体テストを行う場面が多いと思いますが、PHP5用としてはPHPUnit2がPEARに登録されています。
PHPUnit2は機能的にJUnit3.8.1とJUnitour1.2を組み合わせたモノになっていて、基本的にCLI版となっています。また、PHP4向けのPHPUnitにはない以下の機能があります。
- テストコードの雛形の自動生成
- TestDoxの生成
- コードカバレッジ(網羅率)のレポート生成
今回はこの3つに絞ってまとめてみました。使用するサンプルスクリプトは、PHPUnitの時に使ったサンプルをPHP5に焼き直したものです(手抜きだ。。。(^-^;)。
●カートクラス - Cart.php
<?php
class Cart
{
private $items_;
public function Cart()
{
$this->items_ = array();
}
public function add($item_cd, $amount)
{
$this->_check($item_cd);
if ($amount > 0) {
$this->items_[$item_cd] += $amount;
}
}
public function remove($item_cd, $amount)
{
$this->_check($item_cd);
if ($amount > 0) {
$this->items_[$item_cd] -= $amount;
if ($this->items_[$item_cd] < 0) {
$this->items_[$item_cd] = 0;
}
}
}
public function clear()
{
unset($this->items_);
}
public function getAmount($item_cd)
{
$this->_check($item_cd);
return $this->items_[$item_cd];
}
public function _check($item_cd)
{
if (!isset($this->items_[$item_cd])) {
$this->items_[$item_cd] = 0;
}
}
}
?>
●テストクラス - CartTest.php
<?php
require_once 'PHPUnit2/Framework/TestCase.php';
require_once "Cart.php";
?>
<?php
class CartTest extends PHPUnit2_Framework_TestCase
{
private $cart_;
public function CartTest($name)
{
parent::__construct($name);
}
public function setUp()
{
$this->cart_ = new Cart();
}
public function tearDown() {}
public function testInit()
{
$this->assertEquals(0, $this->cart_->getAmount("aaa"));
}
public function testAddPositive()
{
$this->cart_->add("aaa", 1);
$this->cart_->add("aaa", 2);
$this->assertEquals(3, $this->cart_->getAmount("aaa"));
$this->cart_->add("bbb", 10);
$this->cart_->add("bbb", 20);
$this->assertEquals(3, $this->cart_->getAmount("aaa"));
$this->assertEquals(30, $this->cart_->getAmount("bbb"));
}
public function testAddNegative()
{
$this->cart_->add("aaa", 1);
$this->cart_->add("aaa", 0);
$this->cart_->add("bbb", 0);
$this->cart_->add("bbb", 10);
$this->assertEquals(1, $this->cart_->getAmount("aaa"));
$this->assertEquals(10, $this->cart_->getAmount("bbb"));
$this->cart_->add("aaa", -2);
$this->cart_->add("aaa", -20);
$this->assertEquals(1, $this->cart_->getAmount("aaa"));
$this->assertEquals(10, $this->cart_->getAmount("bbb"));
}
public function testRemovePositive()
{
$this->cart_->add("aaa", 10);
$this->cart_->remove("aaa", 3);
$this->cart_->add("bbb", 10);
$this->cart_->remove("bbb", 7);
$this->assertEquals(7, $this->cart_->getAmount("aaa"));
$this->assertEquals(3, $this->cart_->getAmount("bbb"));
}
public function testRemoveNegative()
{
$this->cart_->add("aaa", 10);
$this->cart_->add("aaa", -20);
$this->cart_->add("bbb", 1);
$this->cart_->add("bbb", -2);
$this->assertEquals(10, $this->cart_->getAmount("aaa"));
$this->assertEquals(1, $this->cart_->getAmount("bbb"));
}
public function testClear()
{
$this->cart_->add("aaa", 10);
$this->cart_->add("bbb", 5);
$this->cart_->clear();
$this->assertEquals(0, $this->cart_->getAmount("aaa"));
$this->assertEquals(0, $this->cart_->getAmount("bbb"));
}
}
?>
インストール手順
インストール手順は通常のPEARパッケージのインストールと同じく、以下のような感じです。完了後、PHPのインストールPREFIX(指定しなかった場合は/usr/local)/binに「phpunit」というコマンドが追加されていることを確認しましょう。今回は、PHPインストール時に「--prefix=/usr/local/lib/php5」を付けた環境で行いました。
●PHPUnit2のインストール# /usr/local/lib/php5/bin/pear install --alldeps phpunit2
downloading PHPUnit2-2.2.0.tgz ...
Starting to download PHPUnit2-2.2.0.tgz (38,446 bytes)
..........done: 38,446 bytes
downloading Log-1.8.7.tgz ...
Starting to download Log-1.8.7.tgz (32,693 bytes)
...done: 32,693 bytes
downloading DB-1.7.6.tgz ...
Starting to download DB-1.7.6.tgz (124,807 bytes)
...done: 124,807 bytes
install ok: DB 1.7.6
install ok: Log 1.8.7
Optional dependencies:
'xdebug' PHP extension is recommended to utilize some features
install ok: PHPUnit2 2.2.0
#
# ls /usr/local/lib/php5/bin
pear* php* php-config* php5* phpextdist* phpize* phpunit*
#
テストコードの雛形の自動生成
まず、テストコードの雛形の自動生成についてです。開発がある程度の規模になってくるとテストコードを書くだけでも大変ですが、テスト対象のクラスを元にテストコードの雛形が作成されるだけでもかなり楽になると思います。
手順としては、テスト対象のクラスと同じディレクトリで以下のコマンドを実行します。この時、テスト対象のクラスのファイル名は、クラス名と合わせておく必要があります。今回の場合だとクラス名が「Cart」なので、ファイル名は「Cart.php」としておく必要があります。
●雛形の作成$ /usr/local/lib/php5/bin/phpunit --skeleton Cart
PHPUnit 2.2.0 by Sebastian Bergmann.
Wrote test class skeleton for Cart to CartTest.php.
$
生成されたテストクラスは以下の通りです。この後、各メソッドにテスト内容を記述することになります。
●自動生成されたCartTest.php
<?php
if (!defined("PHPUnit2_MAIN_METHOD")) {
define("PHPUnit2_MAIN_METHOD", "CartTest::main");
}
require_once "PHPUnit2/Framework/IncompleteTestError.php";
require_once "PHPUnit2/Framework/TestCase.php";
require_once "PHPUnit2/Framework/TestSuite.php";
require_once "PHPUnit2/TextUI/TestRunner.php";
require_once "Cart.php";
class CartTest extends PHPUnit2_Framework_TestCase {
public static function main() {
$suite = new PHPUnit2_Framework_TestSuite("CartTest");
$result = PHPUnit2_TextUI_TestRunner::run($suite);
}
public function testAdd() {
throw new PHPUnit2_Framework_IncompleteTestError;
}
public function testRemove() {
throw new PHPUnit2_Framework_IncompleteTestError;
}
public function testClear() {
throw new PHPUnit2_Framework_IncompleteTestError;
}
public function testGetAmount() {
throw new PHPUnit2_Framework_IncompleteTestError;
}
public function test_check() {
throw new PHPUnit2_Framework_IncompleteTestError;
}
}
if (PHPUnit2_MAIN_METHOD == "CartTest::main") {
CartTest::main();
}
?>
TestDoxの生成
次にTestDoxの生成についてです。恥ずかしながら今回初めて知ったのですが、テストケースのメソッド名からドキュメントを生成するツールでアジャイル系開発手法で使われているようです。参考までに、JUnit用のTestDoxについては以下のサイトで公開されています。
手順としては「--testdox-text」パラメータと出力するファイルを指定してテストクラスを実行させます。
●TestDoxの作成$ /usr/local/lib/php5/bin/phpunit --testdox-text CartTest.testdox.txt CartTest
PHPUnit 2.2.0 by Sebastian Bergmann.
......
Time: 0.0053179264068604
OK (6 tests)
$
●生成されたTestDox - CartTest.testdox.txtCart
- Init
- Add positive
- Add negative
- Remove positive
- Remove negative
- Clear
また、「--testdox-html」パラメータの場合はHTML形式で出力されます。このHTMLには<html>タグや<body>タグが含まれていませんので、複数のテストを実行後、一つのファイルにまとめる、などバッチ的にも使えるかも知れません(Suiteを使えば済む話かも知れませんが。。。)。
コードカバレッジのレポート生成
最後はコードカバレッジのレポート生成についてです。以前紹介したXDebugのコードカバレッジAPIを使っているため、別途Xdebugをインストールする必要があります。今回は、2005/04/24時点の最新版であるXdebug2.0.0 beta2を使用しました。ざっくりないんストール手順は以下の通りです。
●Xdebug2のインストール$ tar zxf xdebug-2.0.0beta2.tgz
$ cd xdebug-2.0.0beta2/
$ phpize
$ ./configure --enable-xdebug
$ make
$ su -
# make install
# vi /path/to/php.ini(extensionとしてxdebug.soを追加する)
#
実行手順ですが、「--coverage-html」パラメータと出力するファイルを指定してテストクラスを実行させます。
●カバレッジレポートの作成$ /usr/local/lib/php5/bin/phpunit --coverage-html CartTest.coverage.html CartTest
PHP Warning: Xdebug MUST be loaded as a Zend extension in Unknown on line 0
PHPUnit 2.2.0 by Sebastian Bergmann.
......
Time: 0.045461893081665
OK (6 tests)
$
生成されたレポートはこちらですが、CSSファイルを別途用意することではじめて色分けが行われます。このCSSファイルはレポート用のCSSが用意されていないため、[PEARディレクトリ]/PHPUnit2/Extensions/CodeCoverage/Renderer/HTML.phpの先頭コメントにあるCSSのサンプルを元にcodecoverage.cssとして作成したものです。なお、TestDocと同様「--coverage-text」パラメータもあります。
まとめ
こう見てみると、PHPにもだいぶこういったツールが揃ってきましたね。今後が楽しみです(^-^)
|