factory_girl 4.2.0 → 4.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +29 -7
  3. data/.yardopts +1 -1
  4. data/Appraisals +12 -8
  5. data/CONTRIBUTING.md +60 -0
  6. data/GETTING_STARTED.md +473 -191
  7. data/Gemfile +6 -3
  8. data/Gemfile.lock +93 -65
  9. data/LICENSE +1 -1
  10. data/NAME.md +11 -0
  11. data/NEWS +43 -1
  12. data/README.md +52 -28
  13. data/Rakefile +1 -3
  14. data/factory_girl.gemspec +9 -17
  15. data/gemfiles/3.2.gemfile +6 -3
  16. data/gemfiles/3.2.gemfile.lock +85 -62
  17. data/gemfiles/4.0.gemfile +6 -3
  18. data/gemfiles/4.0.gemfile.lock +84 -74
  19. data/gemfiles/4.1.gemfile +10 -0
  20. data/gemfiles/4.1.gemfile.lock +104 -0
  21. data/gemfiles/4.2.gemfile +10 -0
  22. data/gemfiles/4.2.gemfile.lock +104 -0
  23. data/gemfiles/5.0.gemfile +10 -0
  24. data/gemfiles/5.0.gemfile.lock +103 -0
  25. data/lib/factory_girl/attribute/dynamic.rb +4 -1
  26. data/lib/factory_girl/attribute_assigner.rb +4 -4
  27. data/lib/factory_girl/attribute_list.rb +1 -1
  28. data/lib/factory_girl/callback.rb +1 -1
  29. data/lib/factory_girl/callbacks_observer.rb +1 -1
  30. data/lib/factory_girl/configuration.rb +7 -2
  31. data/lib/factory_girl/declaration_list.rb +2 -2
  32. data/lib/factory_girl/decorator/attribute_hash.rb +1 -2
  33. data/lib/factory_girl/decorator/class_key_hash.rb +2 -1
  34. data/lib/factory_girl/decorator.rb +2 -2
  35. data/lib/factory_girl/definition.rb +25 -15
  36. data/lib/factory_girl/definition_hierarchy.rb +1 -1
  37. data/lib/factory_girl/definition_proxy.rb +15 -17
  38. data/lib/factory_girl/errors.rb +6 -0
  39. data/lib/factory_girl/evaluator.rb +7 -1
  40. data/lib/factory_girl/factory.rb +3 -3
  41. data/lib/factory_girl/factory_runner.rb +7 -1
  42. data/lib/factory_girl/find_definitions.rb +3 -3
  43. data/lib/factory_girl/linter.rb +97 -0
  44. data/lib/factory_girl/strategy/stub.rb +58 -20
  45. data/lib/factory_girl/strategy_syntax_method_registrar.rb +17 -0
  46. data/lib/factory_girl/syntax/default.rb +8 -0
  47. data/lib/factory_girl/syntax/methods.rb +18 -2
  48. data/lib/factory_girl/version.rb +1 -1
  49. data/lib/factory_girl.rb +30 -3
  50. metadata +65 -249
  51. data/CONTRIBUTION_GUIDELINES.md +0 -10
  52. data/features/find_definitions.feature +0 -75
  53. data/features/step_definitions/database_steps.rb +0 -9
  54. data/features/step_definitions/factory_girl_steps.rb +0 -36
  55. data/features/support/env.rb +0 -10
  56. data/features/support/factories.rb +0 -16
  57. data/gemfiles/3.0.gemfile +0 -7
  58. data/gemfiles/3.0.gemfile.lock +0 -81
  59. data/gemfiles/3.1.gemfile +0 -7
  60. data/gemfiles/3.1.gemfile.lock +0 -82
  61. data/spec/acceptance/activesupport_instrumentation_spec.rb +0 -62
  62. data/spec/acceptance/aliases_spec.rb +0 -19
  63. data/spec/acceptance/attribute_aliases_spec.rb +0 -45
  64. data/spec/acceptance/attribute_existing_on_object_spec.rb +0 -68
  65. data/spec/acceptance/attributes_for_spec.rb +0 -97
  66. data/spec/acceptance/attributes_from_instance_spec.rb +0 -53
  67. data/spec/acceptance/attributes_ordered_spec.rb +0 -51
  68. data/spec/acceptance/build_list_spec.rb +0 -56
  69. data/spec/acceptance/build_spec.rb +0 -86
  70. data/spec/acceptance/build_stubbed_spec.rb +0 -161
  71. data/spec/acceptance/callbacks_spec.rb +0 -177
  72. data/spec/acceptance/create_list_spec.rb +0 -97
  73. data/spec/acceptance/create_spec.rb +0 -116
  74. data/spec/acceptance/define_child_before_parent_spec.rb +0 -21
  75. data/spec/acceptance/definition_spec.rb +0 -21
  76. data/spec/acceptance/definition_without_block_spec.rb +0 -15
  77. data/spec/acceptance/global_initialize_with_spec.rb +0 -82
  78. data/spec/acceptance/global_to_create_spec.rb +0 -122
  79. data/spec/acceptance/initialize_with_spec.rb +0 -217
  80. data/spec/acceptance/keyed_by_class_spec.rb +0 -22
  81. data/spec/acceptance/modify_factories_spec.rb +0 -184
  82. data/spec/acceptance/modify_inherited_spec.rb +0 -52
  83. data/spec/acceptance/nested_attributes_spec.rb +0 -32
  84. data/spec/acceptance/overrides_spec.rb +0 -61
  85. data/spec/acceptance/parent_spec.rb +0 -90
  86. data/spec/acceptance/register_strategies_spec.rb +0 -128
  87. data/spec/acceptance/sequence_context_spec.rb +0 -52
  88. data/spec/acceptance/sequence_spec.rb +0 -61
  89. data/spec/acceptance/skip_create_spec.rb +0 -19
  90. data/spec/acceptance/stub_spec.rb +0 -62
  91. data/spec/acceptance/syntax_methods_within_dynamic_attributes_spec.rb +0 -41
  92. data/spec/acceptance/traits_spec.rb +0 -727
  93. data/spec/acceptance/transient_attributes_spec.rb +0 -124
  94. data/spec/factory_girl/aliases_spec.rb +0 -31
  95. data/spec/factory_girl/attribute/association_spec.rb +0 -28
  96. data/spec/factory_girl/attribute/dynamic_spec.rb +0 -52
  97. data/spec/factory_girl/attribute/sequence_spec.rb +0 -16
  98. data/spec/factory_girl/attribute/static_spec.rb +0 -19
  99. data/spec/factory_girl/attribute_list_spec.rb +0 -143
  100. data/spec/factory_girl/attribute_spec.rb +0 -16
  101. data/spec/factory_girl/callback_spec.rb +0 -41
  102. data/spec/factory_girl/declaration/implicit_spec.rb +0 -25
  103. data/spec/factory_girl/declaration_list_spec.rb +0 -67
  104. data/spec/factory_girl/definition_proxy_spec.rb +0 -215
  105. data/spec/factory_girl/definition_spec.rb +0 -58
  106. data/spec/factory_girl/disallows_duplicates_registry_spec.rb +0 -19
  107. data/spec/factory_girl/evaluator_class_definer_spec.rb +0 -77
  108. data/spec/factory_girl/factory_spec.rb +0 -259
  109. data/spec/factory_girl/find_definitions_spec.rb +0 -110
  110. data/spec/factory_girl/null_factory_spec.rb +0 -13
  111. data/spec/factory_girl/null_object_spec.rb +0 -22
  112. data/spec/factory_girl/registry_spec.rb +0 -68
  113. data/spec/factory_girl/sequence_spec.rb +0 -95
  114. data/spec/factory_girl/strategy/attributes_for_spec.rb +0 -18
  115. data/spec/factory_girl/strategy/build_spec.rb +0 -7
  116. data/spec/factory_girl/strategy/create_spec.rb +0 -25
  117. data/spec/factory_girl/strategy/stub_spec.rb +0 -38
  118. data/spec/factory_girl/strategy_calculator_spec.rb +0 -29
  119. data/spec/factory_girl_spec.rb +0 -22
  120. data/spec/spec_helper.rb +0 -26
  121. data/spec/support/macros/define_constant.rb +0 -86
  122. data/spec/support/matchers/callback.rb +0 -9
  123. data/spec/support/matchers/declaration.rb +0 -83
  124. data/spec/support/matchers/delegate.rb +0 -44
  125. data/spec/support/matchers/trait.rb +0 -9
  126. data/spec/support/shared_examples/strategy.rb +0 -90
