Этот мини-сериал, состоящий из двух частей, был написан для людей, которые хотят начать работать с Factory Girl и начать поиск, не слишком много копаясь в документации для себя. Для людей, которые начали играть с тестами сравнительно недавно, я приложил все усилия, чтобы они были удобны для начинающих
Очевидно, что в какой-то момент я был в одной и той же обуви и заставил меня поверить, что совсем не нужно, чтобы новые люди чувствовали себя более комфортно при тестировании. Потратив немного больше времени на объяснение контекста и демистификацию жаргона, вы значительно снизили уровень разочарования у начинающих.
содержание
- Введение и контекст
- арматура
- конфигурация
- Определение фабрик
- Используя фабрики
- наследование
- Несколько записей
- Последовательности
Введение и контекст
Давайте начнем с небольшой истории и поговорим о замечательных людях в mindbot , которые отвечают за этот популярный драгоценный камень Ruby. Еще в 2007/2008 году Джо Феррис , технический директор Thinkbot, взял его со светильниками и начал готовить собственное решение. Просмотр различных файлов для тестирования одного метода был обычной проблемой при работе со светильниками. Иными словами, игнорируя всевозможные негибкости, эта практика также приводит к написанию тестов, которые мало что говорят о том, что их контекст проверяется сразу.
Из-за того, что эта практика не была продана, он проверял различные решения для фабрик, но никто из них не поддерживал все, что он хотел. Поэтому он придумал Factory Girl, которая сделала тестирование с тестовыми данными более читабельными, DRY, а также более четким, предоставив вам контекст для каждого теста. Пару лет спустя Джош Клэйтон , директор по развитию Thinkbot в Бостоне, занял пост руководителя проекта. Со временем этот камень неуклонно рос и стал «приспособлением» в сообществе Ruby.
Давайте поговорим подробнее об основных болевых точках, которые решает Factory Girl. Когда вы создаете свой набор тестов, вы имеете дело со множеством связанных записей и информацией, которая часто меняется. Вы хотите иметь возможность создавать наборы данных для интеграционных тестов, которые не являются хрупкими, простыми в управлении и явными. Ваши фабрики данных должны быть динамичными и иметь возможность ссылаться на другие фабрики — что-то, что частично выходит за рамки YAML со старых времен.
Еще одно удобство, которое вы хотите иметь, — это возможность перезаписывать атрибуты для объектов на лету. Factory Girl позволяет вам делать все это без особых усилий — учитывая тот факт, что он написан на Ruby, и много колдовства метапрограммирования происходит за кулисами — и вам предоставляется отличный предметно-ориентированный язык, который прост на глаз тоже.
Сбор данных вашего прибора с помощью этого драгоценного камня можно описать как простой, эффективный и в целом более удобный, чем возиться с приборами. Таким образом, вы можете иметь дело больше с понятиями, чем с реальными столбцами в базе данных. Но хватит говорить о разговоре, давайте немного запачкаем руки.
Светильники?
Люди, которые имеют опыт тестирования приложений и которым не нужно изучать концепцию приборов, пожалуйста, не стесняйтесь переходить прямо к следующему разделу. Это для новичков, которые просто нуждаются в обновлении о тестировании данных.
Светильники — это образцы данных — вот и все! Для хорошей части вашего набора тестов вы хотите иметь возможность заполнить тестовую базу данных данными, адаптированными к вашим конкретным тестовым примерам. В течение долгого времени многие разработчики использовали YAML для этих данных, что делало их независимыми от базы данных. Оглядываясь в прошлое, быть независимым таким образом, возможно, было лучшим в этом. Это был более или менее один файл на модель. Уже одно это может дать вам представление о всевозможных головных болях, на которые люди жаловались. Сложность — быстро растущий враг, которого YAML вряд ли сможет эффективно преодолеть. Ниже вы увидите, как .yml
такой файл .yml
с тестовыми данными.
YAML-файл: secret_service.yml
« `Обычный интендант: имя: Q любимый гаджет: навыки радио веника: изобретать вещицы и взламывать
00 Агент: имя: Джеймс Бонд fav_gadget: Подводная лодка Lotus Esprit Навыки: получение Бонда Девушки убиты и скрытое проникновение « `
Это похоже на хэш, не так ли? Это разделенный двоеточиями список пар ключ / значение, разделенных пробелом. Вы можете ссылаться на другие узлы внутри друг друга, если вы хотите смоделировать ассоциации из ваших моделей. Но я думаю, что будет справедливо сказать, что на этом музыка останавливается, и многие говорят, что их боль начинается. Для наборов данных, которые немного более сложны, приборы YAML сложно обслуживать и их трудно изменить, не затрагивая другие тесты. Конечно, вы можете заставить их работать — в конце концов, разработчики использовали их много в прошлом — но многие согласились, что цена за управление приборами была слишком высокой.
Чтобы избежать нарушения ваших тестовых данных, когда происходят неизбежные изменения, разработчики были рады принять более новые стратегии, которые предлагали больше гибкости и динамического поведения. Вот где Фабричная Девушка пришла и оставила дни YAML позади. Другой проблемой является сильная зависимость между тестом и .yml
. Тайные гости также являются основной болью с этими видами приспособлений. Factory Girl позволяет избежать этого, создавая объекты, соответствующие встроенным тестам.
Несомненно, устройства YAML работают быстро, и я слышал, что люди утверждают, что медленный набор тестов с данными Factory Girl заставил их вернуться на землю YAML. На мой взгляд, если вы используете Factory Girl так сильно, что это действительно замедляет ваши тесты, вы можете излишне злоупотреблять фабриками и игнорировать стратегии, которые не затрагивают базу данных. Вы увидите, что я имею в виду, когда перейдем к соответствующему разделу (ам). Конечно, используйте все, что вам нужно, но считайте, что вас предупредили, если вы сгорели от YAML.
Я думаю, было бы справедливо добавить, что на заре Rails и Ruby TDD светильники YAML были де-факто стандартом для настройки тестовых данных в вашем приложении. Они сыграли важную роль и помогли продвинуть отрасль вперед. В настоящее время у них довольно плохая репутация. Времена меняются, поэтому давайте перейдем к фабрикам, которые предназначены для замены светильников.
конфигурация
Я предполагаю, что в вашей системе уже установлены Ruby и RSpec для тестирования. Если нет, вернитесь после консультации с Google, и у вас все получится. Это довольно просто, я бы сказал. Вы можете установить гем вручную в свой терминал через Shell:
bash gem install factory_girl
или добавьте его в свой Gemfile:
ruby gem "factory_girl", "~> 4.0"
и запустите bundle install
.
Теперь вам нужно только потребовать, чтобы Factory Girl завершила настройку. Здесь я использую RSpec, поэтому добавьте следующее вверху в /spec/spec_helper.rb
:
ruby require 'factory_girl'
Рубин на рельсах
Вы, конечно, застрахованы, если хотите использовать Factory Girl with Rails. Драгоценный камень factory_girl_rails
обеспечивает удобную интеграцию с Rails для factory_girl
.
Ракушка:
bash gem install factory_girl_rails
Gemfile:
ruby gem "factory_girl_rails", "~> 4.0"
и, конечно, require
это в spec/spec_helper.rb
:
ruby require 'factory_girl_rails'
Удобная настройка синтаксиса
Если вы предпочитаете вводить что-то вроде (конечно, вы делаете)
Рубин:
ruby create(:user)
вместо того
ruby FactoryGirl.create(:user)
каждый раз, когда вы используете одну из своих фабрик, вам просто нужно включить FactoryGirl::Syntax::Methods
в ваш тестовый конфигурационный файл. Если вы забудете этот шаг, вы должны предварять все методы Factory Girl тем же подробным предисловием. Это работает с любым приложением Ruby, не только с Rails, конечно.
Для RSpec найдите файл spec/spec_helper.rb
и добавьте:
« `ruby require ‘factory_girl_rails’
RSpec.configure do | config | config.include FactoryGirl :: Syntax :: Методы end « `
Внимание!
Для новичков среди вас, имейте в RSpec.configure
блок RSpec.configure
уже будет там — похоронен под некоторым количеством комментариев. Вы также можете выполнить ту же настройку в отдельном файле — например, spec/support/factory_girl.rb
. В этом случае вам, конечно, придется добавить весь блок конфигурации.
Та же конфигурация работает, если вы используете для тестирования другие библиотеки:
- Test :: Unit
- Огурец
- Шпинат
- MiniTest
- MiniTest :: Spec
- MiniTest рельсы
Например, вы можете улучшить свою конфигурацию, добавив DatabaseCleaner
, но документация подразумевает, что этой настройки достаточно для начала работы, поэтому я перейду дальше.
Определяющие фабрики
Вы можете определить свои фабрики где угодно, но они будут загружены автоматически, если они размещены в следующих местах:
RSpec:
bash spec/factories.rb spec/factories/*.rb
Test :: Unit:
bash test/factories.rb test/factories/*.rb
Как видите, у вас есть возможность разделить их на отдельные файлы, которые придерживаются какой-либо логики, или объединить ваши фабрики в один большой файл factory.rb. Сложность вашего проекта будет лучшим руководством для того, когда логически разделять фабрики в их отдельные файлы.
Обнаженные фабрики
Factory Girl предоставляет хорошо разработанный синтаксис ruby DSL для определения фабрик, таких как пользователь , публикация или любой другой объект, а не только объекты Active Record . «Обычные» классы Ruby прекрасно подходят. Вы начинаете с установки определенного блока в вашем файле factories.rb.
Рубин:
« `ruby FactoryGirl.define do
конец « `
Все фабрики определены внутри этого блока. Фабрикам просто нужно :symbol
имя :symbol
и набор атрибутов, чтобы начать. Это имя должно быть версией Snake_cased модели, которую вы хотите эмулировать, например SecretServiceAgent в следующем примере. Фабрика ниже называется secret_service_agent
и имеет атрибуты с именем name
, favorite_gadget
и skills
.
Рубин:
« `ruby FactoryGirl.define do
фабрика: secret_service_agent сделать имя «Q» fav_gadget «Подводная лодка Lotus Esprit» умение «Изобретать вещицы и взламывать» конец
конец « `
Внимание!
Если вы возьмете одну вещь из этой статьи, то это должно быть следующим: Определите только максимально возможную фабрику, чтобы она была действительна по умолчанию — допустима в смысле валидации Active Record, например.
Когда Factory Girl звонит, save!
в некоторых случаях ваши проверки будут выполняться. Если какой-либо из них завершится неудачно, ActiveRecord::RecordInvalid
будет ActiveRecord::RecordInvalid
Определение только минимума дает вам большую гибкость, если ваши данные изменятся, и уменьшит шансы взломать тесты и дублирование, поскольку связывание сводится к ядру. Не ленитесь, когда создаете свои фабрики — это окупится!
Если вы думаете, что это звучит сложно, вы, скорее всего, будете рады услышать, что существуют удобные решения для разделения объектов и их атрибутов. Наследование и Черты станут хорошими союзниками, так как они являются удобными стратегиями, дополняющими ваши голые заводы и сохраняющими их СУХОЙ в то же время. Узнайте больше о наследовании ниже, и моя вторая статья будет посвящена чертам.
Использование Фабрики
Если вы включили FactoryGirl::Syntax::Methods
на этапе настройки, вы можете использовать сокращенный синтаксис для создания фабрик в своих тестах. У вас есть четыре варианта, которые люди называют стратегиями построения :
Создайте
ruby create(:some_object) # FactoryGirl.create(:some_object)
Этот возвращает экземпляр класса, который эмулирует фабрика. Рекомендуется использовать create
только тогда, когда вам действительно нужно попасть в базу данных. Эта стратегия замедляет ваш набор тестов, если чрезмерно используется. Используйте его, если вы хотите запустить свои проверки, так как он запустит save!
на заднем фоне. Я думаю, что этот вариант в основном подходит, когда вы проводите интеграционные тесты, в которых вы хотите задействовать базу данных для ваших тестовых сценариев.
строить
ruby build(:some_object) # FactoryGirl.build(:some_object)
Он создает и присваивает атрибуты, но вы получите возвращенный экземпляр, который не сохранен в базе данных — build
сохраняет объект только в памяти. Если вы хотите проверить, имеет ли объект определенные атрибуты, это сработает, поскольку вам не нужен доступ к базе данных для такого рода вещей. За кулисами не используется save!
, что означает, что ваши проверки не запускаются.
Берегись!
Когда вы используете ассоциации с ним, вы можете столкнуться с небольшой ошибкой. Есть небольшое исключение в отношении того, чтобы не сохранять объект посредством build
— он строит объект, но создает ассоциации — о которых я расскажу в разделе об ассоциациях Factory Girl. Для этого есть решение на тот случай, если вы не для этого покупали.
build_stubbed
ruby build_stubbed(:some_object) # FactoryGirl.build_stubbed(:some_object)
Эта опция была создана для ускорения ваших тестов и для тестовых случаев, когда ни один код не должен попадать в базу данных. Он также создает и присваивает атрибуты, как это делает build
, но при этом объекты выглядят так, как будто они были сохранены. Возвращенный объект имеет все определенные атрибуты из вашей фабрики, а также фальшивый id
и nil
метки времени. Их ассоциации также исключены — в отличие от ассоциативных ассоциаций, которые используют create
для связанных объектов. Поскольку эта стратегия имеет дело с заглушками и не зависит от базы данных, эти тесты будут такими же быстрыми, как и они.
attributes_for
Этот метод возвращает хэш только атрибутов, определенных в соответствующей фабрике — без ассоциаций, временных отметок и, конечно, идентификатора. Это удобно, если вы хотите создать экземпляр объекта без ручного манипулирования хешами атрибутов. Я видел это в основном используется в спецификациях контроллера, как это:
Рубин:
« `ruby it ‘перенаправляет в какое-то место’ do post: create, spy: attribute_for (: spy)
Ожидайте (ответ) .to redirect_to (some_location) end « `
Сравнение объектов
Чтобы закрыть этот раздел, позвольте мне привести один простой пример, чтобы увидеть различные объекты, возвращаемые из этих четырех стратегий сборки. Ниже вы можете сравнить четыре различных объекта, которые вы получите от attributes_for
, create
, build
и build_stubbed
:
« `ruby FactoryGirl.define do
Фабрика: шпион называет «Марти Макспи». fav_gadget навыки «Ховерборд», конец «Проникновение и шпионаж».
конец « `
« `ruby attribute_for (: шпион)
возвращаемый объект
« `
« `ruby create (: шпион)
возвращаемый объект
<Идентификатор шпиона: 1, имя: «Марти Макспи», любимый гаджет: «Ховерборд», навыки: «Проникновение и шпионаж», созданный: «2015-10-17 16:40:09», обновленный_ат: «2015-10-17» 16:40:09 »>` «
« `ruby build (: шпион)
возвращаемый объект
<Идентификатор шпиона: ноль, имя: «Марти Макспи», любимый гаджет: «Ховерборд», навыки: «Проникновение и шпионаж», create_at: ноль, updated_at: ноль> « `
« `ruby build_stubbed (: шпион)
возвращаемый объект
<Идентификатор шпиона: 1001, имя: «Марти Макспи», любимый гаджет: «Ховерборд», навыки: «Проникновение и шпионаж», create_at: nil, updated_at: nil> « `
Я надеюсь, что это было полезно, если у вас все еще есть некоторая путаница относительно того, как они работают и когда использовать какую опцию.
наследование
Тебе понравится этот! С помощью наследования вы можете определять фабрики только с теми атрибутами, которые нужны каждому классу для создания. Эта родительская фабрика может порождать столько «дочерних» фабрик, сколько вы считаете нужным, чтобы охватить все виды тестовых сценариев с различными наборами данных. Хранение данных теста DRY очень важно, а наследование делает это намного проще для вас.
Скажем, вы хотите определить пару основных атрибутов на фабрике, и в пределах одной и той же фабрики есть разные фабрики для одного и того же класса с разными атрибутами. В приведенном ниже примере вы можете увидеть, как избежать повторения атрибутов, просто вложив свои фабрики. Давайте подражаем классу Spy, который должен адаптироваться к трем различным сценариям тестирования.
factories.rb
« `ruby FactoryGirl.define do
Фабрика: шпион зовут «Марти Макспи» licence_to_kill ложные навыки «Шпионаж и интеллект»
фабрика: квартирмейстер до имя "Q" навыки «Изобретая вещиц и взлом» конец фабрика: облигация до имя "Джеймс Бонд" licence_to_kill true конец конец
конец « `
some_spec.rb
« `ruby bond = создать (: облигация) quarmaster = создать (: квартмейстер)
quarmaster.name # => ‘Q’ quarmaster.skills # => ‘Изобретая вещицы и взламывая’ quarmaster.licence_to_kill # => false
bond.name # => ‘Джеймс Бонд’ bond.skills # => ‘Шпионаж и разведка’ bond.licence_to_kill # => true « `
Как вы можете заметить, фабрики :bond
и :quartermaster
наследуют атрибуты от своих родителей :spy
. В то же время вы можете легко перезаписывать атрибуты по мере необходимости и быть очень выразительными по отношению к ним через их фабричные имена. Представьте все сохраненные строки кода, потому что вам не нужно повторять одну и ту же базовую настройку, если вы хотите проверить разные состояния или связанные объекты. Одна эта функция стоит того, чтобы использовать Factory Girl, и она затрудняет возвращение к приборам YAML.
Если вы хотите избежать вложения определений фабрики, вы также можете явно связать фабрики с их родителями, предоставив parent
хеш:
factories.rb
« `ruby factory: имя шпиона ‘Марти Макспи’ licence_to_kill ложные навыки ‘Шпионаж и разведка’ конец
фабрика: связь, родитель:: имя шпиона ‘Джеймс Бонд’ licence_to_kill true end « `
Это та же функциональность и почти как СУХОЙ.
Несколько записей
Вот небольшое, но, тем не менее, приятное дополнение к Factory Girl, которое упрощает работу со списками:
- build_list
- create_list
Время от времени, в ситуациях, когда вы хотите иметь несколько экземпляров какой-либо фабрики без особых размышлений, они пригодятся. Оба метода вернут массив с указанным количеством фабричных элементов. Довольно аккуратно, верно?
Рубин:
« `ruby spy_clones = create_list (: spy, 3)
fake_spies = build_list (: spy, 3)
spy_clones # => [# <ID шпиона: 1, имя: «Марти Макспи», функция: «Тайный агент», навыки: «Проникновение и шпионаж», create_at: «2015-10-18 18:52:02», updated_at : «2015-10-18 18:52:02»>, # <идентификатор шпиона: 2, имя: «Марти Макспи», функция: «Тайный агент», навыки: «Проникновение и шпионаж», creat_at: «2015-10 -18 18:52:02 «, updated_at:» 2015-10-18 18:52:02 «>, # <идентификатор шпиона: 3, имя:« Марти Макспи », функция:« Тайный агент », навыки:« Проникновение » и шпионаж «, create_at:» 2015-10-18 18:52:02 «, updated_at:» 2015-10-18 18:52:02 «>]
fake_spies # => [# <ID шпиона: ноль, имя: «Марти Макспи», функция: «Тайный агент», навыки: «Проникновение и шпионаж», create_at: nil, updated_at: nil>, # <ID шпиона: nil, имя: «Марти Макспи», функция: «Тайный агент», навыки: «Проникновение и шпионаж», созданный_ат: ноль, обновленный_ат: ноль>, # <идентификатор шпиона: ноль, имя: «Марти МакСпи», функция: «Скрытый агент» «, навыки:» Проникновение и шпионаж «, create_at: nil, updated_at: nil>]` «
Между этими двумя вариантами есть тонкие различия, но я уверен, что вы уже поняли их. Я должен также упомянуть, что вы можете предоставить обоим методам хэш атрибутов, если по какой-то причине вы хотите перезаписать атрибуты фабрики на лету. Перезаписи будут снижать скорость тестирования, если вы создаете много тестовых данных с перезаписью. Возможно, для создания списков будет лучше использовать отдельную фабрику с измененными атрибутами.
« `ruby smug_spies = create_list (: шпион, 3, навыки: ‘Самодовольные шутки’)
double_agents = build_list (: шпион, 3, имя: ‘Vesper Lynd’, навыки: ‘Соблазнение и бухгалтерия’)
smug_spies # => [# <Идентификатор шпиона: 1, имя: «Марти Макспи», функция: «Тайный агент», навыки: «Шуточные шутки», create_at: «2015-10-18 19:08:07», updated_at: «2015-10-18 19:08:07»>, # <идентификатор шпиона: 2, имя: «Марти Макспи», функция: «Тайный агент», навыки: «Самодовольные шутки», create_at: «2015-10-18 19:08:07 «, updated_at:» 2015-10-18 19:08:07 «>, # <Идентификатор шпиона: 3, имя:« Марти Макспи », функция:« Тайный агент », навыки:« Самодовольные шутки » , create_at: «2015-10-18 19:08:07», updated_at: «2015-10-18 19:08:07»>]
double_agents # => [# <Идентификатор шпиона: ноль, имя: «Веспер Линд», функция: «Тайный агент», навыки: «Соблазнение и бухгалтерия», create_at: ноль, updated_at: ноль>, # <Идентификатор шпиона: ноль, имя: «Vesper Lynd», функция: «Тайный агент», навыки: «Соблазнение и бухгалтерия», create_at: nil, updated_at: nil>, # <идентификатор шпиона: nil, имя: «Vesper Lynd», функция: «Тайный агент «, навыки:» Соблазнение и бухгалтерия «, create_at: nil, updated_at: nil>]` «
Вам часто понадобится пара объектов, поэтому Factory Girl предоставляет вам еще два варианта:
- build_pair
- create_pair
Это та же идея, что и выше, но возвращаемый массив содержит только две записи одновременно.
« `ruby create_pair (: spy) # => [# <ID шпиона: 1, имя:« Марти Макспи », функция:« Тайный агент », навыки:« Проникновение и шпионаж », create_at:« 2015-10-18 19:31:41 «, updated_at:» 2015-10-18 19:31:41 «>, # <идентификатор шпиона: 2, имя:« Марти Макспи », функция:« Тайный агент », навыки:« Проникновение и шпионаж » «, create_at:» 2015-10-18 19:31:41 «, updated_at:» 2015-10-18 19:31:41 «>]
build_pair (: spy) # => [# <ID шпиона: ноль, имя: «Марти Макспи», функция: «Тайный агент», навыки: «Проникновение и шпионаж», create_at: nil, updated_at: nil>, # <Spy id: nil, имя: «Marty McSpy», функция: «Тайный агент», навыки: «Проникновение и шпионаж», create_at: nil, updated_at: nil>] « `
Последовательности
Если вы думаете, что именование шпионов может быть менее статичным, вы абсолютно правы. В этом последнем разделе мы рассмотрим создание последовательных уникальных значений в качестве тестовых данных для ваших фабричных атрибутов.
Когда это может быть полезно? Как насчет уникальных адресов электронной почты для проверки подлинности или уникальных имен пользователей, например? Вот где последовательности сияют. Давайте рассмотрим несколько разных способов использования sequence
:
«Глобальная» последовательность
« `ruby FactoryGirl.define do
последовательность: spy_email do | n | Конец «00#ndomn‹@mi6.com»
Фабрика: шпион называет «Марти Макспи» электронная почта «[email protected]» навыки «Шпионаж и проникновение» license_to_kill false
фабрика: elite_spy do имя "Эдвард Донн" license_to_kill true конец конец
конец
top_spy = create (: elite_spy) top_spy.email = generate (: spy_email)
top_spy.email # => «[email protected]» « `
Поскольку эта последовательность определена «глобально» для всех ваших фабрик — она не принадлежит ни одной конкретной фабрике — вы можете использовать этот генератор последовательности для всех ваших фабрик, где бы вам ни понадобился :spy_email
. Все, что вам нужно, это generate
и имя вашей последовательности.
Атрибуты
В качестве небольшого варианта, который очень удобен, я покажу вам, как напрямую назначать последовательности в качестве атрибутов для ваших фабрик. Используйте то же условие, что и выше, где ваша последовательность определена «глобально». В случае определения фабрики вы можете отключить вызов метода generate
и Factory Girl присвоит возвращаемое значение из последовательности непосредственно атрибуту с тем же именем. Ухоженная!
« `ruby FactoryGirl.define do
последовательность: электронная почта делает | n | Конец «00#ndomn‹@mi6.com»
фабрика: secret_service_agent дайте имя «Эдвад Донн» электронной почты навыки «Шпионаж и проникновение» license_to_kill true end
конец « `
Ленивые Атрибуты
Вы также можете использовать sequence
на ленивых атрибутах . Я расскажу об этой теме во второй статье, но для полноты картины я хотел бы упомянуть и здесь. В случае, если вам нужно уникальное значение, назначенное во время создания экземпляра — оно называется ленивым, потому что этот атрибут ожидает назначения значения до создания экземпляра объекта — последовательности просто нуждаются в блоке, чтобы также работать.
« `ruby
FactoryGirl.define сделать
последовательность: mission_deployment do | номер | «Миссия № {номер} в # {DateTime.now.to_formatted_s (: short)}» конец
factory: spy do name ‘Marty McSpy’ развертывание {генерировать (: mission_deployment)} конец
конец
some_spy = create (: spy) some_spy.deployment # => «Миссия №1 в 19 октября 21:13» « `
Блок для фабричного атрибута оценивается, когда создается объект. В нашем случае вы получите строку, состоящую из уникального номера миссии и нового объекта DateTime
качестве значений для каждого :spy
который будет развернут.
Последовательность
Этот вариант лучше всего подходит, когда последовательность уникальных значений требуется только для атрибута для одной фабрики. Не имеет смысла определять его за пределами этой фабрики и, возможно, придется искать его в другом месте, если вам нужно настроить его. В приведенном ниже примере мы ищем уникальные идентификаторы для каждого автомобиля-шпиона.
« `ruby FactoryGirl.define do
factory: aston_martin do sequence (: vehicle_id_number) {| n | «A_M _ # {n}»} конец
конец
spycar_01 = создать (: aston_martin) spycar_01.vehicle_id_number # => «A_M_1»
spycar_02 = создать (: aston_martin) spycar_02.vehicle_id_number # => «A_M_2» « `
Ну, может быть, мы должны предоставить атрибут vehicle_id_number
другое начальное значение, чем 1
? Допустим, мы хотим учесть пару прототипов до того, как автомобиль был готов к производству. Вы можете предоставить второй аргумент в качестве начального значения для вашей последовательности. Пойдем с 9
этот раз.
« `ruby FactoryGirl.define do
factory: aston_martin do sequence (: номер_порта_диска, 9) {| n | «A_M _ # {n}»} конец
конец
spycar_01 = создать (: aston_martin) spycar_01.vehicle_id_number # => «A_M_9»
spycar_02 = создать (: aston_martin) spycar_02.vehicle_id_number # => «A_M_10»
…
« `
Заключительные мысли
Как вы уже видели, Factory Girl предлагает хорошо сбалансированный Ruby DSL, который строит объекты вместо записей базы данных для ваших тестовых данных. Это помогает держать ваши тесты сфокусированными, сухими и читаемыми, когда вы работаете с фиктивными данными. Это довольно солидное достижение в моей книге.
Помните, что определения фабрики с пустыми руками являются ключом к вашему здравомыслию Чем больше заводских данных вы поместите в свое глобальное тестовое пространство, тем больше вероятность того, что вы испытаете какие-то трудности с обслуживанием.
Для ваших юнит-тестов Factory Girl не понадобится и только замедляет ваш набор тестов. Джош Клэйтон был бы первым, кто засвидетельствовал это, и порекомендовал бы наилучшую практику использовать Factory Girl избирательно и как можно меньше.