Prev Next

第10章 不完全なテスト・テストの省略

不完全なテスト

新しいテストケースクラスを作成する際には、 これから書くべきテストの内容をはっきりさせるために、 まず最初は以下のような空のテストメソッドを書きたくなることでしょう。

public function testSomething()
{
}

しかし、PHPUnit フレームワークでは空のメソッドを「成功した」 と判断してしまうという問題があります。このような解釈ミスがあると、 テスト結果のレポートが無意味になってしまいます。 そのテストがほんとうに成功したのか、 それともまだテストが実装されていないのかが判断できないからです。 実装していないテストメソッドの中で $this->fail() をコールするようにしたところで事態は何も変わりません。 こうすると、テストが「失敗した」と判断されてしまいます。 これは未実装のテストが「成功」と判断されてしまうのと同じくらいまずいことです (訳注: レポートを見ても、そのテストがほんとうに失敗したのか、 まだ実装されていないだけなのかがわかりません)。

テストの成功を青信号、失敗を赤信号と考えるなら、 テストが未完成あるいは未実装であることを表すための黄信号が必要です。 そのような場合に使用するインターフェイスが PHPUnit_Framework_IncompleteTest で、 これは未完成あるいは未実装のテストメソッドで発生する例外を表すものです。 このインターフェイスの標準的な実装が PHPUnit_Framework_IncompleteTestError です。

例 10.1 では SampleTest というテストケースクラスを定義しています。 便利なメソッド markTestIncomplete() (これは、自動的に PHPUnit_Framework_IncompleteTestError を発生させます) をテストメソッド内でコールすることで、 このメソッドがまだ完成していないことをはっきりさせます。

例 10.1: テストに未完成の印をつける

<?php
class SampleTest extends PHPUnit_Framework_TestCase
{
public function testSomething()
{
// オプション: お望みなら、ここで何かのテストをしてください。
$this->assertTrue(TRUE, 'これは動いているはずです。');

// ここで処理を止め、テストが未完成であるという印をつけます。
$this->markTestIncomplete(
'このテストは、まだ実装されていません。'
);
}
}
?>

未完成のテストは、PHPUnit のコマンドライン版テストランナーでは以下のように I で表されます。

phpunit --verbose SampleTest
PHPUnit 3.5.13 by Sebastian Bergmann.

I

Time: 0 seconds, Memory: 3.75Mb

There was 1 incomplete test:

1) SampleTest::testSomething
このテストは、まだ実装されていません。

/home/sb/SampleTest.php:12
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 1, Incomplete: 1.

表 10.1 に、テストを未完成扱いにするための API を示します。

表10.1 未完成のテスト用の API

メソッド 意味
void markTestIncomplete() 現在のテストを未完成扱いにします。
void markTestIncomplete(string $message) 現在のテストを未完成扱いにします。それを説明する文字列として $message を使用します。

テストの省略

すべてのテストがあらゆる環境で実行できるわけではありません。 考えてみましょう。たとえば、データベースの抽象化レイヤーを使用しており、 それがさまざまなドライバを使用してさまざまなデータベースシステムを サポートしているとします。MySQL ドライバのテストができるのは、 当然 MySQL サーバが使用できる環境だけです。

例 10.2 に示すテストケースクラス DatabaseTest には、 テストメソッド testConnection() が含まれています。 このクラスのテンプレートメソッド setUp() では、 MySQLi 拡張モジュールが使用可能かを調べたうえで、もし使用できない場合は markTestSkipped() メソッドでテストを省略するようにしています。

例 10.2: テストを省略する

<?php
class DatabaseTest extends PHPUnit_Framework_TestCase
{
protected function setUp()
{
if (!extension_loaded('mysqli')) {
$this->markTestSkipped(
'MySQLi 拡張モジュールが使用できません。'
);
}
}

public function testConnection()
{
// ...
}
}
?>

飛ばされたテストは、PHPUnit のコマンドライン版テストランナーでは以下のように S で表されます。

phpunit --verbose DatabaseTest
PHPUnit 3.5.13 by Sebastian Bergmann.

S

Time: 0 seconds, Memory: 3.75Mb

There was 1 skipped test:

1) DatabaseTest::testConnection
MySQLi 拡張モジュールが使用できません。

/home/sb/DatabaseTest.php:9
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 0, Skipped: 1.

表 10.2 に、テストを省略するための API を示します。

表10.2 テストを省略するための API

メソッド 意味
void markTestSkipped() 現在のテストを省略扱いにします。
void markTestSkipped(string $message) 現在のテストを省略扱いにします。それを説明する文字列として $message を使用します。

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. 著作権