data/GETTING_STARTED.md CHANGED
@@ -16,53 +16,91 @@ If you're *not* using Rails, you'll just have to change the required version of
16
16
  gem "factory_girl", "~> 4.0"
17
17
  ```
18
18
 
19
- JRuby users: FactoryGirl works with JRuby starting with 1.6.7.2 (latest stable, as per July 2012).
19
+ JRuby users: factory_girl works with JRuby starting with 1.6.7.2 (latest stable, as per July 2012).
20
20
  JRuby has to be used in 1.9 mode, for that, use JRUBY_OPTS environment variable:
21
21
 
22
- ```
22
+ ```bash
23
23
  export JRUBY_OPTS=--1.9
24
24
  ```
25
25
 
26
26
  Once your Gemfile is updated, you'll want to update your bundle.
27
27
 
28
- Using Without Bundler
29
- ---------------------
28
+ Configure your test suite
29
+ -------------------------
30
30
 
31
- If you're not using Bundler, be sure to have the gem installed and call:
31
+ # RSpec
32
32
 
33
+ ```ruby
34
+ # spec/support/factory_girl.rb
35
+ RSpec.configure do |config|
36
+ config.include FactoryGirl::Syntax::Methods
37
+ end
38
+
39
+ # RSpec without Rails
40
+ RSpec.configure do |config|
41
+ config.include FactoryGirl::Syntax::Methods
42
+
43
+ config.before(:suite) do
44
+ FactoryGirl.find_definitions
45
+ end
46
+ end
33
47
  ```
34
- require 'factory_girl'
48
+
49
+ Remember to require the above file in your rails_helper since the support folder isn't eagerly loaded
50
+
51
+ ```ruby
52
+ require 'support/factory_girl'
35
53
  ```
36
54
 
37
- Once required, assuming you have a directory structure of `spec/factories` or
38
- `test/factories`, all you'll need to do is run
55
+ # Test::Unit
39
56
 
40
57
  ```ruby
41
- FactoryGirl.find_definitions
58
+ class Test::Unit::TestCase
59
+ include FactoryGirl::Syntax::Methods
60
+ end
42
61
  ```
43
62
 
44
- If you're using a separate directory structure for your factories, you can
45
- change the definition file paths before trying to find definitions:
63
+ # Cucumber
46
64
 
47
65
  ```ruby
48
- FactoryGirl.definition_file_paths = %w(custom_factories_directory)
49
- FactoryGirl.find_definitions
66
+ # env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)
67
+ World(FactoryGirl::Syntax::Methods)
50
68
  ```
51
69
 
52
- If you don't have a separate directory of factories and would like to define
53
- them inline, that's possible as well:
70
+ # Spinach
54
71
 
55
72
  ```ruby
56
- require 'factory_girl'
73
+ class Spinach::FeatureSteps
74
+ include FactoryGirl::Syntax::Methods
75
+ end
76
+ ```
57
77
 
58
- FactoryGirl.define do
59
- factory :user do
60
- name 'John Doe'
61
- date_of_birth { 21.years.ago }
62
- end
78
+ # Minitest
79
+
80
+ ```ruby
81
+ class Minitest::Unit::TestCase
82
+ include FactoryGirl::Syntax::Methods
63
83
  end
64
84
  ```
65
85
 
