The symfony Cookbook

モデルのユニットテストを行う

You are currently browsing
the website for symfony 1

Visit the Symfony2 website


About

You are currently reading "The symfony Cookbook" which is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.

Master symfony

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
trainings.sensiolabs.com

Books on symfony

Learn more about symfony with the official guides.
books.sensiolabs.com

L'audit Qualité par SensioLabs

200 points de contrôle de votre applicatif web.
audit.sensiolabs.com

Chapter Content

データベースの接続

テストデータ

ユニットテストを書く

symfony training
Be trained by symfony experts
May 29: Paris (Web Development with Symfony2 - Français)
May 31: Paris (Mastering Symfony2 - Français)
Jun 06: Paris (Introduction to Symfony2 - Français)
Jun 06: Paris (Introduction to Symfony2 - English)
Jun 06: Paris (Going Further with Symfony2 - English)
and more...

Search


powered by google
You are currently browsing "The symfony Cookbook" in Japanese for the 1.1 version - Switch to version: - Switch to language:
Creative Commons License This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.
Translation of this work into another language is explicitly allowed.
This version of symfony is not maintained anymore.
If some of your projects still use this version, consider upgrading as soon as possible.

PropelもしくはDoctrineモデルのためのユニットテストを書くのは極めて簡単です。 このチュートリアルでは、モデル用のベターなテストを書くための 重要なティップスとベストプラクティスを学びます。

データベースの接続

Propelのモデルクラスをテストするには、データベースが必要です。 開発用のものが既にありますが、 テスト専用のものを常に作っておくことは良い習慣です。

すべてのテストはtest環境下で実行されるので、 config/databases.yml設定ファイルを編集して test環境用のデフォルト設定を上書きする必要があるだけです:

test:
  propel:
    param:
      database:     myproject_test
 
dev:
  # dev configuration
 
all:
  propel:
    class:          sfPropelDatabase
    param:
      datasource:   propel
      phptype:      mysql
      hostspec:     localhost
      database:     myproject
      username:     someuser
      password:     somepa$$word

このケースにおいて、データベースの名前だけを変更しましたが、 データベースのエンジンを変更してたとえばSQLiteを利用することもできます。

テストデータ

テスト用の専用データベースがあるので、ユニットテストを立ち上げるたびに テストデータ(フィクスチャ)をロードする方法が必要です。 これはテストを実行するたびにデータベースを同じ状態にしたいからです。

sfDataクラスのおかげでこれを実現する方法はとても簡単です:

$loader = new sfPropelData();
$loader->loadData(sfConfig::get('sf_test_dir').'/fixtures');

loadData()メソッドは1番目の引数としてディレクトリもしくはファイルを受け取ります。 共通のfixturesディレクトリは次の通りです:

test/
  fixtures/
    10_categories.yml
    20_articles.yml
    30_comments.yml

すべてのファイルの接頭辞として数字が追加されていることに注目してください。 これはデータをロードする順序をコントロールするための簡単な方法です。 プロジェクトで後からフィクスチャデータを差し込む必要がある場合、既存の数字の間に好きな数字を入れます:

test/
  fixtures/
    10_categories.yml
    15_must_be_laoded_between_categories_and_articles.yml
    20_articles.yml
    30_comments.yml

賢明な読者はsymfony bookではこれらのフィクスチャがdata/ディレクトリに設置することを推奨されているのに対して、 筆者がフィクスチャをtest/ディレクトリに設置したことに注目するでしょう。 これは本当に好みの問題ですが、筆者はこれらの2つのディレクトリの中でフィクスチャを編成することを好みます。 フィクスチャを2つの異なるグループに分類できるからです:

テストデータの一式が小さいときはこのシンプルなスキーマは立派に機能しますが、

モデルが成長し、もっとたくさんのフィクスチャを持つようになったら、データベースの中でそれらをロードする時間が重大になる可能性があります。

ですので、テストデータのサブセットだけをロードする方法が必要です。 これを行う1つの方法は主要な機能ごとにサブディレクトリを作ることで下位のテストデータの分類を行うことです:

test/
  fixtures/
    10_cms/
      10_categories.yml
      20_articles.yml
      30_comments.yml
    20_forum/
      10_threads.yml

これでメインのfixturesディレクトリをロードする代わりに、 テストしたいモデルクラスに対応したサブディレクトリの1つだけをロードできます。 しかしたいていの場合、ユーザーのように共有データをロードすることも必要です:

test/
  fixtures/
    00_common/
      10_users.yml
    10_cms/
      10_categories.yml
      20_articles.yml
      30_comments.yml
    20_forum/
      10_threads.yml

テストファイルもしくはディレクトリをロードするために、loadData()メソッドを 何度も呼び出すことができます:

// load users and all the CMS data
$loader = new sfPropelData();
$loader->loadData(sfConfig::get('sf_test_dir').'/fixtures/00_common/10_users.yml');
$loader->loadData(sfConfig::get('sf_test_dir').'/fixtures/10_cms');

これによって10_users.ymlフィクスチャファイルはロードされ すべてのフィクスチャファイルは10_cmsディレクトリの中で見つかります。

ユニットテストを書く

専用データベースを既知の状態にする方法があるので、 Articleモデル用のユニットテストを作りましょう。

ファイルをブートストラップするPropelの典型的なユニットテストは次の通りです:

// test/unit/model/ArticlePeerTest.php
include(dirname(__FILE__).'/../../bootstrap/unit.php');
 
$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'test', true);
 
new sfDatabaseManager($configuration);
 
$loader = new sfPropelData();
$loader->loadData(sfConfig::get('sf_test_dir').'/fixtures');
 
$t = new lime_test(1, new lime_output_color());
 
$t->diag('::retrieveBySlug()');
$article = ArticlePeer::retrieveBySlug('the-best-framework-ever');
$t->is($article->getTitle(), 'The Best Framework Ever', '->retrieveBySlug()は特定のスラグにマッチする記事を返す');

このスクリプトの内容は一目瞭然です:

ユニットテストを書くことに慣れていないのであれば、最初は怖いかもしれません。

筆者がテストする必要があることを知るためにいつも使ういくつかのティップスは次の通りです:

筆者のテストファイルは同じパターンで常に構造化されます:

// テストするメソッドでメッセージを出力する(->はインスタンスメソッドに対して、::はクラスメソッドに対して)
$t->diag('->methodName()');
 
// 1回につきシンプルなセンテンスで表現できる1つのことをテストする
// センテンスは常にメソッドの名前で始まる
// 動詞はしなければならないこと、どのように振る舞わなければならないことなどを表現する
$t->is($object->methodName(), 1, '->methodName()は引数が渡されていない場合は1を返す');

Questions & Feedback

If you find a typo or an error, please register and open a ticket.

If you need support or have a technical question, please post to the official user mailing-list.