`ActiveRecord::FixtureSet`(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社エンジニアの「?」を「!」に。`ActiveRecord::FixtureSet`(翻訳)hachi8833シェアツイートブックマークLINE概要MITライセンスに基づいて翻訳・公開いたします。MIT-LICENSE以下も参考にどうぞ。ActiveRecord::FixtureSet(翻訳)fixtureとは、テストの対象としたいデータ(つまりサンプルデータ)を組み立てる手法のひとつです。fixtureはYAMLファイルに保存されます。1つのYAMLファイルが1つのモデルに対応し、ActiveSupport::TestCase.fixture_path=(パス)で指定されたディレクトリに保存されます(このディレクトリはRailsで自動設定されますので、自分のRailsアプリ/test/fixtures/に保存できます)。自分のRailsアプリ/test/fixtures/web_sites.yml)。fixtureファイルのフォーマットは次のような感じになります。http://www.google.com上のfixtureファイルにはfixtureが2件含まれています。値」の形式で記述します。レコードとレコードの間には見やすくするための空行が入ります。fixture同士の間には順序関係がありません。fixtureを順序付けしたい場合は、omapというYAMLをお使いください。omapの仕様についてはyaml.org/type/omap.htmlをどうぞ。同じテーブルのキーに外部キー制約を付ける場合は、順序ありのfixtureが必要になります。これは主に次のようなツリー構造で必要となります。Childテストケースでfixtureを使うfixtureはテストの構成要素なので、fixtureは単体テストや機能テストで用いられます。fixtureの利用法は2とおりありますが、まずは単体テストのサンプルを見てみましょう。endendtest_helper.rbはデフォルトですべてのfixtureをテストデータベースに読み込みます。したがって、このテストは成功します。test環境では、各テストの実行前にすべてのfixtureが自動的にデータベースに読み込まれます。データの一貫性を保つために、fixtureは読み込みが実行される前に環境によって削除されます。fixtureはデータベースでも利用できますが、その他にモデルと同じ名前の特殊な動的メソッドを介してアクセスすることもできます。この動的メソッドにfixture名を渡すと、その名前と一致するfixtureを返します。web_sites(:rubyonrails).nameendfixture名を複数渡すと、それらの名前に一致するfixtureをすべて返します。:google).lengthend引数を渡さない場合、すべてのfixtureを返します。web_sites.lengthend存在しないfixture名を渡すとStandardErrorが発生します。}end別の方法として、fixtureデータの自動インスタンス化を有効にすることもできます。次のテストがあるとします。@rubyonrails.nameendテストケース内でこれらの手法を用いてfixtureデータにアクセスするには、ActiveSupport::TestCaseの派生クラスで以下のいずれか1つを指定しなければなりません。インスタンス化されたfixtureをすべて有効にする(上のalt_method_1とalt_method_2を有効にする)には以下のようにします。truefixtureのハッシュだけを作成し、各インスタンスをfindしない(alt_method_1のみを有効にする)ようにするには以下のようにします。:no_instancesこれらの別の方法のいずれかを使うと、パフォーマンスに悪影響が生じます。理由は、fixtureのハッシュやインスタンス変数を作成するために、データベース内のfixture化されたデータをフルスキャンしなければならないためです。そのため、fixture化されたデータセットが大規模になるとコストがかさみます。ERBで動的fixtureを使うfixtureの量が重要だが、fixtureの中身はさほど重要ではない場合があります。そのような場合はYAMLのfixtureでERBを併用することで、以下のようにテストの読み込みで大量のfixtureを作成できます。%>上はきわめてシンプルなfixtureを1000件作成します。%>などをのような動的な値をfixtureに注入できます。この機能には若干の注意点があります。fixtureは、それがfixtureの形であれば予測可能なサンプルデータの安定的な単位となりますが、そこに動的な値を注入する必要があると思えてきた場合は、おそらくアプリケーションが正しくテスト可能な状態であるかどうかを再点検する必要があるでしょう。fixtureの中で動的な値を使うことはすなわち「コードの匂い」と考えるべきです。あるfixture内で定義されたヘルパーメソッドは、他のfixtureでは利用できません。これは、テスト同士をまたがる依存関係を意図に反して作り出さないためです。複数のfixtureで用いるメソッドは、::context_classでincludeされる何らかのモジュール内で定義すべきです。%>トランザクショナルテストテストケースでは、テストケースごとにdeleteとinsertを使う代わりに、beginとrollbackを用いてデータベース変更を分離できます。test)を行うと、テストケース内のすべてのfixture宣言を省略できることがあります。理由は、全データが既に存在し、すべてのケースの変更がロールバックされるからです。インスタンス化されたfixtureでプリロード済みデータを用いるには、self.pre_loaded_fixturesをtrueに設定してください。これにより、fixture経由で読み込まれたすべてのテーブルのfixtureデータにアクセスできるようになります(この挙動はuse_instantiated_fixturesの値によって変わります)。以下の場合はトランザクショナルテストを使いません。トランザクションが正しく動いているかどうかをテストする場合。ネストしたトランザクションは、すべての親トランザクションがコミットされるまでコミットされません(特にfixtureのトランザクションがセットアップで開始され、ティアダウン(teardown)でロールバックする場合)。Recordがネステッドトランザクションまたはsavepointsをサポートするまではトランザクションの結果を検証できません(これについては作業中)。データベースがトランザクションをサポートしていない場合。Recordデータベースはトランザクションをサポートしています。その場合はInnoDBかMaxDBかNDBをお使いください。アドバンストfixtureIDを指定しないfixtureにはいくつかの機能を利用できます。現在のRailsでHABTM(has_and_belongs_to_many)を使ったリレーションは一般に悪手とされています。:through関連付けを使うのが一般的です。ガイドIDを指定した場合でも利用できる機能がいくつかあります。defaultsのサポート安定な自動生成ID以下のおさるfixtureがあるとします。Pirateそれぞれのfixtureには一意のIDが2種類あります。2つのIDのうち、1つはデータベース用で、もう1つは人間用です。する代わりに、主キーを生成できるとよいでしょう。それぞれのfixtureのラベルがハッシュ化されて一貫したIDが生成されます。Recordはこのfixtureのモデルクラスを参照して正しい主キーを見つけ、fixtureがデータベースに挿入される直前に主キーを生成します。IDを見つけられます。関連付けをラベルで参照する(belongs_to、has_one、has_many)fixtureで外部キーを指定すると非常にもろくなる可能性があり、しかも読みにくくなります(言うまでもありませんが)。Recordは任意のfixtureのIDをラベルで特定できるので、外部キーを(IDではなく)ラベルで指定できます。belongs_toおさると海賊でもう少しやってみましょう。1この調子でおさると海賊を増やして複数のファイルに分割すると、追いかけるのがつらくなってきます。IDをやめてラベルを使ってみましょう。reginald見事にすっきりしました。george)のターゲットラベルを指定できるようになります。ポリモーフィックbelongs_toポリモーフィックなリレーションシップのサポートは少し複雑です。Recordが認識する必要があるためです。次のような例ならわかりやすいでしょう。Monkeyもっとよくできそうですね。Recordが面倒を見てくれます。has_and_belongs_to_manyおさるにフルーツをあげる時間になりました。fixtureを消し去りましょう。grapefruits_monkeys.ymlファイルが不要になりました!ここではジョージのfixtureでフルーツのリストを指定しましたが、フルーツごとにおさるのリストを指定することも簡単です。Recordに反映され、has_and_belongs_to_many関連付けが見つかるようになります。Recordの標準的なタイムスタンプカラム(created_at、created_on、updated_at、updated_on)のいずれかがテーブルやモデルで指定される場合は、自動的にTime.nowで設定されます。特定の値が設定済みの場合は何もしません。現在のfixtureのラベルは、カラムの値としていつでも参照できます。$LABEL@email.comまた、指定のラベルでIDを保持できるようにする必要が生じることがあります(古い結合テーブルfixtureを移植する場合など)。そんなときはERBが役に立ちます。defaultsのサポートfixtureのYAMLファイルでデフォルト値を設定して再利用できます。これはdatabase.ymlでデフォルトを指定するのに使われる手法と同じです。この場合DEFAULTSはすべて大文字にする必要があります。*DEFAULTSラベルが「DEFAULTS」のfixtureはすべて安全に無視されます。fixtureのモデルクラスを設定するfixtureのモデルクラスをYAMLファイルで直接指定できます。db:fixtures:loadの実行時など)に有用です。Davidラベルが「_fixture」のfixtureはすべて安全に無視されます。コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。enno.jpを運営。実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。Storageを使ってはいけない(翻訳)#Tags#会社紹介#自社サービス#勉強会#Rails#PHP#デザイン#実績#週刊RailsウオッチCONTACTお気軽にご相談ください。(翻訳)CONTACTTechRachoでは、パートナーシップをご検討いただける方からのご連絡をお待ちしております。お気軽にご意見・ご相談ください。