86
+ # Minitest::Spec
87
+
88
+ ```ruby
89
+ class Minitest::Spec
90
+ include FactoryGirl::Syntax::Methods
91
+ end
92
+ ```
93
+
94
+ # minitest-rails
95
+
96
+ ```ruby
97
+ class ActiveSupport::TestCase
98
+ include FactoryGirl::Syntax::Methods
99
+ end
100
+ ```
101
+
102
+ If you do not include `FactoryGirl::Syntax::Methods` in your test suite, then all factory_girl methods will need to be prefaced with `FactoryGirl`.
103
+
66
104
  Defining factories
67
105
  ------------------
68
106
 
@@ -90,8 +128,9 @@ It is highly recommended that you have one factory for each class that provides
90
128
 
91
129
  Attempting to define multiple factories with the same name will raise an error.
92
130
 
93
- Factories can be defined anywhere, but will be automatically loaded if they
94
- are defined in files at the following locations:
131
+ Factories can be defined anywhere, but will be automatically loaded after
132
+ calling `FactoryGirl.find_definitions` if factories are defined in files at the
133
+ following locations:
95
134
 
96
135
  test/factories.rb
97
136
  spec/factories.rb
@@ -105,19 +144,19 @@ factory\_girl supports several different build strategies: build, create, attrib
105
144
 
106
145
  ```ruby
107
146
  # Returns a User instance that's not saved
108
- user = FactoryGirl.build(:user)
147
+ user = build(:user)
109
148
 
110
149
  # Returns a saved User instance
111
- user = FactoryGirl.create(:user)
150
+ user = create(:user)
112
151
 
113
152
  # Returns a hash of attributes that can be used to build a User instance
114
- attrs = FactoryGirl.attributes_for(:user)
153
+ attrs = attributes_for(:user)
115
154
 
116
155
  # Returns an object with all defined attributes stubbed out
117
- stub = FactoryGirl.build_stubbed(:user)
156
+ stub = build_stubbed(:user)
118
157
 
119
158
  # Passing a block to any of the methods above will yield the return object
120
- FactoryGirl.create(:user) do |user|
159
+ create(:user) do |user|
121
160
  user.posts.create(attributes_for(:post))
122
161
  end
123
162
  ```
@@ -126,62 +165,18 @@ No matter which strategy is used, it's possible to override the defined attribut
126
165
 
127
166
  ```ruby
128
167
  # Build a User instance and override the first_name property
129
- user = FactoryGirl.build(:user, first_name: "Joe")
168
+ user = build(:user, first_name: "Joe")
130
169
  user.first_name
131
170
  # => "Joe"
132
171
  ```
133
172
 
134
- If repeating "FactoryGirl" is too verbose for you, you can mix the syntax methods in:
135
-
136
- ```ruby
137
- # rspec
138
- RSpec.configure do |config|
139
- config.include FactoryGirl::Syntax::Methods
140
- end
141
-
142
- # Test::Unit
143
- class Test::Unit::TestCase
144
- include FactoryGirl::Syntax::Methods
145
- end
146
-
147
- # Cucumber
148
- World(FactoryGirl::Syntax::Methods)
149
-
150
- # MiniTest
151
- class MiniTest::Unit::TestCase
152
- include FactoryGirl::Syntax::Methods
153
- end
154
-
155
- # MiniTest::Spec
156
- class MiniTest::Spec
157
- include FactoryGirl::Syntax::Methods
158
- end
159
-
160
- # minitest-rails
161
- class MiniTest::Rails::ActiveSupport::TestCase
162
- include FactoryGirl::Syntax::Methods
163
- end
164
- ```
165
-
166
- This allows you to use the core set of syntax methods (`build`,
167
- `build_stubbed`, `create`, `attributes_for`, and their `*_list` counterparts)
168
- without having to call them on FactoryGirl directly:
169
-
170
- ```ruby
171
- describe User, "#full_name" do
172
- subject { create(:user, first_name: "John", last_name: "Doe") }
173
-
174
- its(:full_name) { should eq "John Doe" }
175
- end
176
- ```
177
-
178
- Lazy Attributes
179
- ---------------
173
+ Dynamic Attributes
174
+ ------------------
180
175
 
181
176
  Most factory attributes can be added using static values that are evaluated when
182
177
  the factory is defined, but some attributes (such as associations and other
183
178
  attributes that must be dynamically generated) will need values assigned each
184
- time an instance is generated. These "lazy" attributes can be added by passing a
179
+ time an instance is generated. These "dynamic" attributes can be added by passing a
185
180
  block instead of a parameter:
186
181
 
187
182
  ```ruby
@@ -192,28 +187,18 @@ factory :user do
192
187
  end
193
188
  ```
194
189
 
195
- In addition to running other methods dynamically, you can use FactoryGirl's
196
- syntax methods (like `build`, `create`, and `generate`) within dynamic
197
- attributes without having to prefix the call with `FactoryGirl.`. This allows
198
- you to do:
190
+ Because of the block syntax in Ruby, defining attributes as `Hash`es (for
191
+ serialized/JSON columns, for example) requires two sets of curly brackets:
199
192
 
200
193
  ```ruby
201
- sequence(:random_string) {|n| LoremIpsum.generate }
202
-
203
- factory :post do
204
- title { generate(:random_string) } # instead of FactoryGirl.generate(:random_string)
205
- end
206
-
207
- factory :comment do
208
- post
209
- body { generate(:random_string) } # instead of FactoryGirl.generate(:random_string)
194
+ factory :program do
195
+ configuration { { auto_resolve: false, auto_define: true } }
210
196
  end
211
197
  ```
212
198
 
213
199
  Aliases
214
200
  -------
215
-
216
- Aliases allow you to use named associations more easily.
201
+ factory_girl allows you to define aliases to existing factories to make them easier to re-use. This could come in handy when, for example, your Post object has an author attribute that actually refers to an instance of a User class. While normally factory_girl can infer the factory name from the association name, in this case it will look for a author factory in vain. So, alias your user factory so it can be used under alias names.
217
202
 
