Skip to content
Menu
CDhistory
CDhistory

Getting Started

Posted on 8月 17, 2021 by admin
  • Update Your Gemfile
  • テストスイートの設定
  • Test::Unit
  • Cucumber
  • Spinach
  • Minitest
  • Minitest:.NET
  • Minitest::Spec
  • minitest-rails
  • Defining factories
  • Using factories
  • Dependent Attributes
  • Transient Attributes
  • 継承
  • Associations
  • Traits
  • コールバック
  • Building or Creating Multiple Records
  • Linting Factories
  • Custom Construction
  • カスタム戦略
  • オブジェクトを永続化するカスタム メソッド
  • ActiveSupport Instrumentation
  • Rails プリローダーと RSpec
  • Bundler なしで使用する場合

Update Your Gemfile

Railsを使っている場合は、factory_girl_rails:

gem "factory_girl_rails", "~> 4.0"

Railsを使っていない場合は、factory_girl:

gem "factory_girl", "~> 4.0"
export JRUBY_OPTS=--1.9

Gemfileが更新できたら、バンドルの更新を行いましょう。

テストスイートの設定

サポートフォルダがイーガーリーロードされないので、rails_helper で上記のファイルを要求するのを忘れないでください

require 'support/factory_girl'

Test::Unit

class Test::Unit::TestCase include FactoryGirl::Syntax::Methodsend

Cucumber

# env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)World(FactoryGirl::Syntax::Methods)

Spinach

class Spinach::FeatureSteps include FactoryGirl::Syntax::Methodsend

Minitest

class Minitest::Unit::TestCase include FactoryGirl::Syntax::Methodsend

Minitest:.NET

class Minitest::Unit::TestCase include FactoryGirl::Syntax::Methodsend

Minitest::Spec

class Minitest::Spec include FactoryGirl::Syntax::Methodsend

minitest-rails

class ActiveSupport::TestCase include FactoryGirl::Syntax::Methodsend

テスト スイートに FactoryGirl::Syntax::Methods を含めない場合、すべての factory_girl メソッドの前に FactoryGirl を付ける必要があります。

Defining factories

各ファクトリーは名前と属性のセットを持っています。 名前は、デフォルトではオブジェクトのクラスを推測するために使用されますが、明示的に指定することも可能です。

そのクラスのインスタンスを作成するために必要な属性の最も単純なセットを提供する、各クラスに 1 つのファクトリを持つことが強く推奨されます。 ActiveRecord オブジェクトを作成する場合、これは、検証によって必要とされ、デフォルトを持たない属性のみを提供する必要があることを意味します。

同じ名前で複数のファクトリーを定義しようとすると、エラーが発生します。

ファクトリーはどこでも定義できますが、ファクトリーが次の場所にあるファイルで定義されている場合、FactoryGirl.find_definitions を呼び出した後に自動的に読み込まれます:

