Prev Next

第2章 PHPUnit の目標

いまのところ、組み込みの array および count() 関数のテストしかありません。 PHP が提供する数多くの array_*() 関数をテストしようとすると、それらそれぞれについてテストを記述する必要があります。 それらのすべてのテストについて基盤部分を最初から書いていくこともできますが、 共通部分は一度だけ記述するようにし、 個々のテストではテスト固有の部分のみを記述していくほうがずっとよい方法です。 PHPUnit は、そのような基盤部分を提供します。

PHPUnit のようなフレームワークには、解決しなければならない制約があります。 その中のいくつかはお互いに相反するものです。 テストは、以下の条件を同時に満たす必要があります。

記述方法を習得しやすいこと。

テストの書き方を身に着けるのが難しければ、 開発者はそんなものを覚えようとしないでしょう。

記述しやすいこと。

テストが書きにくければ、開発者はそんなものを書こうとしないでしょう。

読みやすいこと。

テストコードには、外部からの要素を含めるべきではありません。 そうするとテストコードが周りのノイズに埋もれてしまいます。

実行しやすいこと。

ボタン一発でテストが実行でき、 その結果は明白な形式で表示されなければなりません。

すばやく実行できること。

一日に何百何千というテストを実行できるよう、 テストはすばやく実行できなければなりません。

独立していること。

テストは、お互い他のテストに影響を及ぼしてはいけません。 テストの実行順序を変えることでテストの結果が変わってしまってはいけません。

自由に組み合わせられること。

テストの数や組み合わせを自由に選択できなければなりません。 テストが独立している以上、これは当然のことです。

これらの制約の中には、相反する項目が 2 点あります。

習得のしやすさか書きやすさか。

一般に、テストにはプログラミング言語の全機能を必要としません。 多くのテストツールは、テストを記述するため必要最小限の機能のみを組み込んだ 独自のスクリプト言語を提供しています。その結果、テストは読みやすく、 また書きやすいものになります。 なぜならテストの内容から気をそらせるノイズがないためです。しかし、 またひとつ新たなプログラミング言語やプログラミングツールの使い方を覚える必要があり、 不便です。

独立か実行速度か。

ひとつのテストが他のテストの結果に何の影響もおよぼさないようにするには、 各テストの実行前に毎回テスト用の環境を構築し、 終了後には毎回それを元の状態に戻す必要があります。しかし、環境を構築する (例: データベースに接続し、特定の状態を表すデータを投入する) には長い時間がかかります。

PHPUnit は、テスト言語として PHP を使用することで これらの衝突を回避しようとしています。小規模で単純なテストを行う際には、 PHP の機能は行き過ぎた面もあるかもしれません。しかし、PHP を使用することで、 これまでの開発経験や開発ツールを武器として利用できます。 あまり気乗りしないテスターを納得させるため、 テストを最初に書き始める際の負担をできるだけ下げることが重要だと考えています。

PHPUnit では、実行速度よりもテストの独立性を重視しています。 独立したテストに価値があるのは、そのほうがより高品質のフィードバックが得られるからです。 一連のテストの最初のほうで失敗したことでその後のすべてのテストが失敗してしまい、 大量の失敗報告を受け取るようなことがなくなります。 このオリエンテーションでは独立したテストを目指し、 シンプルなオブジェクトを数多く作るという設計を心がけます。 各オブジェクトは独立してすばやくテストできます。結果としてよりよい設計 に加えてより高速なテストが可能となります。

PHPUnit ではほとんどのテストが成功することを想定しており、 成功したテストの詳細について報告することはあまり価値がないと考えています。 テストが失敗した場合には、そのことをしっかり報告しなければなりません。 大半のテストは成功すべきであり、 それらについては実行したテストの数以外に特にコメントすべき情報はありません。 これは、PHPUnit のコアではなく報告用のクラス群に組み込まれている機能です。 テストの結果が表示される際には実行したテストの数が表示されますが、 詳細が表示されるのは失敗したテストについてだけです。

テストは決め細やかに行うこと、つまりひとつのテストではひとつのオブジェクトの ひとつの機能についてをテストするようにすることが期待されています。 そのため、最初のテストは失敗し、テストの実行は終了し、 PHPUnit は失敗を報告します。多くの小さなテストを実行させることは一種の芸術です。 決め細やかなテストにより、システム全体の設計がよりよいものとなります。

PHPUnit でオブジェクトをテストする際には、 その公開インターフェースについてのみテストを行います。 公開されている振る舞いにのみ基づいてテストを行うことで、 設計上の困難な問題により早い段階で対応できるようになり、 設計ミスがシステムの大部分に影響を及ぼすことを避けられます。