218
203
  ```ruby
219
204
  factory :user, aliases: [:author, :commenter] do
@@ -241,7 +226,8 @@ end
241
226
  Dependent Attributes
242
227
  --------------------
243
228
 
244
- Attributes can be based on the values of other attributes using the evaluator that is yielded to lazy attribute blocks:
229
+ Attributes can be based on the values of other attributes using the evaluator
230
+ that is yielded to dynamic attribute blocks:
245
231
 
246
232
  ```ruby
247
233
  factory :user do
@@ -250,7 +236,7 @@ factory :user do
250
236
  email { "#{first_name}.#{last_name}@example.com".downcase }
251
237
  end
252
238
 
253
- FactoryGirl.create(:user, last_name: "Doe").email
239
+ create(:user, last_name: "Doe").email
254
240
  # => "joe.doe@example.com"
255
241
  ```
256
242
 
@@ -261,7 +247,7 @@ There may be times where your code can be DRYed up by passing in transient attri
261
247
 
262
248
  ```ruby
263
249
  factory :user do
264
- ignore do
250
+ transient do
265
251
  rockstar true
266
252
  upcased false
267
253
  end
@@ -274,18 +260,70 @@ factory :user do
274
260
  end
275
261
  end
276
262
 
277
- FactoryGirl.create(:user, upcased: true).name
263
+ create(:user, upcased: true).name
278
264
  #=> "JOHN DOE - ROCKSTAR"
279
265
  ```
280
266
 
281
- Static and dynamic attributes can be ignored. Ignored attributes will be ignored
282
- within attributes\_for and won't be set on the model, even if the attribute
283
- exists or you attempt to override it.
267
+ Static and dynamic attributes can be created as transient attributes. Transient
268
+ attributes will be ignored within attributes\_for and won't be set on the model,
269
+ even if the attribute exists or you attempt to override it.
284
270
 
285
- Within FactoryGirl's dynamic attributes, you can access ignored attributes as
286
- you would expect. If you need to access the evaluator in a FactoryGirl callback,
271
+ Within factory_girl's dynamic attributes, you can access transient attributes as
272
+ you would expect. If you need to access the evaluator in a factory_girl callback,
287
273
  you'll need to declare a second block argument (for the evaluator) and access
288
- ignored attributes from there.
274
+ transient attributes from there.
275
+
276
+ Method Name / Reserved Word Attributes
277
+ -------------------------------
278
+
279
+ If your attributes conflict with existing methods or reserved words you can define them with `add_attribute`.
280
+
281
+ ```ruby
282
+ factory :dna do
283
+ add_attribute(:sequence) { 'GATTACA' }
284
+ end
285
+
286
+ factory :payment do
287
+ add_attribute(:method) { 'paypal' }
288
+ end
289
+
290
+ ```
291
+
292
+ Inheritance
293
+ -----------
294
+
295
+ You can easily create multiple factories for the same class without repeating common attributes by nesting factories:
296
+
297
+ ```ruby
298
+ factory :post do
299
+ title "A title"
300
+
301
+ factory :approved_post do
302
+ approved true
303
+ end
304
+ end
305
+
306
+ approved_post = create(:approved_post)
307
+ approved_post.title # => "A title"
308
+ approved_post.approved # => true
309
+ ```
310
+
311
+ You can also assign the parent explicitly:
312
+
313
+ ```ruby
314
+ factory :post do
315
+ title "A title"
316
+ end
317
+
318
+ factory :approved_post, parent: :post do
319
+ approved true
320
+ end
321
+ ```
322
+
323
+ As mentioned above, it's good practice to define a basic factory for each class
324
+ with only the attributes required to create it. Then, create more specific
325
+ factories that inherit from this basic parent. Factory definitions are still
326
+ code, so keep them DRY.
289
327
 
290
328
  Associations
291
329
  ------------
@@ -312,12 +350,12 @@ The behavior of the association method varies depending on the build strategy us
312
350
 
313
351
  ```ruby
314
352
  # Builds and saves a User and a Post
315
- post = FactoryGirl.create(:post)
353
+ post = create(:post)
316
354
  post.new_record? # => false
317
355
  post.author.new_record? # => false
318
356
 
319
357
  # Builds and saves a User, and then builds but does not save a Post
320
- post = FactoryGirl.build(:post)
358
+ post = build(:post)
321
359
  post.new_record? # => true
322
360
  post.author.new_record? # => false
323
361
  ```
@@ -331,7 +369,7 @@ factory :post do
331
369
  end
332
370
 
333
371
  # Builds a User, and then builds a Post, but does not save either
334
- post = FactoryGirl.build(:post)
372
+ post = build(:post)
335
373
  post.new_record? # => true
336
374
  post.author.new_record? # => true
337
375
  ```
@@ -364,18 +402,18 @@ FactoryGirl.define do
364
402
 
365
403
  # user_with_posts will create post data after the user has been created
366
404
  factory :user_with_posts do
367
- # posts_count is declared as an ignored attribute and available in
405
+ # posts_count is declared as a transient attribute and available in
368
406
  # attributes on the factory, as well as the callback via the evaluator
369
- ignore do
407
+ transient do
370
408
  posts_count 5
371
409
  end
372
410
 
373
411
  # the after(:create) yields two values; the user instance itself and the
374
- # evaluator, which stores all values from the factory, including ignored
412
+ # evaluator, which stores all values from the factory, including transient
375
413
  # attributes; `create_list`'s second argument is the number of records
376
414
  # to create and we make sure the user is associated properly to the post
377
415
  after(:create) do |user, evaluator|
378
- FactoryGirl.create_list(:post, evaluator.posts_count, user: user)
416
+ create_list(:post, evaluator.posts_count, user: user)
379
417
  end
380
418
  end
381
419
  end
@@ -385,54 +423,69 @@ end
385
423
  This allows us to do:
386
424
 
