Prev Next

第16章 雛形ジェネレータ

PHPUnit Skeleton Generator を使うと、 プロダクションコードのクラスからテストクラスを生成したり その逆を実行したりすることができます。 インストールするには、次のコマンドを実行します。

pear install phpunit/PHPUnit_SkeletonGenerator

テストケースクラスの雛形の作成

既存のコードのテストを記述する際は、 以下のようなコードを何度となく繰り返し記述することになるでしょう。

public function testMethod()
{
}

PHPUnit Skeleton Generator は、既存のクラスのコードを解析して テストケースクラスの雛形を作成することができます。

例 16.1: Calculator クラス

<?php
class Calculator
{
public function add($a, $b)
{
return $a + $b;
}
}
?>

次の例は、Calculator という名前のクラス (例 16.1 を参照ください) 用のテストクラスの雛形を作成する手順を示すものです。

phpunit-skelgen --test Calculator
PHPUnit Skeleton Generator 1.0.0 by Sebastian Bergmann.

Wrote skeleton for "CalculatorTest" to "/home/sb/CalculatorTest.php".

もとのクラスの各メソッドについて、 出来上がったテストケースクラスのテストケースは不完全な状態 (第 9 章 を参照ください) です。

名前空間つきのクラスと雛形ジェネレータ

名前空間 内で宣言されたクラス用のコードを雛形ジェネレータで生成する際には、 そのクラスの修飾名とクラスが宣言されているソースファイルへのパスを渡さなければなりません。

たとえば、名前空間 project の中でクラス Calculator が宣言されている場合は 次のようにして雛形ジェネレータを実行します。

phpunit-skelgen --test -- "project\Calculator" Calculator.php
PHPUnit Skeleton Generator 1.0.0 by Sebastian Bergmann.

Wrote skeleton for "project\CalculatorTest" to "/home/sb/CalculatorTest.php".

作成されたテストケースクラスを実行した結果を以下に示します。

phpunit --bootstrap Calculator.php --verbose CalculatorTest
PHPUnit 3.8.0 by Sebastian Bergmann.

I

Time: 0 seconds, Memory: 3.50Mb

There was 1 incomplete test:

1) CalculatorTest::testAdd
This test has not been implemented yet.

/home/sb/CalculatorTest.php:38
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 0, Incomplete: 1.

@assert アノテーションを メソッドのコメント部で使用すると、 シンプルではあるけれど意味のあるテストを自動的に生成することができます。 これは不完全なテストケースではありません。 例 16.2 に例を示します。

例 16.2: @assert アノテーションをつけた Calculator クラス

<?php
class Calculator
{
/**
* @assert (0, 0) == 0
* @assert (0, 1) == 1
* @assert (1, 0) == 1
* @assert (1, 1) == 2
*/
public function add($a, $b)
{
return $a + $b;
}
}
?>

もとのクラスの各メソッドについて、 @assert アノテーションの内容をチェックします。 これらは、以下のようなテストコードに変換されます。

    /**
     * Generated from @assert (0, 0) == 0.
     */
    public function testAdd() {
        $o = new Calculator;
        $this->assertEquals(0, $o->add(0, 0));
    }

作成されたテストケースクラスを実行した結果を以下に示します。

phpunit --bootstrap Calculator.php --verbose CalculatorTest
PHPUnit 3.8.0 by Sebastian Bergmann.

....

Time: 0 seconds, Memory: 3.50Mb

OK (4 tests, 4 assertions)

表 16.1 に、サポートされる @assert の種類と、それがどのようなテストコードに変換されるかをまとめました。

表16.1 サポートされる @assert アノテーション

アノテーション 変換後の内容
@assert (...) == X assertEquals(X, method(...))
@assert (...) != X assertNotEquals(X, method(...))
@assert (...) === X assertSame(X, method(...))
@assert (...) !== X assertNotSame(X, method(...))
@assert (...) > X assertGreaterThan(X, method(...))
@assert (...) >= X assertGreaterThanOrEqual(X, method(...))
@assert (...) < X assertLessThan(X, method(...))
@assert (...) <= X assertLessThanOrEqual(X, method(...))
@assert (...) throws X @expectedException X

テストケースクラスからのクラスの雛形の作成

テスト駆動開発 (第 12 章 を参照ください) ではまずテストを書いてからそのテストの対象となるコードを書くことになりますが、 PHPUnit ではテストケースクラスをもとにしてクラスの雛形を作成することができます。

規約に従って、Unit クラスのテストは UnitTest クラスに記述されることになります。 このテストケースクラスのソースを検索し、 Unit クラスのオブジェクトを参照している変数を見つけて そのオブジェクトがどんなメソッドをコールしているかを調べます。 例として 例 16.4 を見てみましょう。これは、例 16.3 の解析結果をもとにして作成されたものです。

例 16.3: BowlingGameTest クラス

<?php
class BowlingGameTest extends PHPUnit_Framework_TestCase
{
protected $game;

protected function setUp()
{
$this->game = new BowlingGame;
}

protected function rollMany($n, $pins)
{
for ($i = 0; $i < $n; $i++) {
$this->game->roll($pins);
}
}

public function testScoreForGutterGameIs0()
{
$this->rollMany(20, 0);
$this->assertEquals(0, $this->game->score());
}
}
?>

phpunit-skelgen --class BowlingGameTest
PHPUnit Skeleton Generator 1.0.0 by Sebastian Bergmann.

Wrote skeleton for "BowlingGame" to "./BowlingGame.php".

例 16.4: 作成された BowlingGame クラスの雛形

<?php
/**
* Generated by PHPUnit_SkeletonGenerator on 2012-01-09 at 16:55:58.
*/
class BowlingGame
{
/**
* @todo Implement roll().
*/
public function roll()
{
// Remove the following line when you implement this method.
throw new RuntimeException('Not yet implemented.');
}

/**
* @todo Implement score().
*/
public function score()
{
// Remove the following line when you implement this method.
throw new RuntimeException('Not yet implemented.');
}
}
?>

作成されたクラスに対してテストを実行した結果を以下に示します。

phpunit --bootstrap BowlingGame.php BowlingGameTest
PHPUnit 3.8.0 by Sebastian Bergmann.

E

Time: 0 seconds, Memory: 3.50Mb

There was 1 error:

1) BowlingGameTest::testScoreForGutterGameIs0
RuntimeException: Not yet implemented.

/home/sb/BowlingGame.php:13
/home/sb/BowlingGameTest.php:14
/home/sb/BowlingGameTest.php:20

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