factory_girl 2.3.2 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +5 -3
- data/Appraisals +4 -0
- data/CONTRIBUTION_GUIDELINES.md +1 -1
- data/Changelog +13 -0
- data/GETTING_STARTED.md +362 -286
- data/Gemfile.lock +1 -1
- data/README.md +8 -8
- data/features/factory_girl_steps.feature +4 -0
- data/features/support/factories.rb +19 -0
- data/gemfiles/2.1.gemfile.lock +1 -1
- data/gemfiles/2.3.gemfile.lock +1 -1
- data/gemfiles/3.0.gemfile.lock +1 -1
- data/gemfiles/3.1.gemfile.lock +1 -1
- data/gemfiles/3.2.gemfile +7 -0
- data/gemfiles/3.2.gemfile.lock +90 -0
- data/lib/factory_girl.rb +4 -0
- data/lib/factory_girl/attribute.rb +1 -9
- data/lib/factory_girl/attribute/association.rb +2 -2
- data/lib/factory_girl/attribute/dynamic.rb +2 -2
- data/lib/factory_girl/attribute/sequence.rb +1 -1
- data/lib/factory_girl/attribute/static.rb +1 -1
- data/lib/factory_girl/attribute_assigner.rb +73 -0
- data/lib/factory_girl/attribute_list.rb +6 -15
- data/lib/factory_girl/callback.rb +2 -2
- data/lib/factory_girl/evaluator.rb +57 -0
- data/lib/factory_girl/evaluator_class_definer.rb +34 -0
- data/lib/factory_girl/factory.rb +31 -80
- data/lib/factory_girl/null_factory.rb +2 -1
- data/lib/factory_girl/null_object.rb +19 -0
- data/lib/factory_girl/proxy.rb +6 -87
- data/lib/factory_girl/proxy/attributes_for.rb +2 -7
- data/lib/factory_girl/proxy/build.rb +4 -3
- data/lib/factory_girl/proxy/create.rb +6 -7
- data/lib/factory_girl/proxy/stub.rb +19 -18
- data/lib/factory_girl/step_definitions.rb +4 -3
- data/lib/factory_girl/version.rb +1 -1
- data/spec/acceptance/aliases_spec.rb +19 -0
- data/spec/acceptance/attributes_for_spec.rb +10 -1
- data/spec/acceptance/attributes_from_instance_spec.rb +53 -0
- data/spec/acceptance/build_spec.rb +8 -0
- data/spec/acceptance/build_stubbed_spec.rb +9 -0
- data/spec/acceptance/create_spec.rb +8 -0
- data/spec/factory_girl/attribute/association_spec.rb +5 -4
- data/spec/factory_girl/attribute/dynamic_spec.rb +9 -10
- data/spec/factory_girl/attribute/sequence_spec.rb +1 -2
- data/spec/factory_girl/attribute/static_spec.rb +1 -2
- data/spec/factory_girl/attribute_list_spec.rb +14 -4
- data/spec/factory_girl/evaluator_class_definer_spec.rb +54 -0
- data/spec/factory_girl/factory_spec.rb +23 -16
- data/spec/factory_girl/null_factory_spec.rb +2 -1
- data/spec/factory_girl/null_object_spec.rb +8 -0
- data/spec/factory_girl/proxy/attributes_for_spec.rb +8 -24
- data/spec/factory_girl/proxy/build_spec.rb +1 -7
- data/spec/factory_girl/proxy/create_spec.rb +2 -27
- data/spec/factory_girl/proxy/stub_spec.rb +14 -13
- data/spec/factory_girl/proxy_spec.rb +1 -33
- data/spec/support/shared_examples/proxy.rb +22 -45
- metadata +133 -177
data/.travis.yml
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
rvm:
|
2
|
-
- ree-1.8.7
|
3
|
-
- 1.8.7
|
4
|
-
- 1.9.2
|
2
|
+
- ree-1.8.7
|
3
|
+
- 1.8.7
|
4
|
+
- 1.9.2
|
5
|
+
- 1.9.3
|
5
6
|
script: "bundle exec rake spec:unit spec:acceptance features"
|
6
7
|
gemfile:
|
7
8
|
- gemfiles/2.1.gemfile
|
8
9
|
- gemfiles/2.3.gemfile
|
9
10
|
- gemfiles/3.0.gemfile
|
10
11
|
- gemfiles/3.1.gemfile
|
12
|
+
- gemfiles/3.2.gemfile
|
11
13
|
branches:
|
12
14
|
only:
|
13
15
|
- master
|
data/Appraisals
CHANGED
data/CONTRIBUTION_GUIDELINES.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Contributing to factory\_girl:
|
2
2
|
|
3
|
-
1. Fork the [official repository](
|
3
|
+
1. Fork the [official repository](https://github.com/thoughtbot/factory_girl/tree/master).
|
4
4
|
2. Make your changes in a topic branch.
|
5
5
|
3. Send a pull request.
|
6
6
|
|
data/Changelog
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
2.4.0 (January 13, 2012)
|
2
|
+
Refactor internals of Factory Girl to use anonymous class on which attributes
|
3
|
+
get defined
|
4
|
+
Explicitly require Ruby 1.8.7 or higher in gemspec
|
5
|
+
Fix documentation
|
6
|
+
Add Gemnasium status to documentation
|
7
|
+
Supplying a Class to a factory that overrides to_s no longer results in
|
8
|
+
getting the wrong Class constructed
|
9
|
+
Be more agnostic about ORMs when using columns in Factory Girl step
|
10
|
+
definitions
|
11
|
+
Test against Active Record 3.2.0.rc2
|
12
|
+
Update GETTING_STARTED to use Ruby syntax highlighting
|
13
|
+
|
1
14
|
2.3.2 (November 26, 2011)
|
2
15
|
Move logic of where instance.save! is set to Definition
|
3
16
|
Fix method name from aliases_for? to alias_for?
|
data/GETTING_STARTED.md
CHANGED
@@ -6,11 +6,15 @@ Update Your Gemfile
|
|
6
6
|
|
7
7
|
If you're using Rails, you'll need to change the required version of `factory_girl_rails`:
|
8
8
|
|
9
|
-
|
9
|
+
```ruby
|
10
|
+
gem "factory_girl_rails", "~> 1.2"
|
11
|
+
```
|
10
12
|
|
11
13
|
If you're *not* using Rails, you'll just have to change the required version of `factory_girl`:
|
12
14
|
|
13
|
-
|
15
|
+
```ruby
|
16
|
+
gem "factory_girl", "~> 2.1.0"
|
17
|
+
```
|
14
18
|
|
15
19
|
Once your Gemfile is updated, you'll want to update your bundle.
|
16
20
|
|
@@ -19,28 +23,30 @@ Defining factories
|
|
19
23
|
|
20
24
|
Each factory has a name and a set of attributes. The name is used to guess the class of the object by default, but it's possible to explicitly specify it:
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
26
|
+
```ruby
|
27
|
+
# This will guess the User class
|
28
|
+
FactoryGirl.define do
|
29
|
+
factory :user do
|
30
|
+
first_name 'John'
|
31
|
+
last_name 'Doe'
|
32
|
+
admin false
|
33
|
+
end
|
34
|
+
|
35
|
+
# This will use the User class (Admin would have been guessed)
|
36
|
+
factory :admin, :class => User do
|
37
|
+
first_name 'Admin'
|
38
|
+
last_name 'User'
|
39
|
+
admin true
|
40
|
+
end
|
41
|
+
|
42
|
+
# The same, but using a string instead of class constant
|
43
|
+
factory :admin, :class => 'user' do
|
44
|
+
first_name 'Admin'
|
45
|
+
last_name 'User'
|
46
|
+
admin true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
44
50
|
|
45
51
|
It is highly recommended that you have one factory for each class that provides the simplest set of attributes necessary to create an instance of that class. If you're creating ActiveRecord objects, that means that you should only provide attributes that are required through validations and that do not have defaults. Other factories can be created through inheritance to cover common scenarios for each class.
|
46
52
|
|
@@ -59,49 +65,57 @@ Using factories
|
|
59
65
|
|
60
66
|
factory\_girl supports several different build strategies: build, create, attributes\_for and stub:
|
61
67
|
|
62
|
-
|
63
|
-
|
68
|
+
```ruby
|
69
|
+
# Returns a User instance that's not saved
|
70
|
+
user = FactoryGirl.build(:user)
|
64
71
|
|
65
|
-
|
66
|
-
|
72
|
+
# Returns a saved User instance
|
73
|
+
user = FactoryGirl.create(:user)
|
67
74
|
|
68
|
-
|
69
|
-
|
75
|
+
# Returns a hash of attributes that can be used to build a User instance
|
76
|
+
attrs = FactoryGirl.attributes_for(:user)
|
70
77
|
|
71
|
-
|
72
|
-
|
78
|
+
# Returns an object with all defined attributes stubbed out
|
79
|
+
stub = FactoryGirl.build_stubbed(:user)
|
73
80
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
81
|
+
# Passing a block to any of the methods above will yield the return object
|
82
|
+
FactoryGirl.create(:user) do |user|
|
83
|
+
user.posts.create(attributes_for(:post))
|
84
|
+
end
|
85
|
+
```
|
78
86
|
|
79
87
|
No matter which strategy is used, it's possible to override the defined attributes by passing a hash:
|
80
88
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
89
|
+
```ruby
|
90
|
+
# Build a User instance and override the first_name property
|
91
|
+
user = FactoryGirl.build(:user, :first_name => 'Joe')
|
92
|
+
user.first_name
|
93
|
+
# => "Joe"
|
94
|
+
```
|
85
95
|
|
86
96
|
If repeating "FactoryGirl" is too verbose for you, you can mix the syntax methods in:
|
87
97
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
98
|
+
```ruby
|
99
|
+
# rspec
|
100
|
+
RSpec.configure do |config|
|
101
|
+
config.include FactoryGirl::Syntax::Methods
|
102
|
+
end
|
92
103
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
104
|
+
# Test::Unit
|
105
|
+
class Test::Unit::TestCase
|
106
|
+
include Factory::Syntax::Methods
|
107
|
+
end
|
108
|
+
```
|
97
109
|
|
98
110
|
This would allow you to write:
|
99
111
|
|
100
|
-
|
101
|
-
|
112
|
+
```ruby
|
113
|
+
describe User, "#full_name" do
|
114
|
+
subject { create(:user, :first_name => "John", :last_name => "Doe") }
|
102
115
|
|
103
|
-
|
104
|
-
|
116
|
+
its(:full_name) { should == "John Doe" }
|
117
|
+
end
|
118
|
+
```
|
105
119
|
|
106
120
|
Lazy Attributes
|
107
121
|
---------------
|
@@ -112,73 +126,81 @@ attributes that must be dynamically generated) will need values assigned each
|
|
112
126
|
time an instance is generated. These "lazy" attributes can be added by passing a
|
113
127
|
block instead of a parameter:
|
114
128
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
129
|
+
```ruby
|
130
|
+
factory :user do
|
131
|
+
# ...
|
132
|
+
activation_code { User.generate_activation_code }
|
133
|
+
date_of_birth { 21.years.ago }
|
134
|
+
end
|
135
|
+
```
|
120
136
|
|
121
137
|
Aliases
|
122
138
|
-------
|
123
139
|
|
124
140
|
Aliases allow you to use named associations more easily.
|
125
141
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
142
|
+
```ruby
|
143
|
+
factory :user, :aliases => [:author, :commenter] do
|
144
|
+
first_name "John"
|
145
|
+
last_name "Doe"
|
146
|
+
date_of_birth { 18.years.ago }
|
147
|
+
end
|
148
|
+
|
149
|
+
factory :post do
|
150
|
+
author
|
151
|
+
# instead of
|
152
|
+
# association :author, :factory => :user
|
153
|
+
title "How to read a book effectively"
|
154
|
+
body "There are five steps involved."
|
155
|
+
end
|
156
|
+
|
157
|
+
factory :comment do
|
158
|
+
commenter
|
159
|
+
# instead of
|
160
|
+
# association :commenter, :factory => :user
|
161
|
+
body "Great article!"
|
162
|
+
end
|
163
|
+
```
|
146
164
|
|
147
165
|
Dependent Attributes
|
148
166
|
--------------------
|
149
167
|
|
150
168
|
Attributes can be based on the values of other attributes using the proxy that is yielded to lazy attribute blocks:
|
151
169
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
170
|
+
```ruby
|
171
|
+
factory :user do
|
172
|
+
first_name 'Joe'
|
173
|
+
last_name 'Blow'
|
174
|
+
email { "#{first_name}.#{last_name}@example.com".downcase }
|
175
|
+
end
|
157
176
|
|
158
|
-
|
159
|
-
|
177
|
+
FactoryGirl.create(:user, :last_name => 'Doe').email
|
178
|
+
# => "joe.doe@example.com"
|
179
|
+
```
|
160
180
|
|
161
181
|
Transient Attributes
|
162
182
|
--------------------
|
163
183
|
|
164
184
|
There may be times where your code can be DRYed up by passing in transient attributes to factories.
|
165
185
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
186
|
+
```ruby
|
187
|
+
factory :user do
|
188
|
+
ignore do
|
189
|
+
rockstar true
|
190
|
+
upcased { false }
|
191
|
+
end
|
171
192
|
|
172
|
-
|
173
|
-
|
193
|
+
name { "John Doe#{" - Rockstar" if rockstar}" }
|
194
|
+
email { "#{name.downcase}@example.com" }
|
174
195
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
196
|
+
after_create do |user, proxy|
|
197
|
+
user.name.upcase! if proxy.upcased
|
198
|
+
end
|
199
|
+
end
|
179
200
|
|
180
|
-
|
181
|
-
|
201
|
+
FactoryGirl.create(:user, :upcased => true).name
|
202
|
+
#=> "JOHN DOE - ROCKSTAR"
|
203
|
+
```
|
182
204
|
|
183
205
|
Static and dynamic attributes can be ignored. Ignored attributes will be ignored
|
184
206
|
within attributes\_for and won't be set on the model, even if the attribute
|
@@ -194,68 +216,80 @@ Associations
|
|
194
216
|
|
195
217
|
It's possible to set up associations within factories. If the factory name is the same as the association name, the factory name can be left out.
|
196
218
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
219
|
+
```ruby
|
220
|
+
factory :post do
|
221
|
+
# ...
|
222
|
+
author
|
223
|
+
end
|
224
|
+
```
|
201
225
|
|
202
226
|
You can also specify a different factory or override attributes:
|
203
227
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
228
|
+
```ruby
|
229
|
+
factory :post do
|
230
|
+
# ...
|
231
|
+
association :author, :factory => :user, :last_name => 'Writely'
|
232
|
+
end
|
233
|
+
```
|
208
234
|
|
209
235
|
The behavior of the association method varies depending on the build strategy used for the parent object.
|
210
236
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
237
|
+
```ruby
|
238
|
+
# Builds and saves a User and a Post
|
239
|
+
post = FactoryGirl.create(:post)
|
240
|
+
post.new_record? # => false
|
241
|
+
post.author.new_record? # => false
|
215
242
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
243
|
+
# Builds and saves a User, and then builds but does not save a Post
|
244
|
+
post = FactoryGirl.build(:post)
|
245
|
+
post.new_record? # => true
|
246
|
+
post.author.new_record? # => false
|
247
|
+
```
|
220
248
|
|
221
249
|
To not save the associated object, specify :method => :build in the factory:
|
222
250
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
251
|
+
```ruby
|
252
|
+
factory :post do
|
253
|
+
# ...
|
254
|
+
association :author, :factory => :user, :method => :build
|
255
|
+
end
|
227
256
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
257
|
+
# Builds a User, and then builds a Post, but does not save either
|
258
|
+
post = FactoryGirl.build(:post)
|
259
|
+
post.new_record? # => true
|
260
|
+
post.author.new_record? # => true
|
261
|
+
```
|
232
262
|
|
233
263
|
Inheritance
|
234
264
|
-----------
|
235
265
|
|
236
266
|
You can easily create multiple factories for the same class without repeating common attributes by nesting factories:
|
237
267
|
|
238
|
-
|
239
|
-
|
268
|
+
```ruby
|
269
|
+
factory :post do
|
270
|
+
title 'A title'
|
240
271
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
272
|
+
factory :approved_post do
|
273
|
+
approved true
|
274
|
+
end
|
275
|
+
end
|
245
276
|
|
246
|
-
|
247
|
-
|
248
|
-
|
277
|
+
approved_post = FactoryGirl.create(:approved_post)
|
278
|
+
approved_post.title # => 'A title'
|
279
|
+
approved_post.approved # => true
|
280
|
+
```
|
249
281
|
|
250
282
|
You can also assign the parent explicitly:
|
251
283
|
|
252
|
-
|
253
|
-
|
254
|
-
|
284
|
+
```ruby
|
285
|
+
factory :post do
|
286
|
+
title 'A title'
|
287
|
+
end
|
255
288
|
|
256
|
-
|
257
|
-
|
258
|
-
|
289
|
+
factory :approved_post, :parent => :post do
|
290
|
+
approved true
|
291
|
+
end
|
292
|
+
```
|
259
293
|
|
260
294
|
As mentioned above, it's good practice to define a basic factory for each class
|
261
295
|
with only the attributes required to create it. Then, create more specific
|
@@ -270,49 +304,61 @@ generated using sequences. Sequences are defined by calling sequence in a
|
|
270
304
|
definition block, and values in a sequence are generated by calling
|
271
305
|
FactoryGirl.generate:
|
272
306
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
307
|
+
```ruby
|
308
|
+
# Defines a new sequence
|
309
|
+
FactoryGirl.define do
|
310
|
+
sequence :email do |n|
|
311
|
+
"person#{n}@example.com"
|
312
|
+
end
|
313
|
+
end
|
279
314
|
|
280
|
-
|
281
|
-
|
315
|
+
FactoryGirl.generate :email
|
316
|
+
# => "person1@example.com"
|
282
317
|
|
283
|
-
|
284
|
-
|
318
|
+
FactoryGirl.generate :email
|
319
|
+
# => "person2@example.com"
|
320
|
+
```
|
285
321
|
|
286
322
|
Sequences can be used as attributes:
|
287
323
|
|
288
|
-
|
289
|
-
|
290
|
-
|
324
|
+
```ruby
|
325
|
+
factory :user do
|
326
|
+
email
|
327
|
+
end
|
328
|
+
```
|
291
329
|
|
292
330
|
Or in lazy attributes:
|
293
331
|
|
294
|
-
|
295
|
-
|
296
|
-
|
332
|
+
```ruby
|
333
|
+
factory :invite do
|
334
|
+
invitee { FactoryGirl.generate(:email) }
|
335
|
+
end
|
336
|
+
```
|
297
337
|
|
298
338
|
And it's also possible to define an in-line sequence that is only used in
|
299
339
|
a particular factory:
|
300
340
|
|
301
|
-
|
302
|
-
|
303
|
-
|
341
|
+
```ruby
|
342
|
+
factory :user do
|
343
|
+
sequence(:email) {|n| "person#{n}@example.com" }
|
344
|
+
end
|
345
|
+
```
|
304
346
|
|
305
347
|
You can also override the initial value:
|
306
348
|
|
307
|
-
|
308
|
-
|
309
|
-
|
349
|
+
```ruby
|
350
|
+
factory :user do
|
351
|
+
sequence(:email, 1000) {|n| "person#{n}@example.com" }
|
352
|
+
end
|
353
|
+
```
|
310
354
|
|
311
355
|
Without a block, the value will increment itself, starting at its initial value:
|
312
356
|
|
313
|
-
|
314
|
-
|
315
|
-
|
357
|
+
```ruby
|
358
|
+
factory :post do
|
359
|
+
sequence(:position)
|
360
|
+
end
|
361
|
+
```
|
316
362
|
|
317
363
|
Traits
|
318
364
|
------
|
@@ -320,107 +366,117 @@ Traits
|
|
320
366
|
Traits allow you to group attributes together and then apply them
|
321
367
|
to any factory.
|
322
368
|
|
323
|
-
|
369
|
+
```ruby
|
370
|
+
factory :user, :aliases => [:author]
|
324
371
|
|
325
|
-
|
326
|
-
|
327
|
-
|
372
|
+
factory :story do
|
373
|
+
title "My awesome story"
|
374
|
+
author
|
328
375
|
|
329
|
-
|
330
|
-
|
331
|
-
|
376
|
+
trait :published do
|
377
|
+
published true
|
378
|
+
end
|
332
379
|
|
333
|
-
|
334
|
-
|
335
|
-
|
380
|
+
trait :unpublished do
|
381
|
+
published false
|
382
|
+
end
|
336
383
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
384
|
+
trait :week_long_publishing do
|
385
|
+
start_at { 1.week.ago }
|
386
|
+
end_at { Time.now }
|
387
|
+
end
|
341
388
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
389
|
+
trait :month_long_publishing do
|
390
|
+
start_at { 1.month.ago }
|
391
|
+
end_at { Time.now }
|
392
|
+
end
|
346
393
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
394
|
+
factory :week_long_published_story, :traits => [:published, :week_long_publishing]
|
395
|
+
factory :month_long_published_story, :traits => [:published, :month_long_publishing]
|
396
|
+
factory :week_long_unpublished_story, :traits => [:unpublished, :week_long_publishing]
|
397
|
+
factory :month_long_unpublished_story, :traits => [:unpublished, :month_long_publishing]
|
398
|
+
end
|
399
|
+
```
|
352
400
|
|
353
401
|
Traits can be used as attributes:
|
354
402
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
403
|
+
```ruby
|
404
|
+
factory :week_long_published_story_with_title, :parent => :story do
|
405
|
+
published
|
406
|
+
week_long_publishing
|
407
|
+
title { "Publishing that was started at {start_at}" }
|
408
|
+
end
|
409
|
+
```
|
360
410
|
|
361
411
|
Traits that define the same attributes won't raise AttributeDefinitionErrors;
|
362
412
|
the trait that defines the attribute latest gets precedence.
|
363
413
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
414
|
+
```ruby
|
415
|
+
factory :user do
|
416
|
+
name "Friendly User"
|
417
|
+
login { name }
|
418
|
+
|
419
|
+
trait :male do
|
420
|
+
name "John Doe"
|
421
|
+
gender "Male"
|
422
|
+
login { "#{name} (M)" }
|
423
|
+
end
|
424
|
+
|
425
|
+
trait :female do
|
426
|
+
name "Jane Doe"
|
427
|
+
gender "Female"
|
428
|
+
login { "#{name} (F)" }
|
429
|
+
end
|
430
|
+
|
431
|
+
trait :admin do
|
432
|
+
admin true
|
433
|
+
login { "admin-#{name}" }
|
434
|
+
end
|
435
|
+
|
436
|
+
factory :male_admin, :traits => [:male, :admin] # login will be "admin-John Doe"
|
437
|
+
factory :female_admin, :traits => [:admin, :female] # login will be "Jane Doe (F)"
|
438
|
+
end
|
439
|
+
```
|
388
440
|
|
389
441
|
You can also override individual attributes granted by a trait in subclasses.
|
390
442
|
|
391
|
-
|
392
|
-
|
393
|
-
|
443
|
+
```ruby
|
444
|
+
factory :user do
|
445
|
+
name "Friendly User"
|
446
|
+
login { name }
|
394
447
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
448
|
+
trait :male do
|
449
|
+
name "John Doe"
|
450
|
+
gender "Male"
|
451
|
+
login { "#{name} (M)" }
|
452
|
+
end
|
400
453
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
454
|
+
factory :brandon do
|
455
|
+
male
|
456
|
+
name "Brandon"
|
457
|
+
end
|
458
|
+
end
|
459
|
+
```
|
406
460
|
|
407
461
|
Traits can also be passed in as a list of symbols when you construct an instance from FactoryGirl.
|
408
462
|
|
409
|
-
|
410
|
-
|
463
|
+
```ruby
|
464
|
+
factory :user do
|
465
|
+
name "Friendly User"
|
411
466
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
467
|
+
trait :male do
|
468
|
+
name "John Doe"
|
469
|
+
gender "Male"
|
470
|
+
end
|
416
471
|
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
472
|
+
trait :admin do
|
473
|
+
admin true
|
474
|
+
end
|
475
|
+
end
|
421
476
|
|
422
|
-
|
423
|
-
|
477
|
+
# creates an admin user with gender "Male" and name "Jon Snow"
|
478
|
+
FactoryGirl.create(:user, :admin, :male, :name => "Jon Snow")
|
479
|
+
```
|
424
480
|
|
425
481
|
This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
|
426
482
|
|
@@ -435,26 +491,32 @@ factory\_girl makes available three callbacks for injecting some code:
|
|
435
491
|
|
436
492
|
Examples:
|
437
493
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
494
|
+
```ruby
|
495
|
+
# Define a factory that calls the generate_hashed_password method after it is built
|
496
|
+
factory :user do
|
497
|
+
after_build { |user| generate_hashed_password(user) }
|
498
|
+
end
|
499
|
+
```
|
442
500
|
|
443
501
|
Note that you'll have an instance of the user in the block. This can be useful.
|
444
502
|
|
445
503
|
You can also define multiple types of callbacks on the same factory:
|
446
504
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
505
|
+
```ruby
|
506
|
+
factory :user do
|
507
|
+
after_build { |user| do_something_to(user) }
|
508
|
+
after_create { |user| do_something_else_to(user) }
|
509
|
+
end
|
510
|
+
```
|
451
511
|
|
452
512
|
Factories can also define any number of the same kind of callback. These callbacks will be executed in the order they are specified:
|
453
513
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
514
|
+
```ruby
|
515
|
+
factory :user do
|
516
|
+
after_create { this_runs_first }
|
517
|
+
after_create { then_this }
|
518
|
+
end
|
519
|
+
```
|
458
520
|
|
459
521
|
Calling FactoryGirl.create will invoke both after\_build and after\_create callbacks.
|
460
522
|
|
@@ -468,35 +530,41 @@ modify that factory instead of creating a child factory and adding attributes th
|
|
468
530
|
|
469
531
|
If a gem were to give you a User factory:
|
470
532
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
533
|
+
```ruby
|
534
|
+
FactoryGirl.define do
|
535
|
+
factory :user do
|
536
|
+
full_name "John Doe"
|
537
|
+
sequence(:username) {|n| "user#{n}" }
|
538
|
+
password "password"
|
539
|
+
end
|
540
|
+
end
|
541
|
+
```
|
478
542
|
|
479
543
|
Instead of creating a child factory that added additional attributes:
|
480
544
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
545
|
+
```ruby
|
546
|
+
FactoryGirl.define do
|
547
|
+
factory :application_user, :parent => :user do
|
548
|
+
full_name { Faker::Name.name }
|
549
|
+
date_of_birth { 21.years.ago }
|
550
|
+
gender "Female"
|
551
|
+
health 90
|
552
|
+
end
|
553
|
+
end
|
554
|
+
```
|
489
555
|
|
490
556
|
You could modify that factory instead.
|
491
557
|
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
558
|
+
```ruby
|
559
|
+
FactoryGirl.modify do
|
560
|
+
factory :user do
|
561
|
+
full_name { Faker::Name.name }
|
562
|
+
date_of_birth { 21.years.ago }
|
563
|
+
gender "Female"
|
564
|
+
health 90
|
565
|
+
end
|
566
|
+
end
|
567
|
+
```
|
500
568
|
|
501
569
|
When modifying a factory, you can change any of the attributes you want (aside from callbacks).
|
502
570
|
|
@@ -510,20 +578,26 @@ Building or Creating Multiple Records
|
|
510
578
|
|
511
579
|
Sometimes, you'll want to create or build multiple instances of a factory at once.
|
512
580
|
|
513
|
-
|
514
|
-
|
581
|
+
```ruby
|
582
|
+
built_users = FactoryGirl.build_list(:user, 25)
|
583
|
+
created_users = FactoryGirl.create_list(:user, 25)
|
584
|
+
```
|
515
585
|
|
516
586
|
These methods will build or create a specific amount of factories and return them as an array.
|
517
587
|
To set the attributes for each of the factories, you can pass in a hash as you normally would.
|
518
588
|
|
519
|
-
|
589
|
+
```ruby
|
590
|
+
twenty_year_olds = FactoryGirl.build_list(:user, 25, :date_of_birth => 20.years.ago)
|
591
|
+
```
|
520
592
|
|
521
593
|
Cucumber Integration
|
522
594
|
--------------------
|
523
595
|
|
524
596
|
factory\_girl ships with step definitions that make calling factories from Cucumber easier. To use them, add the following to features/support/env.rb:
|
525
597
|
|
526
|
-
|
598
|
+
```ruby
|
599
|
+
require 'factory_girl/step_definitions'
|
600
|
+
```
|
527
601
|
|
528
602
|
Alternate Syntaxes
|
529
603
|
------------------
|
@@ -533,15 +607,17 @@ common feature set. Because of this factory\_girl supports "syntax layers" which
|
|
533
607
|
provide alternate interfaces. See Factory::Syntax for information about the
|
534
608
|
various layers available. For example, the Machinist-style syntax is popular:
|
535
609
|
|
536
|
-
|
537
|
-
|
538
|
-
|
610
|
+
```ruby
|
611
|
+
require 'factory_girl/syntax/blueprint'
|
612
|
+
require 'factory_girl/syntax/make'
|
613
|
+
require 'factory_girl/syntax/sham'
|
539
614
|
|
540
|
-
|
615
|
+
Sham.email {|n| "#{n}@example.com" }
|
541
616
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
617
|
+
User.blueprint do
|
618
|
+
name { 'Billy Bob' }
|
619
|
+
email { Sham.email }
|
620
|
+
end
|
546
621
|
|
547
|
-
|
622
|
+
User.make(:name => 'Johnny')
|
623
|
+
```
|