- Update Your Gemfile
- Skonfiguruj swój zestaw testów
- Test::Unit
- Cucumber
- Spinach
- Minitest
- Minitest::Spec
- minitest-rails
- Definiowanie fabryk
- Używanie fabryk
- Atrybuty dynamiczne
- Aliasy
- Atrybuty zależne
- Transient Attributes
- Nazwy metod / zarezerwowane słowa
- Dziedziczenie
- Asocjacje
- Sekwencje
- Traits
- Callbacks
- Modyfikowanie fabryk
- Building or Creating Multiple Records
- Linting Factories
- Custom Construction
- Strategie niestandardowe
- Custom Callbacks
- Custom Methods to Persist Objects
- ActiveSupport Instrumentation
- Rails Preloaders and RSpec
- Używanie bez Bundlera
Update Your Gemfile
Jeśli używasz Rails, będziesz musiał zmienić wymaganą wersję factory_girl_rails
:
gem "factory_girl_rails", "~> 4.0"
Jeśli nie używasz Rails, będziesz musiał po prostu zmienić wymaganą wersję factory_girl
:
gem "factory_girl", "~> 4.0"
export JRUBY_OPTS=--1.9
Gdy twój Gemfile jest zaktualizowany, będziesz chciał zaktualizować swój bundle.
Skonfiguruj swój zestaw testów
Pamiętaj, aby wymagać powyższego pliku w swoim rails_helper, ponieważ folder wsparcia nie jest chętnie ładowany
require 'support/factory_girl'
Test::Unit
class Test::Unit::TestCase include FactoryGirl::Syntax::Methodsend
Cucumber
# env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)World(FactoryGirl::Syntax::Methods)
Spinach
class Spinach::FeatureSteps include FactoryGirl::Syntax::Methodsend
Minitest
class Minitest::Unit::TestCase include FactoryGirl::Syntax::Methodsend
Minitest::Spec
class Minitest::Spec include FactoryGirl::Syntax::Methodsend
minitest-rails
class ActiveSupport::TestCase include FactoryGirl::Syntax::Methodsend
Jeśli nie uwzględnisz FactoryGirl::Syntax::Methods
w swoim zestawie testów, wówczas wszystkie metody factory_girl będą musiały być poprzedzone FactoryGirl
.
Definiowanie fabryk
Każda fabryka ma nazwę i zestaw atrybutów. Nazwa jest domyślnie używana do odgadnięcia klasy obiektu, ale można ją jawnie określić:
Bardzo zalecane jest posiadanie jednej fabryki dla każdej klasy, która zapewnia najprostszy zestaw atrybutów niezbędnych do utworzenia instancji tej klasy. Jeśli tworzysz obiekty ActiveRecord, oznacza to, że powinieneś dostarczyć tylko te atrybuty, które są wymagane przez walidacje i które nie mają wartości domyślnych. Inne fabryki mogą być tworzone poprzez dziedziczenie, aby pokryć wspólne scenariusze dla każdej klasy.
Próba zdefiniowania wielu fabryk o tej samej nazwie spowoduje podniesienie błędu.
Fabryki mogą być zdefiniowane gdziekolwiek, ale zostaną automatycznie załadowane po wywołaniu FactoryGirl.find_definitions
, jeśli fabryki są zdefiniowane w plikach w następujących miejscach:
test/factories.rbspec/factories.rbtest/factories/*.rbspec/factories/*.rb
Używanie fabryk
factory_girl obsługuje kilka różnych strategii budowania: build, create, attributes_for i build_stubbed:
Niezależnie od tego, która strategia jest używana, możliwe jest nadpisanie zdefiniowanych atrybutów poprzez przekazanie hasha:
# Build a User instance and override the first_name propertyuser = build(:user, first_name: "Joe")user.first_name# => "Joe"
Atrybuty dynamiczne
Większość atrybutów fabryki może być dodana przy użyciu statycznych wartości, które są obliczane, gdy fabryka jest zdefiniowana, ale niektóre atrybuty (takie jak asocjacje i inne atrybuty, które muszą być generowane dynamicznie) będą potrzebowały wartości przypisanych za każdym razem, gdy generowana jest instancja. Te „dynamiczne” atrybuty mogą być dodane przez przekazanie bloku zamiast parametru:
factory :user do # ... activation_code { User.generate_activation_code } date_of_birth { 21.years.ago }end
Z powodu składni blokowej w Rubim, definiowanie atrybutów jako Hash
es (na przykład dla zserializowanych kolumn/JSON) wymaga dwóch zestawów nawiasów klamrowych:
factory :program do configuration { { auto_resolve: false, auto_define: true } }end
Aliasy
factory_girl pozwala na definiowanie aliasów do istniejących fabryk, aby ułatwić ich ponowne użycie. Może się to przydać, gdy na przykład twój obiekt Post ma atrybut author, który w rzeczywistości odnosi się do instancji klasy User. Podczas gdy normalnie factory_girl potrafi wywnioskować nazwę fabryki z nazwy asocjacji, w tym przypadku będzie szukała fabryki autora na próżno. Tak więc, aliasuj swoją fabrykę użytkowników, aby mogła być używana pod nazwami aliasowymi.
Atrybuty zależne
Atrybuty mogą być oparte na wartościach innych atrybutów przy użyciu ewaluatora, który jest przekazywany do dynamicznych bloków atrybutów:
Transient Attributes
Mogą być sytuacje, w których twój kod może być DRYed up poprzez przekazywanie atrybutów transient do fabryk.
Statyczne i dynamiczne atrybuty mogą być tworzone jako atrybuty przejściowe. Atrybuty przejściowe będą ignorowane wewnątrz attributes_for i nie będą ustawiane w modelu, nawet jeśli atrybut istnieje lub próbujesz go zastąpić.
Wewnątrz dynamicznych atrybutów factory_girl możesz uzyskać dostęp do atrybutów przejściowych, tak jak byś tego oczekiwał. Jeśli potrzebujesz dostępu do ewaluatora w wywołaniu zwrotnym factory_girl, będziesz musiał zadeklarować drugi argument bloku (dla ewaluatora) i stamtąd uzyskać dostęp do atrybutów przejściowych.
Nazwy metod / zarezerwowane słowa
Jeśli twoje atrybuty kolidują z istniejącymi metodami lub zarezerwowanymi słowami, możesz je zdefiniować za pomocą add_attribute
.
factory :dna do add_attribute(:sequence) { 'GATTACA' }endfactory :payment do add_attribute(:method) { 'paypal' }end
Dziedziczenie
Możesz łatwo tworzyć wiele fabryk dla tej samej klasy bez powtarzania wspólnych atrybutów poprzez zagnieżdżanie fabryk:
Możesz również przypisać rodzica jawnie:
factory :post do title "A title"endfactory :approved_post, parent: :post do approved trueend
Jak wspomniano powyżej, dobrą praktyką jest zdefiniowanie podstawowej fabryki dla każdej klasy z tylko atrybutami wymaganymi do jej utworzenia. Następnie należy utworzyć bardziej specyficzne fabryki, które dziedziczą z tego podstawowego rodzica. Definicje fabryk są nadal kodem, więc zachowaj DRY.
Asocjacje
Możliwe jest tworzenie asocjacji wewnątrz fabryk. Jeśli nazwa fabryki jest taka sama jak nazwa asocjacji, nazwa fabryki może zostać pominięta.
factory :post do # ... authorend
Możesz również określić inną fabrykę lub nadpisać atrybuty:
factory :post do # ... association :author, factory: :user, last_name: "Writely"end
Zachowanie metody asocjacji różni się w zależności od strategii budowania użytej dla obiektu nadrzędnego.
Aby nie zapisywać obiektu stowarzyszonego, określ strategię: :build w fabryce:
Pamiętaj, że opcja strategy: :build
musi być przekazana do jawnego wywołania association
i nie może być użyta z niejawnymi asocjacjami:
factory :post do # ... author strategy: :build # <<< this does *not* work; causes author_id to be nil
Generowanie danych dla relacji has_many
jest nieco bardziej skomplikowane, w zależności od pożądanej elastyczności, ale oto pewny przykład generowania danych stowarzyszonych.
FactoryGirl.define do # post factory with a `belongs_to` association for the user factory :post do title "Through the Looking Glass" user end # user factory without associated posts factory :user do name "John Doe" # user_with_posts will create post data after the user has been created factory :user_with_posts do # posts_count is declared as a transient attribute and available in # attributes on the factory, as well as the callback via the evaluator transient do posts_count 5 end # the after(:create) yields two values; the user instance itself and the # evaluator, which stores all values from the factory, including transient # attributes; `create_list`'s second argument is the number of records # to create and we make sure the user is associated properly to the post after(:create) do |user, evaluator| create_list(:post, evaluator.posts_count, user: user) end end endend
To pozwala nam zrobić:
create(:user).posts.length # 0create(:user_with_posts).posts.length # 5create(:user_with_posts, posts_count: 15).posts.length # 15
Generowanie danych dla relacji has_and_belongs_to_many
jest bardzo podobne do powyższej relacji has_many
, z małą zmianą, musisz przekazać tablicę obiektów do spolszczonej nazwy atrybutu modelu zamiast pojedynczego obiektu do pojedynczej wersji nazwy atrybutu.
Tutaj przykład z dwoma modelami, które są powiązane przezhas_and_belongs_to_many
:
FactoryGirl.define do # language factory with a `belongs_to` association for the profile factory :language do title "Through the Looking Glass" profile end # profile factory without associated languages factory :profile do name "John Doe" # profile_with_languages will create language data after the profile has # been created factory :profile_with_languages do # languages_count is declared as an ignored attribute and available in # attributes on the factory, as well as the callback via the evaluator transient do languages_count 5 end # the after(:create) yields two values; the profile instance itself and # the evaluator, which stores all values from the factory, including # ignored attributes; `create_list`'s second argument is the number of # records to create and we make sure the profile is associated properly # to the language after(:create) do |profile, evaluator| create_list(:language, evaluator.languages_count, profiles: ) end end endend
To pozwala nam zrobić:
Sekwencje
Unikalne wartości w określonym formacie (na przykład adresy e-mail) mogą być generowane przy użyciu sekwencji. Sekwencje są definiowane przez wywołanie sequence
w bloku adefinicji, a wartości w sekwencji są generowane przez wywołaniegenerate
:
Sekwencje mogą być używane w atrybutach dynamicznych:
factory :invite do invitee { generate(:email) }end
lub jako atrybuty niejawne:
factory :user do email # Same as `email { generate(:email) }`end
Możliwe jest również zdefiniowanie sekwencji in-line, która jest używana tylko w danej fabryce:
factory :user do sequence(:email) { |n| "person#{n}@example.com" }end
Można również nadpisać wartość początkową:
factory :user do sequence(:email, 1000) { |n| "person#{n}@example.com" }end
Bez bloku, wartość będzie inkrementować się sama, zaczynając od wartości początkowej:
factory :post do sequence(:position)end
Sekwencje mogą również posiadać aliasy. Aliasy sekwencji dzielą ten sam licznik:
Zdefiniuj alias i użyj domyślnej wartości (1) dla licznika
factory :user do sequence(:email, aliases: ) { |n| "person#{n}@example.com" }end
Ustawianie wartości:
factory :user do sequence(:email, 'a', aliases: ) { |n| "person#{n}@example.com" }end
Wartość musi tylko obsługiwać metodę #next
. Tutaj następną wartością będzie 'a’, potem 'b’, itd.
Traits
Traits pozwalają na grupowanie atrybutów razem, a następnie zastosowanie ich do dowolnej fabryki.
Traits mogą być używane jako atrybuty:
Traits, które definiują te same atrybuty nie podniosą AttributeDefinitionErrors; cecha, która definiuje atrybut ostatni ma pierwszeństwo.
Możesz również nadpisać poszczególne atrybuty nadane przez cechę w podklasach.
Traity mogą być również przekazane jako lista symboli, gdy konstruujesz instancję z factory_girl.
Ta zdolność działa z build
, build_stubbed
, attributes_for
i create
.
create_list
i build_list
metody są również obsługiwane. Pamiętaj tylko, aby przekazać liczbę instancji do utworzenia/budowy jako drugi parametr, jak udokumentowano w sekcji „Budowanie lub tworzenie wielu rekordów” w tym pliku.
Cechy mogą być również łatwo używane z asocjacjami:
Gdy używasz nazw asocjacji, które są inne niż fabryczne:
Cechy mogą być używane wewnątrz innych cech, aby mieszać w ich atrybutach.
factory :order do trait :completed do completed_at { 3.days.ago } end trait :refunded do completed refunded_at { 1.day.ago } endend
Na koniec, cechy mogą akceptować atrybuty przejściowe.
Callbacks
factory_girl udostępnia cztery callbacks do wstrzyknięcia jakiegoś kodu:
Przykłady:
Zauważ, że będziesz miał instancję użytkownika w bloku. To może być przydatne.
Możesz również zdefiniować wiele typów wywołań zwrotnych na tej samej fabryce:
factory :user do after(:build) { |user| do_something_to(user) } after(:create) { |user| do_something_else_to(user) }end
Fabryki mogą również zdefiniować dowolną liczbę tego samego rodzaju wywołań zwrotnych. Te wywołania zwrotne będą wykonywane w kolejności, w jakiej zostały określone:
factory :user do after(:create) { this_runs_first } after(:create) { then_this }end
Wywołanie create
spowoduje wywołanie zarówno after_build
jak i after_create
wywołań zwrotnych.
Podobnie jak standardowe atrybuty, fabryki-dzieci dziedziczą (i mogą również definiować) wywołania zwrotne z ich fabryki nadrzędnej.
Wielokrotne wywołania zwrotne mogą być przypisane do uruchamiania bloku; jest to przydatne podczas budowania różnych strategii, które uruchamiają ten sam kod (ponieważ nie ma wywołań zwrotnych, które są współdzielone przez wszystkie strategie).
Aby zastąpić wywołania zwrotne dla wszystkich fabryk, zdefiniuj je wewnątrz blokuFactoryGirl.define
:
Możesz również wywoływać wywołania zwrotne, które polegają na Symbol#to_proc
:
Modyfikowanie fabryk
Jeśli dostałeś zestaw fabryk (powiedzmy, od dewelopera klejnotów), ale chcesz je zmienić, aby lepiej pasowały do twojej aplikacji, możesz zmodyfikować tę fabrykę zamiast tworzyć fabrykę potomną i dodawać tam atrybuty.
Jeśli gem dałby ci fabrykę użytkownika:
FactoryGirl.define do factory :user do full_name "John Doe" sequence(:username) { |n| "user#{n}" } password "password" endend
Zamiast tworzyć fabrykę potomną, która dodawałaby dodatkowe atrybuty:
mógłbyś zmodyfikować tę fabrykę.
FactoryGirl.modify do factory :user do full_name "Jane Doe" date_of_birth { 21.years.ago } gender "Female" health 90 endend
Modyfikując fabrykę, możesz zmienić dowolne atrybuty (oprócz wywołań zwrotnych).
FactoryGirl.modify
musi być wywołany poza blokiem FactoryGirl.define
, ponieważ działa na fabrykach w inny sposób.
Zastrzeżenie: możesz modyfikować tylko fabryki (nie sekwencje lub cechy), a wywołania zwrotne nadal się łączą, tak jak normalnie. Tak więc, jeśli fabryka, którą modyfikujesz definiuje wywołanie zwrotne after(:create)
, definiując after(:create)
nie zastąpisz go, po prostu zostanie ono uruchomione po pierwszym wywołaniu zwrotnym.
Building or Creating Multiple Records
Czasami będziesz chciał utworzyć lub zbudować wiele instancji fabryki na raz.
built_users = build_list(:user, 25)created_users = create_list(:user, 25)
Te metody zbudują lub utworzą określoną ilość fabryk i zwrócą je jako tablicę.Aby ustawić atrybuty dla każdej z fabryk, możesz przekazać hash, tak jak normalnie byś to zrobił.
twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
build_stubbed_list
da ci w pełni wyparte instancje:
stubbed_users = build_stubbed_list(:user, 25) # array of stubbed users
Jest też zestaw metod *_pair
do tworzenia dwóch rekordów naraz:
built_users = build_pair(:user) # array of two built userscreated_users = create_pair(:user) # array of two created users
Jeśli potrzebujesz wielu hashy atrybutów, attributes_for_list
je wygeneruje:
users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
Linting Factories
factory_girl pozwala na linting znanych fabryk:
FactoryGirl.lint
FactoryGirl.lint
tworzy każdą fabrykę i wyłapuje wszelkie wyjątki podniesione podczas procesu tworzenia. FactoryGirl::InvalidFactoryError
jest podnoszona lista fabryk (i odpowiadających im wyjątków) dla fabryk, które nie mogły zostać utworzone.
Zalecane użycie FactoryGirl.lint
polega na uruchomieniu tego w zadaniu przed wykonaniem zestawu testów.Uruchomienie go w before(:suite)
, będzie miało negatywny wpływ na wydajność twoich testów podczas uruchamiania pojedynczych testów.
Przykładowe zadanie Rake:
Po wywołaniu FactoryGirl.lint
, prawdopodobnie będziesz chciał wyczyścić bazę danych, ponieważ rekordy najprawdopodobniej zostaną utworzone. Powyższy przykład używa klejnotu database_cleaner do wyczyszczenia bazy danych; upewnij się, że dodałeś klejnot do swojego Gemfile w odpowiednich grupach.
Możesz selektywnie podlinkować fabryki, przekazując tylko te, które chcesz podlinkować:
factories_to_lint = FactoryGirl.factories.reject do |factory| factory.name =~ /^old_/endFactoryGirl.lint factories_to_lint
W ten sposób podlinkujesz wszystkie fabryki, które nie są poprzedzone old_
.
Podlinkować można również cechy. Ta opcja weryfikuje, czy każda cecha fabryki generuje poprawny obiekt samodzielnie.Włącza się to przez przekazanie traits: true
do metody lint
:
FactoryGirl.lint traits: true
Można to również połączyć z innymi argumentami:
FactoryGirl.lint factories_to_lint, traits: true
Można również określić strategię używaną do lintowania:
FactoryGirl.lint strategy: :build
Custom Construction
Jeśli chcesz użyć factory_girl do skonstruowania obiektu, w którym niektóre atrybuty są przekazywane do initialize
lub jeśli chcesz zrobić coś innego niż po prostu wywołać new
na swojej klasie konstrukcyjnej, możesz nadpisać domyślne zachowanie przez zdefiniowanie initialize_with
na swojej fabryce. Przykład:
Chociaż factory_girl jest napisana do pracy z ActiveRecord, może również pracować z dowolną klasą Ruby. Dla maksymalnej kompatybilności z ActiveRecord, domyślny inicjalizator buduje wszystkie instancje przez wywołanie new
na twojej klasie konstrukcyjnej bez żadnych argumentów. Następnie wywołuje metody piszące atrybuty, aby przypisać im wszystkie wartości atrybutów. Podczas gdy działa to dobrze dla ActiveRecord, nie działa to dla prawie żadnej innej klasy Ruby.
Możesz nadpisać inicjalizator, aby:
- Buduj obiekty inne niż ActiveRecord, które wymagają argumentów do
initialize
- Użyj metody innej niż
new
do instancjonowania instancji - Rób szalone rzeczy, takie jak dekorowanie instancji po jej zbudowaniu
Gdy używasz initialize_with
, nie musisz deklarować samej klasy podczas wywoływania new
; jednak wszelkie inne metody klasowe, które chcesz wywołać, będą musiały być wywołane na klasie jawnie.
Na przykład:
factory :user do name "John Doe" initialize_with { User.build_with_name(name) }end
Możesz również uzyskać dostęp do wszystkich publicznych atrybutów w bloku initialize_with
przez wywołanie attributes
:
factory :user do transient do 5 end name "John Doe" initialize_with { new(attributes) }end
To zbuduje hash wszystkich atrybutów do przekazania do new
. Nie będzie on zawierał atrybutów przejściowych, ale wszystko inne zdefiniowane w fabryce zostanie przekazane (asocjacje, ewaluowane sekwencje, itp.)
Możesz zdefiniować initialize_with
dla wszystkich fabryk, umieszczając go w blokuFactoryGirl.define
:
FactoryGirl.define do initialize_with { new("Awesome first argument") }end
Kiedy używasz initialize_with
, atrybuty dostępne z wnętrza bloku initialize_with
są przypisywane tylko w konstruktorze; odpowiada to mniej więcej następującemu kodowi:
FactoryGirl.define do factory :user do initialize_with { new(name) } name { 'value' } endendbuild(:user)# runsUser.new('value')
To zapobiega duplikowaniu przypisań; w wersjach factory_girl sprzed 4.0, działałoby to tak:
Strategie niestandardowe
Są sytuacje, w których możesz chcieć rozszerzyć zachowanie factory_girl przez dodanie niestandardowej strategii budowania.
Strategie definiują dwie metody: association
i result
. association
otrzymuje instancję FactoryGirl::FactoryRunner
, na której możesz wywołaćrun
, nadpisując strategię, jeśli chcesz. Druga metoda, result
, otrzymuje instancję FactoryGirl::Evaluation
. Zapewnia ona sposób na wyzwalanie wywołania zwrotnego (za pomocą notify
), object
lub hash
(aby uzyskać instancję wyniku lub ahash na podstawie atrybutów zdefiniowanych w fabryce) oraz create
, która wykonuje wywołanie zwrotne to_create
zdefiniowane w fabryce.
Aby zrozumieć, jak factory_girl używa strategii wewnętrznie, prawdopodobnie najłatwiej jest po prostu przejrzeć źródła dla każdej z czterech domyślnych strategii.
Oto przykład komponowania strategii przy użyciuFactoryGirl::Strategy::Create
, aby zbudować JSON-ową reprezentację twojego modelu.
Aby factory_girl rozpoznała nową strategię, możesz ją zarejestrować:
FactoryGirl.register_strategy(:json, JsonStrategy)
To pozwala na wywołanie
FactoryGirl.json(:user)
Na koniec, możesz nadpisać własne strategie factory_girl, jeśli chcesz, rejestrując nowy obiekt w miejsce strategii.
Custom Callbacks
Custom callbacks mogą być zdefiniowane, jeśli używasz niestandardowych strategii:
Custom Methods to Persist Objects
Domyślnie, tworzenie rekordu wywołuje save!
na instancji; ponieważ to może nie zawsze być idealne, możesz zastąpić to zachowanie definiującto_create
na fabryce:
factory :different_orm_model do to_create { |instance| instance.persist! }end
Aby całkowicie wyłączyć metodę persystencji przy tworzeniu, możesz skip_create
dla tej fabryki:
factory :user_without_database do skip_createend
Aby nadpisać to_create
dla wszystkich fabryk, zdefiniuj ją wewnątrz blokuFactoryGirl.define
:
FactoryGirl.define do to_create { |instance| instance.persist! } factory :user do name "John Doe" endend
ActiveSupport Instrumentation
Aby śledzić, jakie fabryki są tworzone (i z jaką strategią budowania), ActiveSupport::Notifications
są dołączone, aby zapewnić sposób subskrybowania uruchamianych fabryk. Jednym z przykładów może być śledzenie fabryk na podstawie progu czasu wykonania.
Innym przykładem może być śledzenie wszystkich fabryk i tego, jak są one używane w całym zestawie testów. Jeśli używasz RSpec, jest to tak proste, jak dodaniebefore(:suite)
i after(:suite)
:
Rails Preloaders and RSpec
Gdy uruchamiasz RSpec z preloaderem Rails, takim jak spring
lub zeus
, możliwe jest napotkanie błędu ActiveRecord::AssociationTypeMismatch
podczas tworzenia factorywith associations, jak poniżej:
Błąd pojawia się podczas uruchamiania zestawu testów:
Dwa możliwe rozwiązania to albo uruchomienie zestawu bez preloadera, albo dodanie FactoryGirl.reload
do konfiguracji RSpec, jak poniżej:
RSpec.configure do |config| config.before(:suite) { FactoryGirl.reload }end
Używanie bez Bundlera
Jeśli nie używasz Bundlera, upewnij się, że masz zainstalowany gem i wywołaj:
require 'factory_girl'
Jeśli jest to wymagane, zakładając, że masz strukturę katalogów spec/factories
lubtest/factories
, wszystko, co musisz zrobić, to uruchomić
FactoryGirl.find_definitions
Jeśli używasz oddzielnej struktury katalogów dla swoich fabryk, możesz zmienić ścieżki plików definicji przed próbą znalezienia definicji:
FactoryGirl.definition_file_paths = %w(custom_factories_directory)FactoryGirl.find_definitions
Jeśli nie masz osobnego katalogu z fabrykami i chciałbyś zdefiniować je inline, to również jest to możliwe:
require 'factory_girl'FactoryGirl.define do factory :user do name 'John Doe' date_of_birth { 21.years.ago } endend
.