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.