PHPUnitをインストールしてみる

PHPで自動テストを行うにはPHPUnitというPEARモジュールを使うらしいので
インストールしてみることにした
私の場合はPEARモジュールをインストールすること自体初めてだったりする

PEARのインストール

まず以下のページからgo-pearをダウンロードしてくる
http://pear.php.net/manual/ja/installation.getting.php
ブラウザで表示してコピー、と書いてあるが私の場合は勝手にダウンロードされたのでそれを使った
必要なかったかもしれないがPHPのインストールディレクトリに保存してからコマンドプロンプト
以下のコマンドをタイプする

php go-pear

終わってからpear versionとタイプして反応があったのでたぶん成功

PHPUnitのインストール

以下のページの通り
http://www.phpunit.de/manual/3.6/ja/installation.html

pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit

終わってからphpunit --versionとタイプしてみるが無反応だったので調べてみたらphpunit.batが足りない様子
ググって最初にあったページをそのままに、以下のコマンドをタイプしたら解決した

pear install --alldeps --force phpunit/phpunit

今度はちゃんとphpunit --versionで反応がある

PHPUnitの書き方

参考にしたサイトはこちら
http://www.phpunit.de/manual/3.6/ja/index.html


テスト対象のスクリプト
Foo.php

<?php
class Foo
{
	protected $val;
	public function __construct($val = 0)
	{
		$this->val = $val;
	}
	public function add($num)
	{
		if(! is_int($num))
		{
			throw new InvalidArgumentException("'add' only accepts integers.");
		}
		$this->val += $num;
	}
	public function get()
	{
		return $this->val;
	}
	public function puts()
	{
		echo $this->val, PHP_EOL;
	}
}


単体テスト用のスクリプト
FooTest.php

<?php
set_include_path(__DIR__ . './lib' . PATH_SEPARATOR . get_include_path());
require_once("Foo.php");

class FooTest extends PHPUnit_Framework_TestCase
{
	protected $foo;
	public function setUp()
	{
		$this->foo = new Foo();
	}
	
	/**
	 * @test
	*/
	public function test1()
	{
		$this->foo->add(1);
		$this->assertTrue(1 === $this->foo->get());
	}
	
	public function test2()
	{
		$this->foo->add(1);
		$this->foo->add(2);
		$this->assertSame(3, $this->foo->get());
	}
	
	/**
	 * @expectedException InvalidArgumentException
	 * @expectedExceptionMessage 'add' only accepts integers.
	*/
	public function test3()
	{
		$this->foo->add("x");
	}
	
	public function test4()
	{
		$this->foo->add(1);
		$this->expectOutputString("1" . PHP_EOL);
		$this->foo->puts();
	}
}


コマンド

phpunit FooTest


出力

PHPUnit 3.6.10 by Sebastian Bergmann.

....

Time: 0 seconds, Memory: 2.75Mb

OK (4 tests, 5 assertions)


2行目のset_include_pathはライブラリ検索用のパスを追加している
Perlでいうuse libみたいな感じ
テスト用のクラスはPHPUnit_Framework_TestCaseを継承して作る
setUpというメソッドは各テストの前にコールされる
他にも以下のようなものがある

tearDown           // 各テストの後にコールされる
setUpBeforeClass   // テスト開始時にコールされる
tearDownAfterClass // テスト終了時にコールされる

スクリプトの中にある@から始まるコメントは単なるコメントではなく
アノテーションというやつで、その直後に書いたメソッドの振る舞いを決めるもの
@testはテストメソッドを指定するものだけど、メソッド名がtestから始まる場合は
この指定なしにテストメソッドになる
@expectedExceptionは投げられるはずの例外のクラスを指定して
例外のテストを行うことができる
@expectedExceptionMessageは例外のメッセージに含まれる文字列を指定する


assertから始まるメソッドはアサーションというやつで
こいつらで値をチェックしていく
assertTrueメソッドは引数がtrueであれば成功する
PerlでいうTest::SimpleとかTest::Moreのok関数みたいな感じ
ただし勝手にキャストされることはないのでassertTrue(1)などは失敗する
本当にtrueを期待する場面に使ったほうがよさそう
逆にfalseを期待するassertFalseもある


assertSameは2つの引数を === で比較し真ならば成功する

<?php
$this->assertSame(1, 1); // Successful
$this->assertSame(1, "1"); // Failures

$foo = new Foo;
$alias = &$foo;
$this->assertSame($foo, $alias); // Successful
$this->assertSame($foo, new Foo); // Failures

逆に !== で比較するassertNotSameもある


expectOutputStringは出力のテストを行う
正規表現を使うexpectOutputRegexもある

次回の課題

とりあえずきちっとテストにこけるか試せばよかったな、と
もうすこし複雑な使い方についても試してみようか