首页 > 解决方案 > FactoryBot 的随机特征

问题描述

我想使用 FactoryBot 像这样随机返回特征:

FactoryBot.define do
  factory :user do

    [:active, inactive].sample

    trait :active do
      active { true }
      ...
    end
    trait :inactive do
      active { false }
      ...
    end
  end
end

要做到这一点:

(1..5).map{ |e| FactoryBot.build(:user) }.map(&:active?)
=> [true, false, false, true, false]

其实是这样的:

FactoryBot.define do
  factory :user do
    active                    { [true, false].Sample }
    name                      { "name-#{SecureRandom.uuid}" }
    birthday                  { active == true ? rand(18..99).years.ago - rand(0..365).days.ago : nil }
    preferred_contact_method  { active == true ? %w(phone email).sample : nil }
    activated_at              { active == true ? rand(1..200).days.ago : nil }
    contact_phone_number      { preferred_contact_method == "phone" ? "+33XXXXXXXXX" : nil }
    contact_email             { preferred_contact_method == "email" ? "toto@tati.com" : nil }
  end
end

有可能这样做吗?

标签: rubyfactory-bot

解决方案


这是一个相当古老的问题,但与 OP 有相同的需求,我想我找到了解决方案,唉,它并不漂亮:

FactoryBot.define do
  factory :user do
    active { nil }

    initialize_with do
      if active.nil?
        build :user, %i[active inactive].sample, attributes
      else
        User.new(attributes)
      end
    end
    
    trait :active do
      active { true }
      ...
    end
    trait :inactive do
      active { false }
      ...
    end
  end
end

FactoryBot.create_list(:user, 5).map(&:active) #=> random array of booleans
FactoryBot.create_list(:user, 5, :active).all?(&:active?) #=> true

推荐阅读