テスト概要 ======== テストはソフトウェア開発に必要不可欠です。 それを承知しているか否かに関係なく、私たちがウェブアプリケーションを開発している時にはいつでもテストを行います。 例えば、PHP でクラスを書いた時、実装したメソッドが正しい事を確認するために、`echo` や `die` といった文を使うかもしれません。 また、複雑な HTML フォームを含むウェブページを実装するとき、期待された動作を保障するために、いくつかのテストデータを入力するかもしれません。 より高度な開発者は、テストが必要な際、毎回、コードを呼び出せば、コンピュータがテストを実行するように、テストを自動化するためのコードを書くでしょう。 これは **自動化テスト** として知られているもので、この章のメイントピックです。 Yii が提供するテストサポートには、**ユニットテスト** と **機能テスト** が含まれます。 ユニットテストは、コードの 1 ユニットが期待した通りに動作するどうかを検証します。 オブジェクト指向プログラミングでは、最も基本的なコード単位はクラスです。 よって、ユニットテストでは、主にクラス内の各インタフェースメソッドが適切に動くかどうかを検証する必要があります。 すなわち、異なった入力パラメーターを与えて、そのメソッドが期待された結果を返すかどうかを検証します。 ユニットテストは通常、テストされるクラスを書いた人により開発されます。 機能テストは、(例えばブログシステムの記事管理のような) 機能が期待した通りに動作するどうかを検証します。 ユニットテストと比較すると、機能テストは、テストされる機能が、複数のクラスにまたがる場合が多いため、より高いレベルのテストとなります。 機能テストは通常、システムの要件を良く知る人 (開発者か品質管理技術者のどちらかでしょう) により開発されます。 テスト駆動開発 ----------------------- 以下では、いわゆる [テスト駆動開発 (TDD)](http://ja.wikipedia.org/wiki/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA) での開発サイクルを示します。 1. 実装されるべき機能をカバーする新しいテストを作成します。 機能がまだ実装されていないので、新しいテストは最初の実行時に失敗すると予想されます。 2. 全てのテストを実行し、新しいテストが失敗することを確認します。 3. 新しいテストに合格するようにコードを書きます。 4. 全てのテストを実行し、それらが全て合格することを確認します。 5. 新しく書かれたコードをリファクタリングした上で、全てのテストが合格することを確認します。 ステップ 1 から 5 を繰り返して、機能の実装を進めて行きます。 テスト環境構築 ---------------------- Yii がサポートするテストには [PHPUnit](http://www.phpunit.de/) 3.5 以上 と [Selenium Remote Control](http://seleniumhq.org/projects/remote-control/) 1.0 以上が必要です。 PHPUnit と Selenium Remote Control のインストール方法については、それらのドキュメントを参照してください。 新しい Yii アプリケーションを `yiic webapp` コンソールコマンドで生成すると、同時に、テストを書いて実行するためのファイルとディレクトリが下記のように生成されます。 ~~~ testdrive/ protected/ 保護されたアプリケーションファイルが含まれる tests/ アプリケーションのテストが含まれる fixtures/ データベースフィクスチャが含まれる functional/ 機能テストが含まれる unit/ ユニットテストが含まれる report/ カバレッジレポートが含まれる bootstrap.php 最初に実行されるスクリプト phpunit.xml PHPUnitの設定ファイル WebTestCase.php ウェブベースの機能テストのための基本クラス ~~~ 上記で示すように、テストコードは主として3つのディレクトリ、`fixtures`, `functional` および `unit` に置かれます。 そして `report` ディレクトリが、生成されたコードカバレッジレポートを格納するために使用されます。 テスト (ユニットテストまたは機能テスト) を実行するためには、コンソールウィンドウで下記のコマンドを実行します。 ~~~ % cd testdrive/protected/tests % phpunit functional/PostTest.php // 特定のテストを実行 % phpunit --verbose functional // 'functional' 下の全てのテストを実行 % phpunit --coverage-html ./report unit ~~~ 上記において、最後のコマンドは `unit` ディレクトリ下のすべてのテストを実行して、`report` ディレクトリの下にコードカバレッジレポートを生成します。 コードカバレッジレポートを生成するためには、[xdebug 拡張](http://www.xdebug.org/) がインストールされて有効になっている必要があることに注意して下さい。 テストのブートストラップスクリプト -------------------- `bootstrap.php` ファイルに何が書かれているか見てみましょう。 このファイルは、[エントリスクリプト](/doc/guide/basics.entry) に似ており、また、一連のテストを実行する時の開始点であるという意味で、特別なファイルです。 ~~~ [php] $yiit='path/to/yii/framework/yiit.php'; $config=dirname(__FILE__).'/../config/test.php'; require_once($yiit); require_once(dirname(__FILE__).'/WebTestCase.php'); Yii::createWebApplication($config); ~~~ 上記においては、最初に Yii フレームワークから `yiit.php` ファイルをインクルードしています。 このファイルがいくつかのグローバル定数を初期化し、必要になるテストの基本クラスをインクルードします。 次に `test.php` 構成ファイルを使って、ウェブアプリケーションのインスタンスを作成します。 `test.php` をチェックすれば、それが `main.php` 構成ファイルから継承しながら、[CDbFixtureManager] というクラスの `fixture` アプリケーションコンポーネントを追加していることが分るでしょう。 フィクスチャについては、次の章で詳細に説明します。 ~~~ [php] return CMap::mergeArray( require(dirname(__FILE__).'/main.php'), array( 'components'=>array( 'fixture'=>array( 'class'=>'system.test.CDbFixtureManager', ), /* テスト用のデータベース接続を提供するためには、コメントを外すこと 'db'=>array( 'connectionString'=>'テスト用データベースの DSN', ), */ ), ) ); ~~~ データベースを含むテストを実行する時には、テストの実行が通常の開発や運用の活動に干渉しないように、テスト用のデータベースを提供すべきです。 そうするためには、上記の `db` 構成のコメントを外して、`connectionString` プロパティにテスト用データベースの DSN (データソース名) を入力するだけで済みます。 このようなブートストラップスクリプトによって、ユニットテストを実行する時には、ウェブリクエストに応答するためのものとほとんど同一のアプリケーションインスタンスが作られることになります。 主な違いは、テスト用のインスタンスがフィクスチャマネジャを持っていることと、テスト用のデータベースを使うことです。