387
425
  ```ruby
388
- FactoryGirl.create(:user).posts.length # 0
389
- FactoryGirl.create(:user_with_posts).posts.length # 5
390
- FactoryGirl.create(:user_with_posts, posts_count: 15).posts.length # 15
426
+ create(:user).posts.length # 0
427
+ create(:user_with_posts).posts.length # 5
428
+ create(:user_with_posts, posts_count: 15).posts.length # 15
391
429
  ```
392
430
 
393
- Inheritance
394
- -----------
431
+ Generating data for a `has_and_belongs_to_many` relationship is very similar
432
+ to the above `has_many` relationship, with a small change, you need to pass an
433
+ array of objects to the model's pluralized attribute name rather than a single
434
+ object to the singular version of the attribute name.
395
435
 
396
- You can easily create multiple factories for the same class without repeating common attributes by nesting factories:
436
+ Here's an example with two models that are related via
437
+ `has_and_belongs_to_many`:
397
438
 
398
439
  ```ruby
399
- factory :post do
400
- title "A title"
440
+ FactoryGirl.define do
401
441
 
402
- factory :approved_post do
403
- approved true
442
+ # language factory with a `belongs_to` association for the profile
443
+ factory :language do
444
+ title "Through the Looking Glass"
445
+ profile
404
446
  end
405
- end
406
447
 
407
- approved_post = FactoryGirl.create(:approved_post)
408
- approved_post.title # => "A title"
409
- approved_post.approved # => true
410
- ```
411
-
412
- You can also assign the parent explicitly:
448
+ # profile factory without associated languages
449
+ factory :profile do
450
+ name "John Doe"
413
451
 
414
- ```ruby
415
- factory :post do
416
- title "A title"
417
- end
452
+ # profile_with_languages will create language data after the profile has
453
+ # been created
454
+ factory :profile_with_languages do
455
+ # languages_count is declared as an ignored attribute and available in
456
+ # attributes on the factory, as well as the callback via the evaluator
457
+ transient do
458
+ languages_count 5
459
+ end
418
460
 
419
- factory :approved_post, parent: :post do
420
- approved true
461
+ # the after(:create) yields two values; the profile instance itself and
462
+ # the evaluator, which stores all values from the factory, including
463
+ # ignored attributes; `create_list`'s second argument is the number of
464
+ # records to create and we make sure the profile is associated properly
465
+ # to the language
466
+ after(:create) do |profile, evaluator|
467
+ create_list(:language, evaluator.languages_count, profiles: [profile])
468
+ end
469
+ end
470
+ end
421
471
  end
422
472
  ```
423
473
 
424
- As mentioned above, it's good practice to define a basic factory for each class
425
- with only the attributes required to create it. Then, create more specific
426
- factories that inherit from this basic parent. Factory definitions are still
427
- code, so keep them DRY.
474
+ This allows us to do:
475
+
476
+ ```ruby
477
+ create(:profile).languages.length # 0
478
+ create(:profile_with_languages).languages.length # 5
479
+ create(:profile_with_languages, languages_count: 15).languages.length # 15
480
+ ```
428
481
 
429
482
  Sequences
430
483
  ---------
431
484
 
432
485
  Unique values in a specific format (for example, e-mail addresses) can be
433
- generated using sequences. Sequences are defined by calling sequence in a
486
+ generated using sequences. Sequences are defined by calling `sequence` in a
434
487
  definition block, and values in a sequence are generated by calling
435
- FactoryGirl.generate:
488
+ `generate`:
436
489
 
437
490
  ```ruby
438
491
  # Defines a new sequence
@@ -442,26 +495,26 @@ FactoryGirl.define do
442
495
  end
443
496
  end
444
497
 
445
- FactoryGirl.generate :email
498
+ generate :email
446
499
  # => "person1@example.com"
447
500
 
448
- FactoryGirl.generate :email
501
+ generate :email
449
502
  # => "person2@example.com"
450
503
  ```
451
504
 
452
- Sequences can be used as attributes:
505
+ Sequences can be used in dynamic attributes:
453
506
 
454
507
  ```ruby
455
- factory :user do
456
- email
508
+ factory :invite do
509
+ invitee { generate(:email) }
457
510
  end
458
511
  ```
459
512
 
460
- Or in lazy attributes:
513
+ Or as implicit attributes:
461
514
 
462
515
  ```ruby
463
- factory :invite do
464
- invitee { generate(:email) }
516
+ factory :user do
517
+ email # Same as `email { generate(:email) }`
465
518
  end
466
519
  ```
467
520
 
@@ -470,7 +523,7 @@ a particular factory:
470
523
 
471
524
  ```ruby
472
525
  factory :user do
473
- sequence(:email) {|n| "person#{n}@example.com" }
526
+ sequence(:email) { |n| "person#{n}@example.com" }
474
527
  end
475
528
  ```
476
529
 
@@ -478,7 +531,7 @@ You can also override the initial value:
478
531
 
479
532
  ```ruby
480
533
  factory :user do
481
- sequence(:email, 1000) {|n| "person#{n}@example.com" }
534
+ sequence(:email, 1000) { |n| "person#{n}@example.com" }
482
535
  end
483
536
  ```
484
537
 
@@ -494,18 +547,18 @@ Sequences can also have aliases. The sequence aliases share the same counter:
494
547
 
495
548
  ```ruby
496
549
  factory :user do
497
- sequence(:email, 1000, aliases: [:sender, :receiver]) {|n| "person#{n}@example.com" }
550
+ sequence(:email, 1000, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
498
551
  end
499
552
 
500
553
  # will increase value counter for :email which is shared by :sender and :receiver
501
- FactoryGirl.next(:sender)
554
+ generate(:sender)
502
555
  ```
503
556
 
504
557
  Define aliases and use default value (1) for the counter
505
558
 
506
559
  ```ruby
507
560
  factory :user do
508
- sequence(:email, aliases: [:sender, :receiver]) {|n| "person#{n}@example.com" }
561
+ sequence(:email, aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
509
562
  end
510
563
  ```
511
564
 
@@ -513,7 +566,7 @@ Setting the value:
513
566
 
