vitalish-factory_girl 1.2.5 → 1.2.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +67 -121
- data/Rakefile +103 -29
- data/VERSION +1 -0
- data/lib/factory_girl/aliases.rb +32 -3
- data/lib/factory_girl/attribute/association.rb +1 -1
- data/lib/factory_girl/attribute/callback.rb +1 -1
- data/lib/factory_girl/attribute/dynamic.rb +3 -3
- data/lib/factory_girl/attribute/static.rb +1 -1
- data/lib/factory_girl/attribute.rb +3 -3
- data/lib/factory_girl/factory.rb +354 -164
- data/lib/factory_girl/proxy/attributes_for.rb +1 -1
- data/lib/factory_girl/proxy/build.rb +5 -7
- data/lib/factory_girl/proxy/create.rb +3 -2
- data/lib/factory_girl/proxy/stub.rb +5 -19
- data/lib/factory_girl/proxy.rb +23 -7
- data/lib/factory_girl/sequence.rb +40 -5
- data/lib/factory_girl/step_definitions.rb +13 -19
- data/lib/factory_girl/syntax/blueprint.rb +5 -5
- data/lib/factory_girl/syntax/generate.rb +8 -13
- data/lib/factory_girl/syntax/make.rb +7 -9
- data/lib/factory_girl/syntax/sham.rb +8 -11
- data/lib/factory_girl/syntax.rb +7 -7
- data/lib/factory_girl.rb +19 -8
- data/spec/factory_girl/aliases_spec.rb +5 -9
- data/spec/factory_girl/attribute/association_spec.rb +4 -4
- data/spec/factory_girl/attribute/callback_spec.rb +4 -4
- data/spec/factory_girl/attribute/dynamic_spec.rb +10 -21
- data/spec/factory_girl/attribute/static_spec.rb +6 -6
- data/spec/factory_girl/attribute_spec.rb +6 -6
- data/spec/factory_girl/factory_spec.rb +465 -305
- data/spec/factory_girl/proxy/attributes_for_spec.rb +3 -3
- data/spec/factory_girl/proxy/build_spec.rb +13 -18
- data/spec/factory_girl/proxy/create_spec.rb +13 -18
- data/spec/factory_girl/proxy/stub_spec.rb +6 -7
- data/spec/factory_girl/proxy_spec.rb +3 -3
- data/spec/factory_girl/sequence_spec.rb +39 -16
- data/spec/factory_girl/syntax/blueprint_spec.rb +34 -0
- data/spec/factory_girl/syntax/generate_spec.rb +57 -0
- data/spec/factory_girl/syntax/make_spec.rb +35 -0
- data/spec/factory_girl/syntax/sham_spec.rb +35 -0
- data/spec/integration_spec.rb +304 -0
- data/spec/models.rb +43 -0
- data/spec/spec_helper.rb +10 -85
- metadata +15 -3
data/README.rdoc
CHANGED
@@ -1,56 +1,49 @@
|
|
1
|
-
= NOTE: this documentation is for the beta version of factory_girl 2
|
2
|
-
|
3
|
-
Up-to-date documentation for the stable branch can be found here:
|
4
|
-
|
5
|
-
http://github.com/thoughtbot/factory_girl/tree/1.3.x
|
6
|
-
|
7
1
|
= factory_girl
|
8
2
|
|
9
3
|
factory_girl is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance.
|
10
4
|
|
11
|
-
If you want to use factory_girl with Rails 3, see
|
12
|
-
http://github.com/thoughtbot/factory_girl_rails
|
13
|
-
|
14
5
|
== Download
|
15
6
|
|
16
7
|
Github: http://github.com/thoughtbot/factory_girl/tree/master
|
17
8
|
|
18
9
|
Gem:
|
19
|
-
gem install factory_girl
|
10
|
+
gem install thoughtbot-factory_girl --source http://gems.github.com
|
11
|
+
|
12
|
+
Note: if you install factory_girl using the gem from Github, you'll need this
|
13
|
+
in your environment.rb if you want to use Rails 2.1+'s dependency manager:
|
14
|
+
|
15
|
+
config.gem "thoughtbot-factory_girl",
|
16
|
+
:lib => "factory_girl",
|
17
|
+
:source => "http://gems.github.com"
|
20
18
|
|
21
19
|
== Defining factories
|
22
20
|
|
23
21
|
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:
|
24
22
|
|
25
23
|
# This will guess the User class
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
admin false
|
31
|
-
end
|
32
|
-
|
33
|
-
# This will use the User class (Admin would have been guessed)
|
34
|
-
factory :admin, :class => User do
|
35
|
-
first_name 'Admin'
|
36
|
-
last_name 'User'
|
37
|
-
admin true
|
38
|
-
end
|
39
|
-
|
40
|
-
# The same, but using a string instead of class constant
|
41
|
-
factory :admin, :class => 'user' do
|
42
|
-
first_name 'Admin'
|
43
|
-
last_name 'User'
|
44
|
-
admin true
|
45
|
-
end
|
24
|
+
Factory.define :user do |u|
|
25
|
+
u.first_name 'John'
|
26
|
+
u.last_name 'Doe'
|
27
|
+
u.admin false
|
46
28
|
end
|
47
29
|
|
48
|
-
|
30
|
+
# This will use the User class (Admin would have been guessed)
|
31
|
+
Factory.define :admin, :class => User do |u|
|
32
|
+
u.first_name 'Admin'
|
33
|
+
u.last_name 'User'
|
34
|
+
u.admin true
|
35
|
+
end
|
49
36
|
|
50
|
-
|
37
|
+
# The same, but using a string instead of class constant
|
38
|
+
Factory.define :admin, :class => 'user' do |u|
|
39
|
+
u.first_name 'Admin'
|
40
|
+
u.last_name 'User'
|
41
|
+
u.admin true
|
42
|
+
end
|
43
|
+
|
44
|
+
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.
|
51
45
|
|
52
|
-
Factories can be defined anywhere, but will be
|
53
|
-
are defined in files at the following locations:
|
46
|
+
Factories can either be defined anywhere, but will automatically be loaded if they are defined in files at the following locations:
|
54
47
|
|
55
48
|
test/factories.rb
|
56
49
|
spec/factories.rb
|
@@ -81,13 +74,13 @@ You can use the Factory method as a shortcut for the default build strategy:
|
|
81
74
|
The default strategy can be overriden:
|
82
75
|
|
83
76
|
# Now same as Factory.build(:user)
|
84
|
-
|
77
|
+
Factory.define :user, :default_strategy => :build do |u|
|
85
78
|
...
|
86
79
|
end
|
87
80
|
|
88
81
|
user = Factory(:user)
|
89
82
|
|
90
|
-
No matter which
|
83
|
+
No matter which startegy is used, it's possible to override the defined attributes by passing a hash:
|
91
84
|
|
92
85
|
# Build a User instance and override the first_name property
|
93
86
|
user = Factory.build(:user, :first_name => 'Joe')
|
@@ -98,19 +91,19 @@ No matter which strategy is used, it's possible to override the defined attribut
|
|
98
91
|
|
99
92
|
Most factory attributes can be added using static values that are evaluated when the factory is defined, but some attributes (such as associations and other attributes that must be dynamically generated) will need values assigned each time an instance is generated. These "lazy" attributes can be added by passing a block instead of a parameter:
|
100
93
|
|
101
|
-
|
94
|
+
Factory.define :user do |u|
|
102
95
|
# ...
|
103
|
-
activation_code { User.generate_activation_code }
|
96
|
+
u.activation_code { User.generate_activation_code }
|
104
97
|
end
|
105
98
|
|
106
99
|
== Dependent Attributes
|
107
100
|
|
108
101
|
Attributes can be based on the values of other attributes using the proxy that is yieled to lazy attribute blocks:
|
109
102
|
|
110
|
-
|
111
|
-
first_name 'Joe'
|
112
|
-
last_name 'Blow'
|
113
|
-
email { "#{first_name}.#{last_name}@example.com".downcase }
|
103
|
+
Factory.define :user do |u|
|
104
|
+
u.first_name 'Joe'
|
105
|
+
u.last_name 'Blow'
|
106
|
+
u.email {|a| "#{a.first_name}.#{a.last_name}@example.com".downcase }
|
114
107
|
end
|
115
108
|
|
116
109
|
Factory(:user, :last_name => 'Doe').email
|
@@ -121,16 +114,9 @@ Attributes can be based on the values of other attributes using the proxy that i
|
|
121
114
|
Associated instances can be generated by using the association method when
|
122
115
|
defining a lazy attribute:
|
123
116
|
|
124
|
-
|
117
|
+
Factory.define :post do |p|
|
125
118
|
# ...
|
126
|
-
author
|
127
|
-
end
|
128
|
-
|
129
|
-
You can also specify a different factory or override attributes:
|
130
|
-
|
131
|
-
factory :post do
|
132
|
-
# ...
|
133
|
-
association :author, :factory => :user, :last_name => 'Writely'
|
119
|
+
p.author {|author| author.association(:user, :last_name => 'Writely') }
|
134
120
|
end
|
135
121
|
|
136
122
|
The behavior of the association method varies depending on the build strategy used for the parent object.
|
@@ -141,10 +127,22 @@ The behavior of the association method varies depending on the build strategy us
|
|
141
127
|
post.author.new_record # => false
|
142
128
|
|
143
129
|
# Builds and saves a User, and then builds but does not save a Post
|
144
|
-
|
130
|
+
Factory.build(:post)
|
145
131
|
post.new_record? # => true
|
146
132
|
post.author.new_record # => false
|
147
133
|
|
134
|
+
Because this pattern is so common, a prettier syntax is available for defining
|
135
|
+
associations:
|
136
|
+
|
137
|
+
# The following definitions are equivilent:
|
138
|
+
Factory.define :post do |p|
|
139
|
+
p.author {|a| a.association(:user) }
|
140
|
+
end
|
141
|
+
|
142
|
+
Factory.define :post do |p|
|
143
|
+
p.association :author, :factory => :user
|
144
|
+
end
|
145
|
+
|
148
146
|
If the factory name is the same as the association name, the factory name can
|
149
147
|
be left out.
|
150
148
|
|
@@ -152,15 +150,15 @@ be left out.
|
|
152
150
|
|
153
151
|
You can easily create multiple factories for the same class without repeating common attributes by using inheritance:
|
154
152
|
|
155
|
-
|
153
|
+
Factory.define :post do |p|
|
156
154
|
# the 'title' attribute is required for all posts
|
157
|
-
title 'A title'
|
155
|
+
p.title 'A title'
|
158
156
|
end
|
159
157
|
|
160
|
-
|
161
|
-
approved true
|
158
|
+
Factory.define :approved_post, :parent => :post do |p|
|
159
|
+
p.approved true
|
162
160
|
# the 'approver' association is required for an approved post
|
163
|
-
association :approver, :factory => :user
|
161
|
+
p.association :approver, :factory => :user
|
164
162
|
end
|
165
163
|
|
166
164
|
== Sequences
|
@@ -170,7 +168,7 @@ generated using sequences. Sequences are defined by calling Factory.sequence,
|
|
170
168
|
and values in a sequence are generated by calling Factory.next:
|
171
169
|
|
172
170
|
# Defines a new sequence
|
173
|
-
|
171
|
+
Factory.sequence :email do |n|
|
174
172
|
"person#{n}@example.com"
|
175
173
|
end
|
176
174
|
|
@@ -180,83 +178,32 @@ and values in a sequence are generated by calling Factory.next:
|
|
180
178
|
Factory.next :email
|
181
179
|
# => "person2@example.com"
|
182
180
|
|
183
|
-
Sequences can be used
|
184
|
-
|
185
|
-
factory :user do
|
186
|
-
email
|
187
|
-
end
|
188
|
-
|
189
|
-
Or in lazy attributes:
|
181
|
+
Sequences can be used in lazy attributes:
|
190
182
|
|
191
|
-
|
192
|
-
|
183
|
+
Factory.define :user do |f|
|
184
|
+
f.email { Factory.next(:email) }
|
193
185
|
end
|
194
186
|
|
195
187
|
And it's also possible to define an in-line sequence that is only used in
|
196
188
|
a particular factory:
|
197
189
|
|
198
|
-
|
190
|
+
Factory.define :user do |f|
|
199
191
|
f.sequence(:email) {|n| "person#{n}@example.com" }
|
200
192
|
end
|
201
193
|
|
202
|
-
== Callbacks
|
203
|
-
|
204
|
-
Factory_girl makes available three callbacks for injecting some code:
|
205
|
-
|
206
|
-
* after_build - called after a factory is built (via Factory.build)
|
207
|
-
* after_create - called after a factory is saved (via Factory.create)
|
208
|
-
* after_stub - called after a factory is stubbed (via Factory.stub)
|
209
|
-
|
210
|
-
Examples:
|
211
|
-
|
212
|
-
# Define a factory that calls the generate_hashed_password method after it is built
|
213
|
-
factory :user do
|
214
|
-
after_build { |user| do_something_to(user) }
|
215
|
-
end
|
216
|
-
|
217
|
-
Note that you'll have an instance of the user in the block. This can be useful.
|
218
|
-
|
219
|
-
You can also define multiple types of callbacks on the same factory:
|
220
|
-
|
221
|
-
factory :user do
|
222
|
-
after_build { |user| do_something_to(user) }
|
223
|
-
after_create { |user| do_something_else_to(user) }
|
224
|
-
end
|
225
|
-
|
226
|
-
Factories can also define any number of the same kind of callback. These callbacks will be executed in the order they are specified:
|
227
|
-
|
228
|
-
factory :user do
|
229
|
-
after_create { this_runs_first }
|
230
|
-
after_create { then_this }
|
231
|
-
end
|
232
|
-
|
233
|
-
Calling Factory.create will invoke both after_build and after_create callbacks.
|
234
|
-
|
235
|
-
Also, like standard attributes, child factories will inherit (and can define additional) callbacks from their parent factory.
|
236
|
-
|
237
194
|
== Alternate Syntaxes
|
238
195
|
|
239
|
-
Users' tastes for syntax vary dramatically, but most users are looking for a common feature set. Because of this, factory_girl supports "syntax layers" which provide alternate interfaces. See Factory::Syntax for information about the various layers available.
|
196
|
+
Users' tastes for syntax vary dramatically, but most users are looking for a common feature set. Because of this, factory_girl supports "syntax layers" which provide alternate interfaces. See Factory::Syntax for information about the various layers available.
|
240
197
|
|
241
|
-
|
242
|
-
require 'factory_girl/syntax/make'
|
243
|
-
require 'factory_girl/syntax/sham'
|
198
|
+
== More Information
|
244
199
|
|
245
|
-
|
200
|
+
Our blog: http://giantrobots.thoughtbot.com
|
246
201
|
|
247
|
-
|
248
|
-
name { 'Billy Bob' }
|
249
|
-
email { Sham.email }
|
250
|
-
end
|
202
|
+
factory_girl rdoc: http://rdoc.info/projects/thoughtbot/factory_girl
|
251
203
|
|
252
|
-
|
253
|
-
|
254
|
-
== More Information
|
204
|
+
Mailing list: http://groups.google.com/group/factory_girl
|
255
205
|
|
256
|
-
|
257
|
-
* Mailing list[http://groups.google.com/group/factory_girl]
|
258
|
-
* Issues[http://github.com/thoughtbot/factory_girl/issues]
|
259
|
-
* GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS[http://giantrobots.thoughtbot.com]
|
206
|
+
factory_girl issues: http://github.com/thoughtbot/factory_girl/issues
|
260
207
|
|
261
208
|
== Contributing
|
262
209
|
|
@@ -270,7 +217,6 @@ factory_girl was written by Joe Ferris with contributions from several authors,
|
|
270
217
|
* Jon Yurek
|
271
218
|
* Josh Nichols
|
272
219
|
* Josh Owens
|
273
|
-
* Nate Sutton
|
274
220
|
|
275
221
|
The syntax layers are derived from software written by the following authors:
|
276
222
|
* Pete Yandell
|
@@ -279,4 +225,4 @@ The syntax layers are derived from software written by the following authors:
|
|
279
225
|
|
280
226
|
Thanks to all members of thoughtbot for inspiration, ideas, and funding.
|
281
227
|
|
282
|
-
Copyright 2008-
|
228
|
+
Copyright 2008-2009 Joe Ferris and thoughtbot[http://www.thoughtbot.com], inc.
|
data/Rakefile
CHANGED
@@ -1,34 +1,20 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'bundler/setup'
|
3
2
|
require 'rake'
|
4
3
|
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
5
|
require 'rcov/rcovtask'
|
6
6
|
require 'date'
|
7
|
-
|
8
|
-
require '
|
7
|
+
|
8
|
+
require 'spec/rake/spectask'
|
9
9
|
require 'cucumber/rake/task'
|
10
|
-
require 'appraisal'
|
11
10
|
|
12
11
|
desc 'Default: run the specs and features.'
|
13
|
-
task :default =>
|
14
|
-
system("rake -s appraisal spec:acceptance features;")
|
15
|
-
end
|
12
|
+
task :default => [:spec, :features]
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
RSpec::Core::RakeTask.new('unit') do |t|
|
20
|
-
t.pattern = 'spec/factory_girl/**/*_spec.rb'
|
21
|
-
end
|
22
|
-
|
23
|
-
desc "Run acceptance specs"
|
24
|
-
RSpec::Core::RakeTask.new('acceptance') do |t|
|
25
|
-
t.pattern = 'spec/acceptance/**/*_spec.rb'
|
26
|
-
end
|
14
|
+
Spec::Rake::SpecTask.new do |t|
|
15
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
27
16
|
end
|
28
17
|
|
29
|
-
desc "Run the unit and acceptance specs"
|
30
|
-
task :spec => ['spec:unit', 'spec:acceptance']
|
31
|
-
|
32
18
|
desc 'Performs code coverage on the factory_girl plugin.'
|
33
19
|
Rcov::RcovTask.new do |t|
|
34
20
|
t.test_files = FileList['spec/*_spec.rb']
|
@@ -50,17 +36,105 @@ task :sync_docs => 'rdoc' do
|
|
50
36
|
`rsync -ave ssh rdoc/ dev@dev.thoughtbot.com:/home/dev/www/dev.thoughtbot.com/factory_girl`
|
51
37
|
end
|
52
38
|
|
53
|
-
|
54
|
-
|
39
|
+
# spec = Gem::Specification.new do |s|
|
40
|
+
# s.name = %q{factory_girl}
|
41
|
+
# s.version = "1.2.3"
|
42
|
+
# s.summary = %q{factory_girl provides a framework and DSL for defining and
|
43
|
+
# using model instance factories.}
|
44
|
+
# s.description = %q{factory_girl provides a framework and DSL for defining and
|
45
|
+
# using factories - less error-prone, more explicit, and
|
46
|
+
# all-around easier to work with than fixtures.}
|
47
|
+
#
|
48
|
+
# s.files = FileList['[A-Z]*', 'lib/**/*.rb', 'spec/**/*.rb']
|
49
|
+
# s.require_path = 'lib'
|
50
|
+
# s.test_files = Dir[*['spec/**/*_spec.rb']]
|
51
|
+
#
|
52
|
+
# s.has_rdoc = true
|
53
|
+
# s.extra_rdoc_files = ["README.rdoc"]
|
54
|
+
# s.rdoc_options = ['--line-numbers', "--main", "README.rdoc"]
|
55
|
+
#
|
56
|
+
# s.authors = ["Joe Ferris"]
|
57
|
+
# s.email = %q{jferris@thoughtbot.com}
|
58
|
+
# s.homepage = "http://thoughtbot.com/projects/factory_girl"
|
59
|
+
#
|
60
|
+
# s.platform = Gem::Platform::RUBY
|
61
|
+
# end
|
55
62
|
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
require 'jeweler'
|
64
|
+
|
65
|
+
class Jeweler
|
66
|
+
module Commands
|
67
|
+
class ReleaseGemspec
|
68
|
+
def run
|
69
|
+
unless clean_staging_area?
|
70
|
+
system "git status"
|
71
|
+
raise "Unclean staging area! Be sure to commit or .gitignore everything first. See `git status` above."
|
72
|
+
end
|
73
|
+
|
74
|
+
repo.checkout('parametrize')
|
75
|
+
|
76
|
+
regenerate_gemspec!
|
77
|
+
commit_gemspec! if gemspec_changed?
|
78
|
+
|
79
|
+
output.puts "Pushing parametrize to origin"
|
80
|
+
repo.push
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
59
84
|
end
|
60
85
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
86
|
+
class Jeweler
|
87
|
+
module Commands
|
88
|
+
class ReleaseToGit
|
89
|
+
def run
|
90
|
+
unless clean_staging_area?
|
91
|
+
system "git status"
|
92
|
+
raise "Unclean staging area! Be sure to commit or .gitignore everything first. See `git status` above."
|
93
|
+
end
|
94
|
+
output.puts "Checkouting"
|
95
|
+
repo.checkout('parametrize')
|
96
|
+
repo.push
|
97
|
+
|
98
|
+
if release_not_tagged?
|
99
|
+
output.puts "Tagging #{release_tag}"
|
100
|
+
repo.add_tag(release_tag)
|
101
|
+
|
102
|
+
output.puts "Pushing #{release_tag} to origin"
|
103
|
+
repo.push('origin', release_tag)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
jt = Jeweler::Tasks.new do |gem|
|
110
|
+
gem.name = "vitalish-factory_girl"
|
111
|
+
gem.summary = "factory_girl provides a framework and DSL for defining and using model instance factories."
|
112
|
+
gem.description = "factory_girl provides a framework and DSL for defining and using factories - less error-prone, more explicit, and all-around easier to work with than fixtures."
|
113
|
+
gem.email = "jferris@thoughtbot.com"
|
114
|
+
gem.homepage = "http://thoughtbot.com/projects/factory_girl"
|
115
|
+
gem.authors = ["Joe Ferris","Vitalish"]
|
116
|
+
gem.has_rdoc = true
|
117
|
+
gem.files = FileList['[A-Z]*', 'lib/**/*.rb', 'spec/**/*.rb']
|
118
|
+
gem.test_files = Dir[*['spec/**/*_spec.rb']]
|
65
119
|
end
|
120
|
+
Jeweler::GemcutterTasks.new
|
66
121
|
|
122
|
+
# Rake::GemPackageTask.new spec do |pkg|
|
123
|
+
# pkg.need_tar = true
|
124
|
+
# pkg.need_zip = true
|
125
|
+
# end
|
126
|
+
|
127
|
+
# desc "Clean files generated by rake tasks"
|
128
|
+
# task :clobber => [:clobber_rdoc, :clobber_package]
|
129
|
+
#
|
130
|
+
# desc "Generate a gemspec file"
|
131
|
+
# task :gemspec do
|
132
|
+
# File.open("#{spec.name}.gemspec", 'w') do |f|
|
133
|
+
# f.write spec.to_ruby
|
134
|
+
# end
|
135
|
+
# end
|
136
|
+
|
137
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
138
|
+
t.fork = true
|
139
|
+
t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
|
140
|
+
end
|