Prev Next

第1章 自動テスト

どんなにすぐれたプログラマも、間違いを犯します。 よいプログラマとそうでないプログラマの違いは、 よいプログラマはテストを行って間違いをできるだけ早く発見してしまうことです。 テストをするのが早ければ早いほど間違いを発見しやすくなり、 またそれを修正しやすくなります。 リリース直前までテストを先延ばしにしておくことが非常に問題であるのはこのためです。 そんなことをすると、すべてのエラーを発見しきることができず、 発見したエラーを修正することも非常に難しくなります。結局は、 トリアージを行ってどのエラーに対応するかを判断しなければならなくなります。 なぜならすべてのエラーを完全に修正することは不可能だからです。

PHPUnit を使用したテストは、全体としてはあなたがこれまでに行ってきたことと同じです。 ただ、そのやり方が違うだけです。それは、テスト つまりあなたのプログラムが期待通りにふるまうことを調べることと 総合テスト つまり実行可能なコード片がソフトウェアの各部分 (部品) を自動的にテストすることとの違いになります。実行可能なコード片のことを、 単体テスト (unit test) と呼びます。

この章では、単純な print ベースのテストコードをもとにして完全な自動テストに書き換えていきます。 PHP 組み込みの array をテストするように頼まれたとしましょう。このオブジェクトの機能のひとつに、 関数 sizeof() があります。新しく作成された配列では、 sizeof() 関数は 0 を返すはずです。 そして要素を 1 つ追加すると sizeof()1 を返すようになるはずです。テストしたい内容を 例 1.1 に示します。

例 1.1: Array および sizeof() のテスト

<?php
$fixture = array();
// $fixture は空のはずです。

$fixture[] = 'element';
// $fixture はひとつの要素を含むはずです。
?>

期待通りの結果が得られているかどうかを調べるためのいちばん単純な方法は、 要素を追加する前と後に sizeof() の結果を表示することです (例 1.2 を参照ください)。 それぞれ 0 および 1 が得られたら、 array および sizeof() が期待通りに動作していることになります。

例 1.2: print を使用した Array および sizeof() のテスト

<?php
$fixture = array();
print sizeof($fixture) . "\n";

$fixture[] = 'element';
print sizeof($fixture) . "\n";
?>
0
1

このテストは、成功したかどうかの判断を (出力結果を見て) 手動で行わなければなりません。今度は、この判断を自動でできるようにしてみましょう。 例 1.3 では、 期待される結果と実際の結果をコード中で比較して、もしそれらの値が等しければ ok と表示します。もし not ok と表示された場合は、どこかがおかしいということがわかります。

例 1.3: 期待値と実際の値を比較することによる Array および sizeof() のテスト

<?php
$fixture = array();
print sizeof($fixture) == 0 ? "ok\n" : "not ok\n";

$fixture[] = 'element';
print sizeof($fixture) == 1 ? "ok\n" : "not ok\n";
?>
ok
ok

今度は、相違があった際に例外を発生させる関数を用意して、 期待値と実際の値を比較する処理を抽出してみましょう (例 1.4)。 これには 2 つの利点があります。テストが記述しやすくなること、 そして何か問題があったときにのみそれを出力させることができるということです。

例 1.4: アサーション関数を使用した Array および sizeof() のテスト

<?php
$fixture = array();
assertTrue(sizeof($fixture) == 0);

$fixture[] = 'element';
assertTrue(sizeof($fixture) == 1);

function assertTrue($condition)
{
if (!$condition) {
throw new Exception('Assertion failed.');
}
}
?>

これで、テストは完全に自動化されました。最初のバージョンでは単に テストする だけでしたが、このバージョンでは 自動テスト になっています。

自動テストを行う目的は、間違いを少なくすることです。 いくらすばらしいテストを行ったところで あなたのコードが完璧なものになるわけではありませんが、 自動テストを始めることで不具合の量を劇的に減らすことになるでしょう。 自動テストによってあなたのコードは信頼性の高いものとなり、大胆な設計変更 (リファクタリング) を行ったりチームメイトとの関係をよりよくしたり (複数チームでのテスト)、 その日の朝に比べて帰宅前のコードがよりよくなっていることを確信できたりといった効果があります。

Prev Next
1. 自動テスト
2. PHPUnit の目標
3. PHPUnit のインストール
4. PHPUnit 用のテストの書き方
データプロバイダ
例外のテスト
PHP のエラーのテスト
5. コマンドラインのテストランナー
6. Fixtures
tearDown() よりも setUp()
バリエーション
Fixture の共有
7. テストの構成
スイートレベルのセットアップ
8. テストケースの拡張
出力内容のテスト
パフォーマンス低下のテスト
9. データベースのテスト
データセット
Flat XML データセット
XML データセット
操作
データベースのテストのコツ
10. 不完全なテスト・テストの省略
不完全なテスト
テストの省略
11. モックオブジェクト
自己シャント
スタブ
12. テストの進め方
開発中のテスト
デバッグ中のテスト
13. テストファーストプログラミング
銀行口座の例
14. コードカバレッジ解析
カバーするメソッドの指定
コードブロックの無視
ファイルのインクルードや除外
15. テストのその他の使用法
アジャイルな文書作成
複数チームでのテスト
16. ログ出力
XML 形式
コードカバレッジ (XML)
JavaScript Object Notation (JSON)
Test Anything Protocol (TAP)
GraphViz マークアップ
テストデータベース
17. 雛形ジェネレータ
アノテーション
18. PHPUnit と Selenium
Selenium RC
PHPUnit_Extensions_SeleniumTestCase
19. 継続的インテグレーション
CruiseControl
phpUnderControl
Apache Maven
20. PHPUnit の実装
21. PHPUnit API
概要
PHPUnit_Framework_Assert
PHPUnit_Framework_Test
PHPUnit_Framework_TestCase
PHPUnit_Framework_TestSuite
PHPUnit_Framework_TestResult
パッケージの構成
22. PHPUnit の拡張
PHPUnit_Framework_TestCase のサブクラスの作成
アサートクラスの作成
PHPUnit_Extensions_TestDecorator のサブクラスの作成
PHPUnit_Framework_Test の実装
PHPUnit_Framework_TestResult のサブクラスの作成
PHPUnit_Framework_TestListener の実装
新しいテストランナーの作成
A. アサーション
B. XML 設定ファイル
テストスイート
グループ
コードカバレッジ対象のファイルの追加や除外
ログ出力
PMD ルール
PHP INI 項目やグローバル変数の設定
C. PHP 4 用の PHPUnit
D. 目次
E. 参考文献
F. 著作権