ユニットテスト、ここどうするの?
こんにちは、斉藤です。
前々回はTDDというユニットテストを使った開発方法、前回はユニットテスト実行の自動化と、触れてきました。
今回もやっぱりユニットテストについてということで、方法論などをtips形式でお送りします。
* プライベートメソッドのテスト
ユニットテストでは、公開されているメソッドを呼び出して実行します。
クラスを書いたことがある方なら知っている通り、プライベートメソッドを外部から呼び出すことは出来ません。
そのため一般的にこれは、避けた方が良いと言われていますが・・・自分はテストしたい派なので、以下の方法をご紹介します。
- パブリックメソッドでプライベートメソッドを呼び出す
一番簡単な方法ですね。
ただしこの場合だと、公開APIと非公開APIの区別が出来なくなってしまいます。
クラスに手を入れることになり、テストのためだけのコードが混じってしまうことがデメリットです。
例;
<?php
class Hoge
{
public function __construct()
{
}
private function doSomething($a, $b)
{
return $a + $b;
}
// テストでは使うけど、実際には使わない
public function doSomething2($a, $b)
{
return $this->doSomething($a, $b);
}
}
余談ですが、objective-cでは"クラスに手をつけず、クラスの機能を拡張できる"カテゴリーという機能があります。
この機能を使えば、ユニットテストの時のみ、パブリックメソッドを追加する方法が取れます。
- リフレクションでプライベートメソッドを呼び出す
PHP、JAVAなどは、リフレクションという"プログラム自身を読み取る"機能が使えますので、それを使いましょう。
これをテストコードの中のみに記述しておけば、実際に使うときには使われないので安全です。
以下の例では、上記HogeクラスのdoSomethingメソッドをリフレクションで外部から実行しています。
<?php
class HogeTest extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
$method = new ReflectionMethod(
'Hoge', 'doSomething'
);
$method->setAccessible(true);
$this->assertEquals(3, $method->invokeArgs(new Hoge(), array(1,2)));
}
}
参考:
http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html
http://blog.asial.co.jp/751
* void型メソッドのテスト
値を返さないメソッドをどうやってテストするの?って思いますよね?
割と方法が考えられています。
- プロパティが変化するなら、その値に対してassertをかける
そのメソッド内でプロパティの値が変化するなら、その内容でテストをすることが出来ます。
ただし、このプロパティがパブリックである、もしくはアクセスできるメソッドが公開されている場合に限ります。←コメントで、リフレクションを使えば良いということを教えていただきました。
<?php
class Foo
{
private $a;
public function __construct($a)
{
$this->a = $a;
}
public function doSomething()
{
$this->a += 5;
}
public function getA()
{
return $this->a;
}
}
class FooTest extends PHPUnit_Framework_TestCase
{