test/factories.rbspec/factories.rbtest/factories/*.rbspec/factories/*.rb

Using factories

factory_girl は複数の異なる構築戦略をサポートしています。

どの戦略を使用する場合でも、ハッシュを渡すことにより、定義された属性を上書きすることが可能です。 これらの「動的」属性は、パラメータの代わりにブロックを渡すことで追加できます。

factory :user do # ... activation_code { User.generate_activation_code } date_of_birth { 21.years.ago }end

Ruby のブロック構文のため、属性を Hashes として定義すると (たとえば、シリアライズ/JSON 列の場合)、2 組の中括弧が必要です。 これは、たとえば、Post オブジェクトが、実際には User クラスのインスタンスを参照する author 属性を持っている場合に便利でしょう。 通常 factory_girl はアソシエーション名からファクトリー名を推測しますが、この場合、無駄に author ファクトリーを探してしまいます。

Dependent Attributes

Attributes can be based on the values of other attributes using the evaluates that is yield to dynamic attribute blocks.

Transient Attributes

Transient attribute to factory でコードを DRY アップできる場合があります。

Static および Dynamic 属性は、Transient 属性として作成することができます。 Transient 属性は attributes_for 内では無視され、属性が存在するか、それをオーバーライドしようとした場合でも、モデルには設定されません。 factory_girl コールバックで評価者にアクセスする必要がある場合は、2 番目のブロック引数 (評価者用) を宣言し、そこからトランジェントな属性にアクセスする必要があります。

factory :dna do add_attribute(:sequence) { 'GATTACA' }endfactory :payment do add_attribute(:method) { 'paypal' }end

継承

ファクトリーを入れ子にすることにより、共通の属性を繰り返すことなく、同じクラスに対して複数のファクトリーを簡単に作成できます:

また、親を明示的に割り当てることもできます:

factory :post do title "A title"endfactory :approved_post, parent: :post do approved trueend

上述のように、各クラスに対して基本ファクトリーとそれを作るために必要な属性のみを定義することは良い習慣と言えます。 次に、この基本的な親を継承する、より具体的なファクトリーを作成します。 ファクトリーの定義はコードなので、DRY に保つこと。

Associations

ファクトリー内に関連付けを設定することが可能です。 ファクトリー名がアソシエーション名と同じ場合は、ファクトリー名を省くことができます。

factory :post do # ... authorend

別のファクトリーやオーバーライド属性を指定することもできます。

factory :post do # ... association :author, factory: :user, last_name: "Writely"end

親オブジェクトに使用される構築戦略によって、アソシエーションメソッドの動作は変化します。

関連付けられたオブジェクトを保存しない場合は、ファクトリーに strategy: :build を指定します。

strategy: :buildオプションは、association への明示的な呼び出しに渡される必要があり、暗黙の関連付けでは使用できないことに注意してください:

factory :post do # ... author strategy: :build # <<< this does *not* work; causes author_id to be nil

has_many関係のデータの生成は、必要な柔軟性に応じて少し複雑になりますが、ここでは確実に関連データを生成する例です。

FactoryGirl.define do # post factory with a `belongs_to` association for the user factory :post do title "Through the Looking Glass" user end # user factory without associated posts factory :user do name "John Doe" # user_with_posts will create post data after the user has been created factory :user_with_posts do # posts_count is declared as a transient attribute and available in # attributes on the factory, as well as the callback via the evaluator transient do posts_count 5 end # the after(:create) yields two values; the user instance itself and the # evaluator, which stores all values from the factory, including transient # attributes; `create_list`'s second argument is the number of records # to create and we make sure the user is associated properly to the post after(:create) do |user, evaluator| create_list(:post, evaluator.posts_count, user: user) end end endend

これにより、次のことが可能になります。

create(:user).posts.length # 0create(:user_with_posts).posts.length # 5create(:user_with_posts, posts_count: 15).posts.length # 15

has_and_belongs_to_many リレーションのデータを生成することは、上記の has_many リレーションと非常に似ていますが、小さな変更があり、単一バージョンの属性名には単一のオブジェクトではなく、モデルの複数化した属性名にはオブジェクトの配列を渡す必要があります。

以下は、has_and_belongs_to_many を介して関連付けられた 2 つのモデルの例です。

FactoryGirl.define do # language factory with a `belongs_to` association for the profile factory :language do title "Through the Looking Glass" profile end # profile factory without associated languages factory :profile do name "John Doe" # profile_with_languages will create language data after the profile has # been created factory :profile_with_languages do # languages_count is declared as an ignored attribute and available in # attributes on the factory, as well as the callback via the evaluator transient do languages_count 5 end # the after(:create) yields two values; the profile instance itself and # the evaluator, which stores all values from the factory, including # ignored attributes; `create_list`'s second argument is the number of # records to create and we make sure the profile is associated properly # to the language after(:create) do |profile, evaluator| create_list(:language, evaluator.languages_count, profiles: ) end end endend

これにより、次のようなことが可能になります。 シーケンスは定義ブロック内でsequenceを呼び出して定義し、シーケンスの値はgenerateを呼び出して生成されます。

factory :user do email # Same as `email { generate(:email) }`end

また、特定のファクトリーでのみ使用されるインラインシーケンスを定義することもできます:

factory :user do sequence(:email) { |n| "person#{n}@example.com" }end

初期値を上書きすることもできます:

factory :user do sequence(:email, 1000) { |n| "person#{n}@example.com" }end

ブロックなしで、値は初期値から自動的に増加します:

factory :post do sequence(:position)end

シーケンスにはエイリアスも用意されています。

エイリアスを定義し、カウンターにデフォルト値(1)を使用する

factory :user do sequence(:email, aliases: ) { |n| "person#{n}@example.com" }end

値の設定:

factory :user do sequence(:email, 'a', aliases: ) { |n| "person#{n}@example.com" }end

値は、#nextメソッドをサポートしていればよいのです。

Traits

Traits は、属性をグループ化し、任意のファクトリーに適用することができます。

また、サブクラスで trait が与える個々の属性をオーバーライドできます。

また、factory_girl からインスタンスを構築するときに、シンボルのリストとして trait を渡すことができます。

Traits は関連付けでも簡単に使用できます。

Factory と異なる関連付け名を使用している場合、

Traits は他の traits 内で使用でき、その属性を混在させることが可能です。

factory :order do trait :completed do completed_at { 3.days.ago } end trait :refunded do completed refunded_at { 1.day.ago } endend

最後に、trait は一時的な属性を受け入れることができます。

コールバック

factory_girl は、いくつかのコードを注入するための 4 つのコールバックを利用可能にします:

例:

±2612> ブロック内にユーザーのインスタンスを持つことに注意してください。 これは便利です。

また、同じファクトリーに複数の種類のコールバックを定義できます:

factory :user do after(:build) { |user| do_something_to(user) } after(:create) { |user| do_something_else_to(user) }end

ファクトリーは、同じ種類のコールバックをいくつでも定義することができます。

factory :user do after(:create) { this_runs_first } after(:create) { then_this }end

create を呼び出すと、after_build と after_create の両方のコールバックが呼び出されます。

また、標準属性と同様に、子ファクトリーは親ファクトリーのコールバックを継承し、定義できます。

複数のコールバックをブロックの実行に割り当てることができます。これは、同じコードを実行するさまざまな戦略を構築する場合に便利です (すべての戦略にわたって共有されるコールバックは存在しないため)。

すべてのファクトリーのコールバックをオーバーライドするには、FactoryGirl.define ブロック内で定義します。

また、Symbol#to_proc に依存するコールバックを呼び出すこともできます。

Gem がユーザー ファクトリーを提供する場合、

FactoryGirl.define do factory :user do full_name "John Doe" sequence(:username) { |n| "user#{n}" } password "password" endend

追加属性を追加する子ファクトリーを作成する代わりに、

そのファクトリーを変更できます。

FactoryGirl.modify do factory :user do full_name "Jane Doe" date_of_birth { 21.years.ago } gender "Female" health 90 endend

ファクトリーを変更する場合、(コールバック以外の)任意の属性を変更することができます。

FactoryGirl.modify はファクトリーに対して異なる操作を行うため、FactoryGirl.define ブロックの外側で呼び出す必要があります。

注意: (シーケンスや特性ではなく) ファクトリーのみを変更でき、コールバックは通常と同じように複合します。 したがって、変更するファクトリーが after(:create) コールバックを定義している場合、after(:create) を定義しても上書きされず、最初のコールバックの後に実行されます。

Building or Creating Multiple Records

時には、一度にファクトリーの複数のインスタンスを作成または構築したいことがあります。

built_users = build_list(:user, 25)created_users = create_list(:user, 25)

これらのメソッドは、特定の量のファクトリーを構築または作成し、それらを配列として返します。各ファクトリーの属性を設定するには、通常と同じようにハッシュを渡すことができます。

twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)

build_stubbed_list は完全にスタブ化されたインスタンスを生成します。

stubbed_users = build_stubbed_list(:user, 25) # array of stubbed users

一度に2つのレコードを作成する *_pair メソッドのセットもあります。

users_attrs = attributes_for_list(:user, 25) # array of attribute hashes

Linting Factories

factory_girl は、既知のファクトリーのリンティングを可能にします:

FactoryGirl.lint

FactoryGirl.lint 各ファクトリーを作成し、作成プロセス中に発生する例外を捕捉します。 FactoryGirl::InvalidFactoryError は、作成できなかったファクトリーのために、ファクトリーのリスト (と対応する例外) とともに発生します。

Rake タスクの例:

FactoryGirl.lint を呼び出した後、レコードが作成される可能性が高いので、データベースをクリアしたいと思うかもしれません。 上記の提供された例では、データベースをクリアするために database_cleaner gem を使用しています。

lint させたいファクトリーだけを渡すことで、選択的にファクトリーを lint できます。 このオプションは、ファクトリーの各トレイトがそれ自身で有効なオブジェクトを生成することを確認します。これは、lint メソッドに traits: true を渡すことで有効になります:

FactoryGirl.lint traits: true

これは他の引数と組み合わせることもできます:

FactoryGirl.lint factories_to_lint, traits: true

linting に使用する戦略も指定することができます。

FactoryGirl.lint strategy: :build

Custom Construction

いくつかの属性が initialize に渡されるオブジェクトを構築するために factory_girl を使用したい場合、または構築クラスで単に new を呼び出す以外のことを行いたい場合、ファクトリーに initialize_with を定義してデフォルト動作をオーバーライドすることが可能です。 例:

factory_girl は ActiveRecord で動作するように書かれていますが、任意の Ruby クラスで動作させることも可能です。 ActiveRecord との互換性を最大化するために、デフォルトのイニシャライザは、引数なしでビルド・クラス上で new を呼び出してすべてのインスタンスをビルドします。 そして、属性ライター・メソッドを呼び出して、すべての属性値を割り当てます。 これは ActiveRecord ではうまくいくのですが、実は他のほとんどの Ruby クラスではうまくいきません。

イニシャライザをオーバーライドすることができます。

  • 引数を必要とする ActiveRecord 以外のオブジェクトを initialize
  • インスタンスを生成するのに new 以外のメソッドを使用する
  • インスタンスを生成した後に装飾するといったおかしなことをする

initialize_with を使う場合、クラス自体を new で宣言しなくてもよいです。 しかし、呼び出したい他のクラス・メソッドは明示的にクラス上で呼び出されなければならない。

例:

factory :user do name "John Doe" initialize_with { User.build_with_name(name) }end

また、attributes を呼び出すことにより、initialize_with ブロック内のすべてのパブリック属性にアクセスできます:

factory :user do transient do 5 end name "John Doe" initialize_with { new(attributes) }end

これにより、new に渡されるすべての属性のハッシュが構築されます。 これは一時的な属性を含みませんが、ファクトリーで定義された他のすべての属性が渡されます (関連付け、評価済みシーケンス、など)。)

FactoryGirl.define ブロックに含めることにより、すべてのファクトリーで initialize_with を定義できます。

FactoryGirl.define do initialize_with { new("Awesome first argument") }end

initialize_withブロックを使用すると、initialize_with ブロック内からアクセスされる属性はコンストラクターでのみ割り当てられます。

カスタム戦略

カスタムの構築戦略を追加することによって factory_girl の動作を拡張したい場合があるかもしれません。 associationとresultです。 associationはFactoryGirl::FactoryRunnerインスタンスを受け取り、必要に応じてrunを呼び出し、戦略をオーバーライドすることができます。 2番目のメソッドであるresultはFactoryGirl::Evaluationインスタンスを受け取る。 (notify による) コールバックのトリガー、object または hash (factory で定義された属性に基づく結果インスタンスまたはハッシュを取得)、および create は factory で定義された to_create コールバックを実行します。

factory_girl によるストラテジの内部での使用方法を理解するには、おそらく 4 つのデフォルトストラテジのそれぞれのソースだけを見ることが最も簡単でしょう。

以下は、モデルの JSON 表現を構築するためにFactoryGirl::Strategy::Createを使用してストラテジーを構成する例です。

Factory_girl が新しいストラテジーを認識できるように、それを登録します。

FactoryGirl.register_strategy(:json, JsonStrategy)

これにより、

FactoryGirl.json(:user)

最後に、必要であれば、ストラテジーに代わる新しいオブジェクトを登録して、factory_girl 自身のストラテジーを上書きすることができます。

オブジェクトを永続化するカスタム メソッド

デフォルトでは、レコードを作成すると、インスタンスの save! が呼び出されますが、これは常に理想的とは言えないので、ファクトリーの to_create で定義することによりその動作をオーバーライドできます。

factory :user_without_database do skip_createend

すべてのファクトリーで to_create をオーバーライドするには、FactoryGirl.define ブロック内で定義します:

FactoryGirl.define do to_create { |instance| instance.persist! } factory :user do name "John Doe" endend

ActiveSupport Instrumentation

どのファクトリーが作成され、どの構築戦略で実行するかを追跡するために、ActiveSupport::Notifications は実行中のファクトリーを購読する方法を提供します。 1358>

もう 1 つの例は、すべてのファクトリーと、それらがテスト スイート全体でどのように使用されるかを追跡することです。 RSpec を使用している場合は、before(:suite) と after(:suite) を追加するだけです。

Rails プリローダーと RSpec

spring や zeus などの Rails プリローダーで RSpec を実行すると、以下のように関連付きのファクトリーを作成するときに ActiveRecord::AssociationTypeMismatch エラーに遭遇する可能性があります。

テスト スイートの実行中にエラーが発生します。

可能な解決策は、プリローダーなしでスイートを実行するか、次のように RSpec 設定に FactoryGirl.reload を追加するかの 2 つです。

RSpec.configure do |config| config.before(:suite) { FactoryGirl.reload }end

Bundler なしで使用する場合

Bundler を使用していない場合は、gem がインストールされていることを確認し、次のように呼び出します:

require 'factory_girl'

必要に応じて、spec/factories または test/factories のディレクトリ構造を持っているとすると、

FactoryGirl.find_definitions

Factory に別のディレクトリ構造を使っているなら、定義ファイルパスを変更してから定義を探そうとします。

FactoryGirl.definition_file_paths = %w(custom_factories_directory)FactoryGirl.find_definitions

ファクトリーの個別のディレクトリがなく、インラインで定義したい場合、それも可能です。

コメントを残す コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

最近の投稿

  • アセラ復活。 NYCまたはボストンで99ドル
  • OMIM Entry – # 608363 – CHROMOSOME 22q11.2 DUPLICATION SYNDROME
  • Kate Albrecht’s Parents – Learn More About Her Father Chris Albrecht And Mother Annie Albrecht
  • テンプル・フォーク・アウトフィッターズ
  • Burr(小説)

アーカイブ

  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • DeutschDeutsch
  • NederlandsNederlands
  • SvenskaSvenska
  • DanskDansk
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • RomânăRomână
  • PolskiPolski
  • ČeštinaČeština
  • MagyarMagyar
  • SuomiSuomi
  • 日本語日本語
©2022 CDhistory | Powered by WordPress & Superb Themes