514
567
  ```ruby
515
568
  factory :user do
516
- sequence(:email, 'a', aliases: [:sender, :receiver]) {|n| "person#{n}@example.com" }
569
+ sequence(:email, 'a', aliases: [:sender, :receiver]) { |n| "person#{n}@example.com" }
517
570
  end
518
571
  ```
519
572
 
@@ -563,7 +616,7 @@ Traits can be used as attributes:
563
616
  factory :week_long_published_story_with_title, parent: :story do
564
617
  published
565
618
  week_long_publishing
566
- title { "Publishing that was started at {start_at}" }
619
+ title { "Publishing that was started at #{start_at}" }
567
620
  end
568
621
  ```
569
622
 
@@ -617,7 +670,7 @@ factory :user do
617
670
  end
618
671
  ```
619
672
 
620
- Traits can also be passed in as a list of symbols when you construct an instance from FactoryGirl.
673
+ Traits can also be passed in as a list of symbols when you construct an instance from factory_girl.
621
674
 
622
675
  ```ruby
623
676
  factory :user do
@@ -634,7 +687,7 @@ factory :user do
634
687
  end
635
688
 
636
689
  # creates an admin user with gender "Male" and name "Jon Snow"
637
- FactoryGirl.create(:user, :admin, :male, name: "Jon Snow")
690
+ create(:user, :admin, :male, name: "Jon Snow")
638
691
  ```
639
692
 
640
693
  This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
@@ -653,7 +706,7 @@ factory :user do
653
706
  end
654
707
 
655
708
  # creates 3 admin users with gender "Male" and name "Jon Snow"
656
- FactoryGirl.create_list(:user, 3, :admin, :male, name: "Jon Snow")
709
+ create_list(:user, 3, :admin, :male, name: "Jon Snow")
657
710
  ```
658
711
 
659
712
  Traits can be used with associations easily too:
@@ -672,7 +725,7 @@ factory :post do
672
725
  end
673
726
 
674
727
  # creates an admin user with name "John Doe"
675
- FactoryGirl.create(:post).user
728
+ create(:post).user
676
729
  ```
677
730
 
678
731
  When you're using association names that're different than the factory:
@@ -693,8 +746,42 @@ factory :post do
693
746
  end
694
747
 
695
748
  # creates an admin user with name "John Doe"
696
- FactoryGirl.create(:post).author
749
+ create(:post).author
750
+ ```
751
+
752
+ Traits can be used within other traits to mix in their attributes.
753
+
754
+ ```ruby
755
+ factory :order do
756
+ trait :completed do
757
+ completed_at { 3.days.ago }
758
+ end
759
+
760
+ trait :refunded do
761
+ completed
762
+ refunded_at { 1.day.ago }
763
+ end
764
+ end
697
765
  ```
766
+
767
+ Finally, traits can accept transient attributes.
768
+
769
+ ```ruby
770
+ factory :invoice do
771
+ trait :with_amount do
772
+ transient do
773
+ amount 1
774
+ end
775
+
776
+ after(:create) do |invoice, evaluator|
777
+ create :line_item, invoice: invoice, amount: evaluator.amount
778
+ end
779
+ end
780
+ end
781
+
782
+ create :invoice, :with_amount, amount: 2
783
+ ```
784
+
698
785
  Callbacks
699
786
  ---------
700
787
 
@@ -734,7 +821,7 @@ factory :user do
734
821
  end
735
822
  ```
736
823
 
737
- Calling FactoryGirl.create will invoke both `after_build` and `after_create` callbacks.
824
+ Calling `create` will invoke both `after_build` and `after_create` callbacks.
738
825
 
739
826
  Also, like standard attributes, child factories will inherit (and can also define) callbacks from their parent factory.
740
827
 
@@ -748,6 +835,40 @@ factory :user do
748
835
  end
749
836
  ```
750
837
 
838
+ To override callbacks for all factories, define them within the
839
+ `FactoryGirl.define` block:
840
+
841
+ ```ruby
842
+ FactoryGirl.define do
843
+ after(:build) { |object| puts "Built #{object}" }
844
+ after(:create) { |object| AuditLog.create(attrs: object.attributes) }
845
+
846
+ factory :user do
847
+ name "John Doe"
848
+ end
849
+ end
850
+ ```
851
+
852
+ You can also call callbacks that rely on `Symbol#to_proc`:
853
+
854
+ ```ruby
855
+ # app/models/user.rb
856
+ class User < ActiveRecord::Base
857
+ def confirm!
858
+ # confirm the user account
859
+ end
860
+ end
861
+
862
+ # spec/factories.rb
863
+ FactoryGirl.define do
864
+ factory :user do
865
+ after :create, &:confirm!
866
+ end
867
+ end
868
+
869
+ create(:user) # creates the user and confirms it
870
+ ```
871
+
751
872
  Modifying factories
752
873
  -------------------
753
874
 
@@ -760,7 +881,7 @@ If a gem were to give you a User factory:
760
881
  FactoryGirl.define do
761
882
  factory :user do
762
883
  full_name "John Doe"
763
- sequence(:username) {|n| "user#{n}" }
884
+ sequence(:username) { |n| "user#{n}" }
764
885
  password "password"
765
886
  end
766
887
  end
@@ -805,15 +926,108 @@ Building or Creating Multiple Records
805
926
  Sometimes, you'll want to create or build multiple instances of a factory at once.
806
927
 
807
928
  ```ruby
808
- built_users = FactoryGirl.build_list(:user, 25)
809
- created_users = FactoryGirl.create_list(:user, 25)
929
+ built_users = build_list(:user, 25)
930
+ created_users = create_list(:user, 25)
810
931
  ```
811
932
 
812
933
  These methods will build or create a specific amount of factories and return them as an array.
813
934
  To set the attributes for each of the factories, you can pass in a hash as you normally would.
814
935
 
