| Prev | Next |
ユニットテストでコードをテストする方法はわかりました。でも、 テストそのものをテストするにはどうしたらいいのでしょう? テストされていないコードを見つけるには? 言い換えれば、まだテストで カバーされていない部分を見つけるには? 完全にテストができたことをどうやって確認するの? これらのすべての疑問に対する答えとなるのが、コードカバレッジ解析という手法です。 コードカバレッジ解析を行うと、 コードのどの部分がテストされたのかを調べることができるようになります。
PHPUnit のコードカバレッジ解析では、Xdebug 拡張モジュールが提供するステートメントカバレッジ機能を利用しています。 ステートメントカバレッジというのは、たとえば 100 行のコードで構成されるメソッドがあった場合に、 もしテストで実際に実行されたのがそのうちの 75 行だけだったなら、 そのメソッドのコードカバレッジは 75 パーセントだと考えるということです。
それでは、例 13.3 の BankAccount クラスについての コードカバレッジレポートを作成してみましょう。
phpunit --coverage-html ./report BankAccountTest
PHPUnit 3.2.10 by Sebastian Bergmann.
...
Time: 0 seconds
OK (3 tests)
Generating report, this may take a moment.
図 14.1 は、コードカバレッジレポートの一部を抜粋したものです。 テスト時に実行された行は、緑色で強調表示されます。 実行可能なコードであるにもかかわらず実行されなかった行については赤色で強調表示されます。 また、"無意味なコード" についてはオレンジ色で強調表示されます。 行の左にある数字は、その行をカバーするテストの数を表します。
BankAccount のコードカバレッジレポートからわかることは、 setBalance()、depositMoney() をコールするテストがまだ存在しないということ、 そして withdrawMoney() に正しい値を指定した場合のテストも存在しないということです。 BankAccountTest クラスに追加するテストを 例 14.1 に示します。これによって、BankAccount クラスのテストケースを完全に網羅できるようになります。
例 14.1: 完全なコードカバレッジを達成するために欠けているテスト
<?php
require_once 'PHPUnit/Framework.php';
require_once 'BankAccount.php';
class BankAccountTest extends PHPUnit_Framework_TestCase
{
// ...
public function testDepositWithdrawMoney()
{
$this->assertEquals(0, $this->ba->getBalance());
$this->ba->depositMoney(1);
$this->assertEquals(1, $this->ba->getBalance());
$this->ba->withdrawMoney(1);
$this->assertEquals(0, $this->ba->getBalance());
}
}
?>
図 14.2 は、 テストを追加した後の setBalance() のコードカバレッジです。
テストコードで @covers アノテーションを使用すると、 そのテストメソッドがどのメソッドをテストしたいのかを指定することができます。 これを指定すると、指定したメソッドのコードカバレッジ情報のみを考慮します。 例 14.2 に例を示します。
例 14.2: どのメソッドを対象とするかを指定したテスト
<?php
require_once 'PHPUnit/Framework.php';
require_once 'BankAccount.php';
class BankAccountTest extends PHPUnit_Framework_TestCase
{
protected $ba;
protected function setUp()
{
$this->ba = new BankAccount;
}
/**
* @covers BankAccount::getBalance
*/
public function testBalanceIsInitiallyZero()
{
$this->assertEquals(0, $this->ba->getBalance());
}
/**
* @covers BankAccount::withdrawMoney
*/
public function testBalanceCannotBecomeNegative()
{
try {
$this->ba->withdrawMoney(1);
}
catch (BankAccountException $e) {
$this->assertEquals(0, $this->ba->getBalance());
return;
}
$this->fail();
}
/**
* @covers BankAccount::depositMoney
*/
public function testBalanceCannotBecomeNegative2()
{
try {
$this->ba->depositMoney(-1);
}
catch (BankAccountException $e) {
$this->assertEquals(0, $this->ba->getBalance());
return;
}
$this->fail();
}
/**
* @covers BankAccount::getBalance
* @covers BankAccount::depositMoney
* @covers BankAccount::withdrawMoney
*/
public function testDepositWithdrawMoney()
{
$this->assertEquals(0, $this->ba->getBalance());
$this->ba->depositMoney(1);
$this->assertEquals(1, $this->ba->getBalance());
$this->ba->withdrawMoney(1);
$this->assertEquals(0, $this->ba->getBalance());
}
}
?>
どうしてもテストができないコードブロックなどを、 コードカバレッジ解析時に無視させたいこともあるでしょう。 PHPUnit でこれを実現するには、 @codeCoverageIgnoreStart および @codeCoverageIgnoreEnd アノテーションを 例 14.3 のように使用します。
例 14.3: @codeCoverageIgnoreStart および @codeCoverageIgnoreEnd アノテーションの使用法
<?php
class Sample
{
// ...
public function doSomething()
{
if (0) {
// @codeCoverageIgnoreStart
$this->doSomethingElse();
// @codeCoverageIgnoreEnd
}
}
// ...
}
?>
@codeCoverageIgnoreStart アノテーションから @codeCoverageIgnoreEnd アノテーションまでの間の行は、 (たとえ実行されなかったとしても) 実行されたものとみなされ、 強調表示されません。
デフォルトでは、1 行でもコードが実行されたソースコードファイルはすべて (そしてそのようなファイルのみが) レポートに含められます。 レポートにどのようなソースコードファイルを含めるかを設定するには PHPUnit_Util_Filter API を使用します (表 14.1 を参照ください)。
表14.1 PHPUnit_Util_Filter の API
| メソッド | 意味 |
|---|---|
void addDirectoryToFilter(string $directory)
|
あるディレクトリ内でファイル名の最後が .php であるすべてのファイルを (再帰的に) ブラックリストに追加します。
|
void addDirectoryToFilter(string $directory, string $suffix)
|
あるディレクトリ内でファイル名の最後が $suffix であるすべてのファイルを (再帰的に) ブラックリストに追加します。
|
void addFileToFilter(string $filename)
|
ファイルをブラックリストに追加します。 |
void removeDirectoryFromFilter(string $directory)
|
あるディレクトリ内でファイル名の最後が .php であるすべてのファイルを (再帰的に) ブラックリストから削除します。
|
void removeDirectoryFromFilter(string $directory, string $suffix)
|
あるディレクトリ内でファイル名の最後が $suffix であるすべてのファイルを (再帰的に) ブラックリストから削除します。
|
void removeFileFromFilter(string $filename)
|
ファイルをブラックリストから削除します。 |
void addDirectoryToWhitelist(string $directory)
|
あるディレクトリ内でファイル名の最後が .php であるすべてのファイルを (再帰的に) ホワイトリストに追加します。
|
void addDirectoryToWhitelist(string $directory, string $suffix)
|
あるディレクトリ内でファイル名の最後が $suffix であるすべてのファイルを (再帰的に) ホワイトリストに追加します。
|
void addFileToWhitelist(string $filename)
|
ファイルをホワイトリストに追加します。 |
void removeDirectoryFromWhitelist(string $directory)
|
あるディレクトリ内でファイル名の最後が .php であるすべてのファイルを (再帰的に) ホワイトリストから削除します。
|
void removeDirectoryFromWhitelist(string $directory, string $suffix)
|
あるディレクトリ内でファイル名の最後が $suffix であるすべてのファイルを (再帰的に) ホワイトリストから削除します。
|
void removeFileFromWhitelist(string $filename)
|
ファイルをホワイトリストから削除します。 |
ブラックリストには、PHPUnit 自身のソースコードファイルやテストファイルがデフォルトで登録されています。 ホワイトリストが空 (デフォルト) の場合はブラックリストを使用し、 ホワイトリストが空でない場合はホワイトリストを使用します。 ホワイトリストを使用する場合は、そのファイルが実行されるかどうかにかかわらず リスト内のすべてのファイルがコードカバレッジレポートに追加されます。
| Prev | Next |
Copyright © 2005-2011 Sebastian Bergmann.