Faker створює повторювані дані, коли використовується у factory_girl


86

Я намагаюся заповнити деякі фальшиві дані на заводі, використовуючи самоцвіт Faker:

Factory.define :user do |user|
  user.first_name Faker::Name::first_name
  user.last_name Faker::Name::last_name
  user.sequence(:email) {|n| "user#{n}@blow.com" }
end

Однак, хоча я очікую, що це призведе до користувачів, які мають різні імена та прізвища, кожен з них однаковий:

>> Factory(:user)
=> #<User id: 16, email: "user7@blow.com", created_at: "2011-03-18 18:29:33",     
updated_at: "2011-03-18 18:29:33", first_name: "Bailey", last_name: "Durgan">
>> Factory(:user)
=> #<User id: 17, email: "user8@blow.com", created_at: "2011-03-18 18:29:39", 
updated_at: "2011-03-18 18:29:39", first_name: "Bailey", last_name: "Durgan">

Як я можу отримати дорогоцінний камінь Faker для створення нових імен для кожного користувача, а не просто повторного використання оригінальних?


1
Просто постріл у темряві, але чи пробували ви щось подібне user.sequence(:first_name} {|n| Faker::Name::first_name}? FactoryGirl, швидше за все, просто оцінює ваш дзвінок Faker, коли він завантажує ваші "світильники". Використання sequence param,&blockметоду повинно запобігти цьому.
— Стівен

Відповіді:


156
Factory.define :user do |user|
  user.first_name { Faker::Name::first_name }
  user.last_name { Faker::Name::last_name }
  user.sequence(:email) {|n| "user#{n}@blow.com" }
end

Спробуйте поставити дужки навколо фальшивок. дивіться це посилання


8
Я так люблю stackoverflow - дякую Тобі, ти врятував мій бекон
— Пітер Ніксі

Дякую, це вирішило мою проблему!
— Апельсини13

5
Чому, чому, чому? Що тут відбувається?
— jordanpg

4
через "ледачий атрибут", див .: github.com/thoughtbot/factory_girl/blob/master/…
— Siwei Shen,

9
На жаль, це не завжди працює. Це в основному просто отримує новий випадковий фальшивий об'єкт, однак через RNG все ще існує ймовірність, що це не вдасться.
— Michael Lynch

45

Зверніть увагу, що Faker все ще може надавати дублікати даних через обмежену кількість підроблених даних.

Для простих цілей тестування та для перевірки унікальності я використовував наступне:

sequence(:first_name) {|n| Faker::Name::first_name + " (#{n})"}
sequence(:last_name) {|n| Faker::Name::last_name + " (#{n})"}

3
Ця відповідь заслуговує на більшу підтримку. Можливо, це станеться, коли ваш тест створить багато примірників.
— Енріко Карлессо

Так, я погоджуюсь з Енріко. +1
— karlingen

Приємна ідея, але додавання дужок може порушити решту, якщо ви використовуєте ім’я та прізвище для створення електронних листів, або у вас є перевірки формату (невідомо жодної назви, що має дужки: P).
— Кирило Дюшон-Доріс

18

Задля збереження правильної відповіді, тут вона перенесена з блогу, я не вважаю за відповідь відповідальною.

Якщо ви використовуєте наведений нижче код, факер не видасть унікальні імена

Factory.define :user do |u|
  u.first_name Faker::Name.first_name
  u.last_name Faker::Name.last_name
end

Однак накладання фігурних дужок навколо факера змушує це працювати!

Factory.define :user do |u|
  u.first_name { Faker::Name.first_name }
  u.last_name { Faker::Name.last_name }
end

Щоб пояснити, чому, перший приклад дає однакові назви. Це оцінюється лише один раз. Другий приклад оцінює кожен раз, коли використовується фабрика.

Це пов’язано з {}наданням ледачої оцінки. По суті, вони надають proc / lambda із викликом Faker як своє повернене значення.


Дякуємо, що розмістили це. Я не міг зрозуміти, чому Faker не зміг генерувати випадкові дані, і, здавалося, кожен приклад, з яким я зіткнувся, показав, як використовувати послідовність, яка здалася мені дивною. Я хотів використовувати Faker, щоб кожен запис був випадковим, а не послідовним. Просто додавання фігурних дужок навколо моїх викликів Faker вирішило проблему. Просто і елегантно!
— Blimey85

5

(Менш ефективною) альтернативою використанню послідовностей, коли у вас є перевірка унікальності атрибута, є перевірка, чи вже існує запропоноване значення, і продовжуйте пробувати нові, поки воно не стане унікальним:

FactoryGirl.define do
  factory :company do
    name do
      loop do
        possible_name = Faker::Company.name
        break possible_name unless Company.exists?(name: possible_name)
      end
    end
  end
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.