815
936
  ```ruby
816
- twenty_year_olds = FactoryGirl.build_list(:user, 25, date_of_birth: 20.years.ago)
937
+ twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)
938
+ ```
939
+
940
+ `build_stubbed_list` will give you fully stubbed out instances:
941
+
942
+ ```ruby
943
+ stubbed_users = build_stubbed_list(:user, 25) # array of stubbed users
944
+ ```
945
+
946
+ There's also a set of `*_pair` methods for creating two records at a time:
947
+
948
+ ```ruby
949
+ built_users = build_pair(:user) # array of two built users
950
+ created_users = create_pair(:user) # array of two created users
951
+ ```
952
+
953
+ If you need multiple attribute hashes, `attributes_for_list` will generate them:
954
+
955
+ ```ruby
956
+ users_attrs = attributes_for_list(:user, 25) # array of attribute hashes
957
+ ```
958
+
959
+ Linting Factories
960
+ -----------------
961
+
962
+ factory_girl allows for linting known factories:
963
+
964
+ ```ruby
965
+ FactoryGirl.lint
966
+ ```
967
+
968
+ `FactoryGirl.lint` creates each factory and catches any exceptions raised
969
+ during the creation process. `FactoryGirl::InvalidFactoryError` is raised with
970
+ a list of factories (and corresponding exceptions) for factories which could
971
+ not be created.
972
+
973
+ Recommended usage of `FactoryGirl.lint`
974
+ is to run this in a task
975
+ before your test suite is executed.
976
+ Running it in a `before(:suite)`,
977
+ will negatively impact the performance
978
+ of your tests
979
+ when running single tests.
980
+
981
+ Example Rake task:
982
+
983
+ ```ruby
984
+ # lib/tasks/factory_girl.rake
985
+ namespace :factory_girl do
986
+ desc "Verify that all FactoryGirl factories are valid"
987
+ task lint: :environment do
988
+ if Rails.env.test?
989
+ begin
990
+ DatabaseCleaner.start
991
+ FactoryGirl.lint
992
+ ensure
993
+ DatabaseCleaner.clean
994
+ end
995
+ else
996
+ system("bundle exec rake factory_girl:lint RAILS_ENV='test'")
997
+ end
998
+ end
999
+ end
1000
+ ```
1001
+
1002
+ After calling `FactoryGirl.lint`, you'll likely want to clear out the
1003
+ database, as records will most likely be created. The provided example above
1004
+ uses the database_cleaner gem to clear out the database; be sure to add the
1005
+ gem to your Gemfile under the appropriate groups.
1006
+
1007
+ You can lint factories selectively by passing only factories you want linted:
1008
+
1009
+ ```ruby
1010
+ factories_to_lint = FactoryGirl.factories.reject do |factory|
1011
+ factory.name =~ /^old_/
1012
+ end
1013
+
1014
+ FactoryGirl.lint factories_to_lint
1015
+ ```
1016
+
1017
+ This would lint all factories that aren't prefixed with `old_`.
1018
+
1019
+ Traits can also be linted. This option verifies that each
1020
+ and every trait of a factory generates a valid object on its own.
1021
+ This is turned on by passing `traits: true` to the `lint` method:
1022
+
1023
+ ```ruby
1024
+ FactoryGirl.lint traits: true
1025
+ ```
1026
+
1027
+ This can also be combined with other arguments:
1028
+
1029
+ ```ruby
1030
+ FactoryGirl.lint factories_to_lint, traits: true
817
1031
  ```
818
1032
 
819
1033
  Custom Construction
@@ -835,26 +1049,21 @@ class User
835
1049
  end
836
1050
 
837
1051
  # factories.rb
838
- sequence(:name) {|n| "person#{n}@example.com" }
1052
+ sequence(:email) { |n| "person#{n}@example.com" }
839
1053
 
840
1054
  factory :user do
841
- ignore do
842
- name "Jane Doe"
843
- end
844
-
1055
+ name "Jane Doe"
845
1056
  email
1057
+
846
1058
  initialize_with { new(name) }
847
1059
  end
848
1060
 
849
- FactoryGirl.build(:user).name # Jane Doe
1061
+ build(:user).name # Jane Doe
850
1062
  ```
851
1063
 
852
- Notice that I ignored the `name` attribute. If you don't want attributes
853
- reassigned after your object has been instantiated, you'll want to `ignore` them.
854
-
855
1064
  Although factory_girl is written to work with ActiveRecord out of the box, it
856
- can also work with any Ruby class. For maximum compatibiltiy with ActiveRecord,
857
- the default initializer builds all instances by calling new on your build class
1065
+ can also work with any Ruby class. For maximum compatibility with ActiveRecord,
1066
+ the default initializer builds all instances by calling `new` on your build class
858
1067
  without any arguments. It then calls attribute writer methods to assign all the
859
1068
  attribute values. While that works fine for ActiveRecord, it actually doesn't
860
1069
  work for almost any other Ruby class.
@@ -873,9 +1082,7 @@ For example:
873
1082
 
874
1083
  ```ruby
875
1084
  factory :user do
876
- ignore do
877
- name "John Doe"
878
- end
1085
+ name "John Doe"
879
1086
 
880
1087
  initialize_with { User.build_with_name(name) }
881
1088
  end
@@ -886,7 +1093,7 @@ by calling `attributes`:
886
1093
 
887
1094
  ```ruby
888
1095
  factory :user do
889
- ignore do
1096
+ transient do
890
1097
  comments_count 5
891
1098
  end
892
1099
 
@@ -897,7 +1104,7 @@ end
897
1104
  ```
898
1105
 
899
1106
  This will build a hash of all attributes to be passed to `new`. It won't
900
- include ignored attributes, but everything else defined in the factory will be
1107
+ include transient attributes, but everything else defined in the factory will be
901
1108
  passed (associations, evalued sequences, etc.)
902
1109
 
903
1110
  You can define `initialize_with` for all factories by including it in the
@@ -922,12 +1129,12 @@ FactoryGirl.define do
922
1129
  end
923
1130
  end
924
1131
 