Prev Next
1. 自動テスト
2. PHPUnit の目標
3. PHPUnit のインストール
4. PHPUnit 用のテストの書き方
テストの依存性
データプロバイダ
例外のテスト
PHP のエラーのテスト
アサーション
assertArrayHasKey()
assertClassHasAttribute()
assertClassHasStaticAttribute()
assertContains()
assertContainsOnly()
assertEmpty()
assertEqualXMLStructure()
assertEquals()
assertFalse()
assertFileEquals()
assertFileExists()
assertGreaterThan()
assertGreaterThanOrEqual()
assertInstanceOf()
assertInternalType()
assertLessThan()
assertLessThanOrEqual()
assertNull()
assertObjectHasAttribute()
assertRegExp()
assertStringMatchesFormat()
assertStringMatchesFormatFile()
assertSame()
assertSelectCount()
assertSelectEquals()
assertSelectRegExp()
assertStringEndsWith()
assertStringEqualsFile()
assertStringStartsWith()
assertTag()
assertThat()
assertTrue()
assertType()
assertXmlFileEqualsXmlFile()
assertXmlStringEqualsXmlFile()
assertXmlStringEqualsXmlString()
5. コマンドラインのテストランナー
6. Fixtures
tearDown() よりも setUp()
バリエーション
Fixture の共有
グローバルな状態
7. テストの構成
ファイルシステムを用いたテストスイートの構成
XML 設定ファイルを用いたテストスイートの構成
8. テストケースの拡張
出力内容のテスト
9. データベースのテスト
データベースのテストに対応しているベンダー
データベースのテストの難しさ
データベーステストの四段階
1. データベースのクリーンアップ
2. フィクスチャの準備
3–5. テストの実行、結果の検証、そして後始末
PHPUnit のデータベーステストケースの設定
getConnection() の実装
getDataSet() の実装
データベーススキーマ (DDL) とは?
ヒント: 自前でのデータベーステストケースの抽象化
データセットとデータテーブルについて知る
利用できる実装
外部キーには注意
自作のデータセットやデータテーブルの実装
接続 API
データベースアサーション API
テーブルの行数のアサーション
テーブルの状態のアサーション
クエリの結果のアサーション
複数のテーブルの状態のアサーション
よくある質問
PHPUnit は、テストごとにデータベーススキーマを作り直すの?
PDO を使ったアプリケーションじゃないと Database Extension を使えないの?
Too much Connections というエラーが出たらどうすればいい?
フラット XML や CSV のデータセットで NULL を扱う方法は?
10. 不完全なテスト・テストの省略
不完全なテスト
テストの省略
11. テストダブル
スタブ
モックオブジェクト
ウェブサービスのスタブおよびモック
ファイルシステムのモック
12. テストの進め方
開発中のテスト
デバッグ中のテスト
13. テスト駆動開発
銀行口座の例
14. 振舞駆動開発
ボウリングゲームの例
15. コードカバレッジ解析
カバーするメソッドの指定
コードブロックの無視
ファイルのインクルードや除外
16. テストのその他の使用法
アジャイルな文書作成
複数チームでのテスト
17. 雛形ジェネレータ
テストケースクラスの雛形の作成
テストケースクラスからのクラスの雛形の作成
18. PHPUnit と Selenium
Selenium RC
PHPUnit_Extensions_SeleniumTestCase
19. ログ出力
テスト結果 (XML)
テスト結果 (TAP)
テスト結果 (JSON)
コードカバレッジ (XML)
20. PHPUnit の拡張
PHPUnit_Framework_TestCase のサブクラスの作成
カスタムアサーションの作成
PHPUnit_Framework_TestListener の実装
PHPUnit_Extensions_TestDecorator のサブクラスの作成
PHPUnit_Framework_Test の実装
A. アサーション
B. アノテーション
@assert
@author
@backupGlobals
@backupStaticAttributes
@covers
@dataProvider
@depends
@expectedException
@expectedExceptionCode
@expectedExceptionMessage
@group
@outputBuffering
@runTestsInSeparateProcesses
@runInSeparateProcess
@test
@testdox
@ticket
C. XML 設定ファイル
PHPUnit
テストスイート
グループ
コードカバレッジ対象のファイルの追加や除外
ログ出力
テストリスナー
PHP INI 項目や定数、グローバル変数の設定
Selenium RC の設定ブラウザ
D. 目次
E. 参考文献
F. 著作権