31

プロジェクト ファクトリがある場合

Factory.define :project do |p|
  p.sequence(:title)    { |n| "project #{n} title"                  }
  p.sequence(:subtitle) { |n| "project #{n} subtitle"               }
  p.sequence(:image)    { |n| "../images/content/projects/#{n}.jpg" }
  p.sequence(:date)     { |n| n.weeks.ago.to_date                   }
end

そして、私はプロジェクトのインスタンスを作成しています

Factory.build :project
Factory.build :project

この時点で、次に Factory.build(:project) を実行すると、タイトルが「プロジェクト 3 タイトル」などに設定された Project のインスタンスを受け取ります。驚かない。

ここで、このスコープ内でカウンターをリセットしたいとします。何かのようなもの:

Factory.build :project #=> Project 3
Factory.reset :project #=> project factory counter gets reseted
Factory.build :project #=> A new instance of project 1

これを達成するための最良の方法は何ですか?

現在、次のバージョンを使用しています。

factory_girl (1.3.1) factory_girl_rails (1.0)

4

9 に答える 9

44

前後のコールバックで FactoryGirl.reload を呼び出すだけです。これは、FactoryGirl コードベースで次のように定義されています。

module FactoryGirl
  def self.reload
    self.factories.clear
    self.sequences.clear
    self.traits.clear
    self.find_definitions
  end
end

FactoryGirl.sequences.clear を呼び出すだけでは、何らかの理由で十分ではありません。完全なリロードを実行するとオーバーヘッドが発生する可能性がありますが、コールバックを使用して/使用せずに試したところ、テストの実行にはどちらの方法でも約 30 秒かかりました。したがって、ワークフローに影響を与えるほどのオーバーヘッドはありません。

于 2011-12-09T17:34:15.500 に答える
12

ソースコードをたどった後、最終的にこれに対する解決策を思いつきました。factory_girl 1.3.2 (これを書いている時点での最新リリース) を使用している場合は、factory.rb ファイルの先頭に次のコードを追加できます。

class Factory  
  def self.reset_sequences
    Factory.factories.each do |name, factory|
      factory.sequences.each do |name, sequence|
        sequence.reset
      end
    end
  end
  
  def sequences
    @sequences
  end
  
  def sequence(name, &block)
    s = Sequence.new(&block)
    
    @sequences ||= {}
    @sequences[name] = s
    
    add_attribute(name) { s.next }
  end
  
  def reset_sequence(name)
    @sequences[name].reset
  end
  
  class Sequence
    def reset
      @value = 0
    end
  end
end

次に、Cucumber の env.rb に以下を追加します。

After do
  Factory.reset_sequences
end

rspec テストで同じ問題に遭遇した場合、:each メソッドの後に rspecs を使用できると思います。

現時点では、このアプローチでは、次のようなファクトリ内で定義されたシーケンスのみが考慮されます。

Factory.define :specialty do |f|
  f.sequence(:title) { |n| "Test Specialty #{n}"}
  f.sequence(:permalink) { |n| "permalink#{n}" }
end

処理するコードをまだ作成していません: Factory.sequence...

于 2011-01-07T06:32:15.313 に答える
9

グーグルの人々のために:それ以上拡張せずに、ただFactoryGirl.reload

FactoryGirl.create :user
#=> User id: 1, name: "user_1"
FactoryGirl.create :user
#=> User id: 2, name: "user_2"

DatabaseCleaner.clean_with :truncation #wiping out database with truncation
FactoryGirl.reload

FactoryGirl.create :user
#=> User id: 1, name: "user_1"

私のために働く

* factory_girl (4.3.0)
* factory_girl_rails (4.3.0)

https://stackoverflow.com/a/16048658

于 2014-02-03T10:12:56.230 に答える
5

ThoughBot Hereによると、テスト間のシーケンスをリセットする必要性はアンチパターンです。

夏に向けて

あなたがこのようなものを持っているなら:

FactoryGirl.define do
  factory :category do
    sequence(:name) {|n| "Category #{n}" }
  end
end

テストは次のようになります。

Scenario: Create a post under a category
   Given a category exists with a name of "My Category"
   And I am signed in as an admin
   When I go to create a new post
   And I select "My Category" from "Categories"
   And I press "Create"
   And I go to view all posts
   Then I should see a post with the category "My Category"

これではない:

Scenario: Create a post under a category
  Given a category exists
  And I am signed in as an admin
  When I go to create a new post
  And I select "Category 1" from "Categories"
  And I press "Create"
  And I go to view all posts
  Then I should see a post with the category "Category 1"
于 2011-11-02T05:52:00.333 に答える
1

シーケンスをリセットする組み込みの方法はありません。ソース コードは次のとおりです。

http://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/sequence.rb

ただし、一部の人々はこの機能をハッキング/モンキー パッチで修正しました。以下に例を示します。

http://www.pmamediagroup.com/2009/05/smarter-sequencing-in-factory-girl/

于 2010-07-29T16:31:21.253 に答える
0

特定のシーケンスをリセットするには、試すことができます

# spec/factories/schedule_positions.rb
FactoryGirl.define do
  sequence :position do |n| 
    n
  end

  factory :schedule_position do
    position
    position_date Date.today
    ...
  end
end

# spec/models/schedule_position.rb
require 'spec_helper'

describe SchedulePosition do
  describe "Reposition" do
    before(:each) do
      nullify_position
      FactoryGirl.create_list(:schedule_position, 10)
    end
  end

  protected

  def nullify_position
    position = FactoryGirl.sequences.find(:position)
    position.instance_variable_set :@value, FactoryGirl::Sequence::EnumeratorAdapter.new(1)
  end
end
于 2014-07-02T10:28:02.907 に答える