925
- FactoryGirl.build(:user)
1132
+ build(:user)
926
1133
  # runs
927
1134
  User.new('value')
928
1135
  ```
929
1136
 
930
- This prevents duplicate assignment; in versions of FactoryGirl before 4.0, it
1137
+ This prevents duplicate assignment; in versions of factory_girl before 4.0, it
931
1138
  would run this:
932
1139
 
933
1140
  ```ruby
@@ -939,7 +1146,7 @@ FactoryGirl.define do
939
1146
  end
940
1147
  end
941
1148
 
942
- FactoryGirl.build(:user)
1149
+ build(:user)
943
1150
  # runs
944
1151
  user = User.new('value')
945
1152
  user.name = 'value'
@@ -1022,9 +1229,9 @@ FactoryGirl.register_strategy(:json, JsonStrategy)
1022
1229
 
1023
1230
  FactoryGirl.define do
1024
1231
  factory :user do
1025
- before(:json) {|user| do_something_to(user) }
1026
- after(:json) {|user_json| do_something_to(user_json) }
1027
- callback(:make_json_awesome) {|user_json| do_something_to(user_json) }
1232
+ before(:json) { |user| do_something_to(user) }
1233
+ after(:json) { |user_json| do_something_to(user_json) }
1234
+ callback(:make_json_awesome) { |user_json| do_something_to(user_json) }
1028
1235
  end
1029
1236
  end
1030
1237
  ```
@@ -1038,7 +1245,7 @@ may not always be ideal, you can override that behavior by defining
1038
1245
 
1039
1246
  ```ruby
1040
1247
  factory :different_orm_model do
1041
- to_create {|instance| instance.persist! }
1248
+ to_create { |instance| instance.persist! }
1042
1249
  end
1043
1250
  ```
1044
1251
 
@@ -1056,7 +1263,7 @@ To override `to_create` for all factories, define it within the
1056
1263
 
1057
1264
  ```ruby
1058
1265
  FactoryGirl.define do
1059
- to_create {|instance| instance.persist! }
1266
+ to_create { |instance| instance.persist! }
1060
1267
 
1061
1268
 
1062
1269
  factory :user do
@@ -1088,18 +1295,93 @@ throughout your test suite. If you're using RSpec, it's as simple as adding a
1088
1295
  `before(:suite)` and `after(:suite)`:
1089
1296
 
1090
1297
  ```ruby
1298
+ factory_girl_results = {}
1091
1299
  config.before(:suite) do
1092
- @factory_girl_results = {}
1093
1300
  ActiveSupport::Notifications.subscribe("factory_girl.run_factory") do |name, start, finish, id, payload|
1094
1301
  factory_name = payload[:name]
1095
1302
  strategy_name = payload[:strategy]
1096
- @factory_girl_results[factory_name] ||= {}
1097
- @factory_girl_results[factory_name][strategy_name] ||= 0
1098
- @factory_girl_results[factory_name][strategy_name] += 1
1303
+ factory_girl_results[factory_name] ||= {}
1304
+ factory_girl_results[factory_name][strategy_name] ||= 0
1305
+ factory_girl_results[factory_name][strategy_name] += 1
1099
1306
  end
1100
1307
  end
1101
1308
 
1102
1309
  config.after(:suite) do
1103
- puts @factory_girl_results
1310
+ puts factory_girl_results
1311
+ end
1312
+ ```
1313
+
1314
+ Rails Preloaders and RSpec
1315
+ --------------------------
1316
+
1317
+ When running RSpec with a Rails preloader such as `spring` or `zeus`, it's possible
1318
+ to encounter an `ActiveRecord::AssociationTypeMismatch` error when creating a factory
1319
+ with associations, as below:
1320
+
1321
+ ```ruby
1322
+ FactoryGirl.define do
1323
+ factory :united_states, class: Location do
1324
+ name 'United States'
1325
+ association :location_group, factory: :north_america
1326
+ end
1327
+
1328
+ factory :north_america, class: LocationGroup do
1329
+ name 'North America'
1330
+ end
1331
+ end
1332
+ ```
1333
+
1334
+ The error occurs during the run of the test suite:
1335
+
1336
+ ```
1337
+ Failure/Error: united_states = create(:united_states)
1338
+ ActiveRecord::AssociationTypeMismatch:
1339
+ LocationGroup(#70251250797320) expected, got LocationGroup(#70251200725840)
1340
+ ```
1341
+
1342
+ The two possible solutions are to either run the suite without the preloader, or
1343
+ to add `FactoryGirl.reload` to the RSpec configuration, like so:
1344
+
1345
+ ```ruby
1346
+ RSpec.configure do |config|
1347
+ config.before(:suite) { FactoryGirl.reload }
1348
+ end
1349
+ ```
1350
+
1351
+ Using Without Bundler
1352
+ ---------------------
1353
+
1354
+ If you're not using Bundler, be sure to have the gem installed and call:
1355
+
1356
+ ```ruby
1357
+ require 'factory_girl'
1358
+ ```
1359
+
1360
+ Once required, assuming you have a directory structure of `spec/factories` or
1361
+ `test/factories`, all you'll need to do is run
1362
+
1363
+ ```ruby
1364
+ FactoryGirl.find_definitions
1365
+ ```
1366
+
1367
+ If you're using a separate directory structure for your factories, you can
1368
+ change the definition file paths before trying to find definitions:
1369
+
1370
+ ```ruby
1371
+ FactoryGirl.definition_file_paths = %w(custom_factories_directory)
1372
+ FactoryGirl.find_definitions
1373
+ ```
1374
+
1375
+ If you don't have a separate directory of factories and would like to define
1376
+ them inline, that's possible as well:
1377
+
1378
+ ```ruby
1379
+ require 'factory_girl'
1380
+
1381
+ FactoryGirl.define do
1382
+ factory :user do
1383
+ name 'John Doe'
1384
+ date_of_birth { 21.years.ago }
1385
+ end
1104
1386
  end
1105
1387
  ```