cranky 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +11 -17
- data/README.md +326 -0
- data/Rakefile +36 -0
- data/lib/cranky/factory.rb +11 -0
- data/lib/cranky/version.rb +1 -1
- data/spec/cranky_spec.rb +9 -0
- data/spec/spec_helper.rb +10 -5
- metadata +28 -50
- data/README.rdoc +0 -265
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 832320f9e104372957157b3cef6c0d81592a6b66
|
4
|
+
data.tar.gz: 6560e13c455a033fa20f11041c065bf13b95f7ec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 82347e3df728a862aec73692225e6e0344df1503d0ff117ca4f8bff366f8626e7fbc027d7322c32f73b95d11de6a0bd0bbe1c895a1116141e5fbb5c45238e62f
|
7
|
+
data.tar.gz: a5c223a0a63ad0231fb342c5f20fcd17fbdd438431a05f78fff8fa25fbc00b163f8b1bb6bea24166e36070bab98d7ca3f88812987de034d944aa49f3a251f9e8
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://gemcutter.org/
|
3
3
|
specs:
|
4
|
-
archive-tar-minitar (0.5.2)
|
5
|
-
columnize (0.3.4)
|
6
4
|
diff-lcs (1.1.2)
|
5
|
+
docile (1.1.5)
|
7
6
|
gemcutter (0.7.0)
|
8
|
-
|
9
|
-
ruby_core_source (>= 0.1.4)
|
7
|
+
json (1.8.3)
|
10
8
|
rake (0.9.2)
|
11
|
-
rcov (0.9.9)
|
12
9
|
rspec (2.6.0)
|
13
10
|
rspec-core (~> 2.6.0)
|
14
11
|
rspec-expectations (~> 2.6.0)
|
@@ -17,16 +14,11 @@ GEM
|
|
17
14
|
rspec-expectations (2.6.0)
|
18
15
|
diff-lcs (~> 1.1.2)
|
19
16
|
rspec-mocks (2.6.0)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
columnize (>= 0.3.1)
|
26
|
-
linecache19 (>= 0.5.11)
|
27
|
-
ruby-debug-base19 (>= 0.11.19)
|
28
|
-
ruby_core_source (0.1.5)
|
29
|
-
archive-tar-minitar (>= 0.5.2)
|
17
|
+
simplecov (0.11.2)
|
18
|
+
docile (~> 1.1.0)
|
19
|
+
json (~> 1.8)
|
20
|
+
simplecov-html (~> 0.10.0)
|
21
|
+
simplecov-html (0.10.0)
|
30
22
|
|
31
23
|
PLATFORMS
|
32
24
|
ruby
|
@@ -34,6 +26,8 @@ PLATFORMS
|
|
34
26
|
DEPENDENCIES
|
35
27
|
gemcutter
|
36
28
|
rake
|
37
|
-
rcov
|
38
29
|
rspec
|
39
|
-
|
30
|
+
simplecov
|
31
|
+
|
32
|
+
BUNDLED WITH
|
33
|
+
1.12.2
|
data/README.md
ADDED
@@ -0,0 +1,326 @@
|
|
1
|
+
# Cranky
|
2
|
+
|
3
|
+
Cranky is a fixtures replacement inspired by the excellent Factory Girl but with easier syntax and no external
|
4
|
+
dependencies, it will work straight out of the box with rails 10.
|
5
|
+
|
6
|
+
In short use this if you want to quickly and naturally create factory methods that you feel 100% in control of.
|
7
|
+
|
8
|
+
## Install
|
9
|
+
|
10
|
+
First install the gem...
|
11
|
+
|
12
|
+
~~~
|
13
|
+
gem install cranky
|
14
|
+
~~~
|
15
|
+
|
16
|
+
Or with bundler...
|
17
|
+
|
18
|
+
~~~ruby
|
19
|
+
# Gemfile
|
20
|
+
gem "cranky"
|
21
|
+
~~~
|
22
|
+
|
23
|
+
Then in your spec_helper.rb ...
|
24
|
+
|
25
|
+
~~~ruby
|
26
|
+
# spec_helper.rb
|
27
|
+
require "cranky"
|
28
|
+
require "factories/my_factories"
|
29
|
+
~~~
|
30
|
+
|
31
|
+
The above assumes that you have created your factory methods in a file called my_factories.rb in the spec/factories directory.
|
32
|
+
You can create as many different factory files as you want, just require them in the same way.
|
33
|
+
|
34
|
+
## In a Nutshell
|
35
|
+
|
36
|
+
The API to use in your tests is:
|
37
|
+
|
38
|
+
~~~ruby
|
39
|
+
crank(:user) # Build a user instance without saving
|
40
|
+
crank!(:user) # Build and save a user instance
|
41
|
+
crank(:user, :name => "Ian") # Override a default attribute value
|
42
|
+
crank(:user_attrs) # Return a set of valid attributes rather than the object
|
43
|
+
~~~
|
44
|
+
|
45
|
+
Alternatively the Factory Girl syntax also works and therefore Cranky can drop into tests already written for that framework...
|
46
|
+
|
47
|
+
~~~ruby
|
48
|
+
Factory.build(:user) # Build a user instance without saving
|
49
|
+
Factory.create(:user) # Build and save a user instance
|
50
|
+
Factory.build(:user, :name => "Ian") # Override a default attribute value
|
51
|
+
Factory.attributes_for(:user) # Return a set of valid attributes rather than the object
|
52
|
+
~~~
|
53
|
+
|
54
|
+
Or if you're coming from Machinist, you can make your Cranky factories drop into your existing tests by setting up make and make! methods as [shown here](http://gist.github.com/525653).
|
55
|
+
|
56
|
+
Cranky has a nice debug option (rails only) to warn you when your factory is broken, recommend you do this for your first spec...
|
57
|
+
|
58
|
+
~~~ruby
|
59
|
+
describe User do
|
60
|
+
it "should have a working factory" do
|
61
|
+
# This will raise an error and report the validation errors should they occur
|
62
|
+
Factory.debug(:user).should be_valid
|
63
|
+
end
|
64
|
+
end
|
65
|
+
~~~
|
66
|
+
|
67
|
+
Cranky allows you to build factories via std Ruby methods, like this...
|
68
|
+
|
69
|
+
~~~ruby
|
70
|
+
# factories/my_factories.rb
|
71
|
+
class Cranky::Factory # Your factory must reopen Cranky::Factory
|
72
|
+
|
73
|
+
# Simple factory method to create a user instance, you would call this via Factory.build(:user)
|
74
|
+
def user
|
75
|
+
# Define attributes via a hash, generate the values any way you want
|
76
|
+
define :name => "Jimmy",
|
77
|
+
:email => "jimmy#{n}@home.com", # An 'n' counter method is available to help make things unique
|
78
|
+
:role => "pleb",
|
79
|
+
:address => default_address # Call your own helper methods to wire up your associations
|
80
|
+
end
|
81
|
+
|
82
|
+
# Easily create variations via the inherit helper, callable via Factory.build(:admin)
|
83
|
+
def admin
|
84
|
+
inherit(:user, :role => "admin")
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return a default address if it already exists, or call the address factory to make one
|
88
|
+
def default_address
|
89
|
+
@default_address ||= create(:address)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Alternatively loose the DSL altogether and define the factory yourself, still callable via Factory.build(:address)
|
93
|
+
def address
|
94
|
+
a = Address.new
|
95
|
+
a.street = "192 Broadway"
|
96
|
+
a.city = options[:city] || "New York" # You can get any caller overrides via the options hash
|
97
|
+
a # Only rule is the method must return the generated object
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
~~~
|
102
|
+
|
103
|
+
# Details
|
104
|
+
|
105
|
+
## Define Your Factories
|
106
|
+
|
107
|
+
This is where Cranky really shines, if you can create Ruby methods you can pretty much create your factories without having to refer to the syntax documentation ever again.
|
108
|
+
|
109
|
+
The only rules are:
|
110
|
+
|
111
|
+
1. Your factory must reopen the Cranky::Factory class
|
112
|
+
2. Your factory method must return the object you wanted to create
|
113
|
+
3. You can access the overrides passed in via options[:key]. (not really a rule!)
|
114
|
+
|
115
|
+
So for example to create a simple user factory...
|
116
|
+
|
117
|
+
~~~ruby
|
118
|
+
# factories/my_factories.rb
|
119
|
+
class Cranky::Factory
|
120
|
+
|
121
|
+
# Simple factory method to create a user instance, you would call this via Factory.build(:user)
|
122
|
+
def user
|
123
|
+
u = User.new
|
124
|
+
u.name = options[:name] || "Jimmy" # Use the passed in name if present, or the default
|
125
|
+
u.email = options[:email] || "jimmy#{n}@home.com" # Give each user a unique email address
|
126
|
+
u.role = options[:role] || "pleb"
|
127
|
+
u
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
~~~
|
132
|
+
|
133
|
+
Now of course you are working in straight Ruby here, so you can extend this any way you want as long as you follow the above rules.
|
134
|
+
|
135
|
+
For example here it is with the capability to automatically create a default address association...
|
136
|
+
|
137
|
+
~~~ruby
|
138
|
+
# factories/my_factories.rb
|
139
|
+
class Cranky::Factory
|
140
|
+
|
141
|
+
# Return the default address if it already exists, or call the address factory to make one
|
142
|
+
def default_address
|
143
|
+
@default_address ||= create(:address)
|
144
|
+
end
|
145
|
+
|
146
|
+
def user
|
147
|
+
u = User.new
|
148
|
+
u.name = options[:name] || "Jimmy"
|
149
|
+
u.email = options[:email] || "jimmy#{n}@home.com"
|
150
|
+
u.role = options[:role] || "pleb"
|
151
|
+
u.address = default_address
|
152
|
+
u
|
153
|
+
end
|
154
|
+
|
155
|
+
# Create the address factory in the same way
|
156
|
+
|
157
|
+
end
|
158
|
+
~~~
|
159
|
+
|
160
|
+
Quite often the database will be cleared between tests but the instance variable in the factory will not necessarily be reset which could lead to problems if the tests check for the associated record in the database.
|
161
|
+
So a nice tip is to implement default associations like this (assuming you're using Rails)...
|
162
|
+
|
163
|
+
~~~ruby
|
164
|
+
# Return the default address if it already exists, or call the address factory to make one
|
165
|
+
def default_address
|
166
|
+
# If the default address exists, but has been cleared from the database...
|
167
|
+
@default_address = nil if @default_address && !Address.exists?(@default_address.id)
|
168
|
+
@default_address ||= create(:address)
|
169
|
+
end
|
170
|
+
~~~
|
171
|
+
|
172
|
+
You can pass additional arguments to your factories via the overrides hash...
|
173
|
+
|
174
|
+
~~~ruby
|
175
|
+
Factory.build(:user, :new_address => true)
|
176
|
+
|
177
|
+
def user
|
178
|
+
u = User.new
|
179
|
+
u.name = options[:name] || "Jimmy"
|
180
|
+
u.email = options[:email] || "jimmy#{n}@home.com"
|
181
|
+
u.role = options[:role] || "pleb"
|
182
|
+
u.address = options[:new_address] ? create(:address) : default_address
|
183
|
+
u
|
184
|
+
end
|
185
|
+
~~~
|
186
|
+
|
187
|
+
You can use traits...
|
188
|
+
|
189
|
+
~~~ruby
|
190
|
+
Factory.build(:user, traits: [:admin, :manager])
|
191
|
+
|
192
|
+
def user
|
193
|
+
u = User.new
|
194
|
+
u.name = options[:name] || "Jimmy"
|
195
|
+
u.email = options[:email] || "jimmy#{n}@home.com"
|
196
|
+
u.role = options[:role] || "pleb"
|
197
|
+
u.address = options[:new_address] ? create(:address) : default_address
|
198
|
+
u
|
199
|
+
end
|
200
|
+
|
201
|
+
def apply_trait_admin_to_user(user)
|
202
|
+
user.roles << :admin
|
203
|
+
end
|
204
|
+
|
205
|
+
def apply_trait_manager_to_user(user)
|
206
|
+
user.roles << :manager
|
207
|
+
end
|
208
|
+
~~~
|
209
|
+
|
210
|
+
## Helpers
|
211
|
+
|
212
|
+
Of course its nice to get some help...
|
213
|
+
|
214
|
+
### Define
|
215
|
+
|
216
|
+
Most of your factories are likely to simply define a list of mimimum attribute values, use the define helper for this.
|
217
|
+
|
218
|
+
~~~ruby
|
219
|
+
# The user factory re-written using the define helper
|
220
|
+
def user
|
221
|
+
define :name => "Jimmy",
|
222
|
+
:email => "jimmy#{n}@home.com",
|
223
|
+
:role => "pleb",
|
224
|
+
:address => default_address
|
225
|
+
end
|
226
|
+
~~~
|
227
|
+
|
228
|
+
Note that you don't have to worry about handling the overrides here, they will be applied automatically if present, just define the defaults.
|
229
|
+
|
230
|
+
The define argument is just a regular hash, you have complete freedom to choose how to generate the values to be passed into it.
|
231
|
+
|
232
|
+
If you like you can generate attributes with a block:
|
233
|
+
|
234
|
+
~~~ruby
|
235
|
+
def user
|
236
|
+
define :name => "Jimmy",
|
237
|
+
:email => lambda{|u| "#{u.name.downcase}@home.com"},
|
238
|
+
:role => "pleb",
|
239
|
+
:address => default_address
|
240
|
+
end
|
241
|
+
~~~
|
242
|
+
|
243
|
+
The define method will return the object, you can grab this for additional manipulation as you would expect...
|
244
|
+
|
245
|
+
~~~ruby
|
246
|
+
def user
|
247
|
+
u = define :name => "Jimmy",
|
248
|
+
:email => "jimmy#{n}@home.com",
|
249
|
+
:role => "pleb",
|
250
|
+
:address => default_address
|
251
|
+
u.do_something
|
252
|
+
u # Remember to return it at the end
|
253
|
+
end
|
254
|
+
~~~
|
255
|
+
|
256
|
+
If for any reason you want to have your factory method named differently from the model it instantiates you can pass in a :class attribute to the define method...
|
257
|
+
|
258
|
+
~~~ruby
|
259
|
+
# Called via Factory.create(:jimmy)
|
260
|
+
def jimmy
|
261
|
+
u = define :class => :user,
|
262
|
+
:name => "Jimmy",
|
263
|
+
:email => "jimmy#{n}@home.com",
|
264
|
+
:role => "pleb",
|
265
|
+
:address => default_address
|
266
|
+
end
|
267
|
+
~~~
|
268
|
+
|
269
|
+
### Inherit
|
270
|
+
|
271
|
+
You can inherit from other factories via the inherit method. So for example to create an admin user you might do...
|
272
|
+
|
273
|
+
~~~ruby
|
274
|
+
# Called via Factory.create(:admin)
|
275
|
+
def admin
|
276
|
+
inherit(:user, :role => "admin") # Pass in any attribute overrides you want
|
277
|
+
end
|
278
|
+
~~~
|
279
|
+
|
280
|
+
### Unique Attributes (n)
|
281
|
+
|
282
|
+
If you want to generate unique attributes you can call the n method which will automatically increment the next time it is called.
|
283
|
+
|
284
|
+
Note that every time n is called it will increment, it does not implement a unique counter per attribute.
|
285
|
+
|
286
|
+
### Reset
|
287
|
+
|
288
|
+
Clear all instance variables in the factory. This may be useful to run between tests depending on your factory logic...
|
289
|
+
|
290
|
+
~~~ruby
|
291
|
+
before(:each) do
|
292
|
+
Factory.reset
|
293
|
+
end
|
294
|
+
~~~
|
295
|
+
|
296
|
+
### Debug
|
297
|
+
|
298
|
+
Sometimes it is useful to be warned that your factory is generating invalid instances (although quite often your tests may intentionally generate invalid instances, so use this with care). By turning on debug the Factory will raise an error if the generated instance is invalid...
|
299
|
+
|
300
|
+
~~~ruby
|
301
|
+
Factory.debug(:user) # A replacement for Factory.build, with validation warnings enabled
|
302
|
+
Factory.debug!(:user) # Likewise for Factory.create
|
303
|
+
~~~
|
304
|
+
|
305
|
+
Note that this relies on the instance having a valid? method, so in practice this may only work with Rails.
|
306
|
+
|
307
|
+
### Attributes For
|
308
|
+
|
309
|
+
Returns the attributes that would be applied by a given factory method...
|
310
|
+
|
311
|
+
~~~ruby
|
312
|
+
valid_attributes = Factory.attributes_for(:user)
|
313
|
+
~~~
|
314
|
+
|
315
|
+
Requires that the instance has an attributes method, so again may only work under Rails.
|
316
|
+
|
317
|
+
## Additional Features
|
318
|
+
|
319
|
+
Want any? Feel free to let me know.
|
320
|
+
|
321
|
+
## Thanks
|
322
|
+
|
323
|
+
Cranky was inspired by [factory_girl](http://github.com/thoughtbot/factory_girl) and [miniskirt](http://gist.github.com/273579).
|
324
|
+
|
325
|
+
Thanks to both.
|
326
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require 'cranky'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'rspec/core'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
desc "Run specs"
|
9
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
10
|
+
t.pattern = ("spec/**/*_spec.rb")
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
task :release_tag do
|
16
|
+
system "git commit -a -m 'Release #{Cranky::VERSION}'"
|
17
|
+
system "git tag -a v#{Cranky::VERSION} -m 'version #{Cranky::VERSION}'"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Push to github
|
21
|
+
desc "Push to Github"
|
22
|
+
task :push do
|
23
|
+
system "git push --tags origin master"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Build the gem"
|
27
|
+
task :build do
|
28
|
+
system "bundle exec gem build cranky.gemspec"
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Release version #{Cranky::VERSION}"
|
32
|
+
task :release => [:build, :release_tag, :push] do
|
33
|
+
system "bundle exec gem push cranky-#{Cranky::VERSION}.gem"
|
34
|
+
end
|
35
|
+
|
36
|
+
|
data/lib/cranky/factory.rb
CHANGED
@@ -58,6 +58,16 @@ module Cranky
|
|
58
58
|
|
59
59
|
private
|
60
60
|
|
61
|
+
def apply_traits(what, item)
|
62
|
+
Array(options[:traits]).each do |t|
|
63
|
+
trait_method_name = "apply_trait_#{t}_to_#{what}"
|
64
|
+
fail("Invalid trait '#{t}'! No method '#{trait_method_name}' is defined.") unless respond_to?(trait_method_name)
|
65
|
+
send(trait_method_name, item)
|
66
|
+
end
|
67
|
+
|
68
|
+
item
|
69
|
+
end
|
70
|
+
|
61
71
|
def n
|
62
72
|
@n += 1
|
63
73
|
end
|
@@ -71,6 +81,7 @@ module Cranky
|
|
71
81
|
item = "TBD"
|
72
82
|
new_job(what, overrides) do
|
73
83
|
item = self.send(what) # Invoke the factory method
|
84
|
+
item = apply_traits(what, item)
|
74
85
|
end
|
75
86
|
item
|
76
87
|
end
|
data/lib/cranky/version.rb
CHANGED
data/spec/cranky_spec.rb
CHANGED
@@ -127,6 +127,15 @@ describe "The Cranky factory" do
|
|
127
127
|
Factory.build(:user_hash, :role => :admin)[:role].should == :admin
|
128
128
|
end
|
129
129
|
|
130
|
+
it "is capable of using traits" do
|
131
|
+
user = Factory.build(:user_manually, :traits => :manager)
|
132
|
+
user.role.should == :manager
|
133
|
+
end
|
134
|
+
|
135
|
+
it "raises exception if trait method is undefined" do
|
136
|
+
lambda { Factory.build(:user_by_define, :traits => :manager) }.should raise_error("Invalid trait 'manager'! No method 'apply_trait_manager_to_user_by_define' is defined.")
|
137
|
+
end
|
138
|
+
|
130
139
|
specify "attributes are not assigned when they have the value :skip" do
|
131
140
|
crank(:user, :name => :skip).name.should_not be
|
132
141
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
3
4
|
require 'cranky'
|
4
5
|
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.expect_with(:rspec) { |c| c.syntax = :should }
|
8
|
+
end
|
5
9
|
|
6
10
|
class TestClass
|
7
11
|
attr_accessor :valid
|
@@ -91,7 +95,8 @@ class Cranky::Factory
|
|
91
95
|
:name => "Fred",
|
92
96
|
:role => :user
|
93
97
|
end
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
98
|
|
99
|
+
def apply_trait_manager_to_user_manually(user)
|
100
|
+
user.role = :manager
|
101
|
+
end
|
102
|
+
end
|
metadata
CHANGED
@@ -1,78 +1,56 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: cranky
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 0
|
7
|
-
- 3
|
8
|
-
- 1
|
9
|
-
version: 0.3.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
10
5
|
platform: ruby
|
11
|
-
authors:
|
6
|
+
authors:
|
12
7
|
- Stephen McGinty
|
13
8
|
autorequire:
|
14
9
|
bindir: bin
|
15
10
|
cert_chain: []
|
16
|
-
|
17
|
-
date: 2011-10-22 00:00:00 +01:00
|
18
|
-
default_executable:
|
11
|
+
date: 2016-05-30 00:00:00.000000000 Z
|
19
12
|
dependencies: []
|
20
|
-
|
21
|
-
|
22
|
-
email:
|
13
|
+
description: A very light yet powerful test factory framework with an extremely clean
|
14
|
+
syntax that makes it very easy to define your factories.
|
15
|
+
email: stephen.f.mcginty@gmail.com
|
23
16
|
executables: []
|
24
|
-
|
25
17
|
extensions: []
|
26
|
-
|
27
18
|
extra_rdoc_files: []
|
28
|
-
|
29
|
-
files:
|
30
|
-
- lib/cranky/factory.rb
|
31
|
-
- lib/cranky/version.rb
|
32
|
-
- lib/cranky/job.rb
|
33
|
-
- lib/cranky.rb
|
34
|
-
- spec/spec_helper.rb
|
35
|
-
- spec/cranky_spec.rb
|
19
|
+
files:
|
36
20
|
- CHANGELOG.md
|
37
21
|
- Gemfile
|
38
22
|
- Gemfile.lock
|
39
|
-
- README.rdoc
|
40
23
|
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
41
26
|
- init.rb
|
42
|
-
|
27
|
+
- lib/cranky.rb
|
28
|
+
- lib/cranky/factory.rb
|
29
|
+
- lib/cranky/job.rb
|
30
|
+
- lib/cranky/version.rb
|
31
|
+
- spec/cranky_spec.rb
|
32
|
+
- spec/spec_helper.rb
|
43
33
|
homepage: http://github.com/ginty/cranky
|
44
34
|
licenses: []
|
45
|
-
|
35
|
+
metadata: {}
|
46
36
|
post_install_message:
|
47
37
|
rdoc_options: []
|
48
|
-
|
49
|
-
require_paths:
|
38
|
+
require_paths:
|
50
39
|
- lib
|
51
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
-
|
53
|
-
requirements:
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
54
42
|
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
version: "0"
|
60
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
|
-
requirements:
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
63
47
|
- - ">="
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
segments:
|
66
|
-
- 1
|
67
|
-
- 3
|
68
|
-
- 4
|
48
|
+
- !ruby/object:Gem::Version
|
69
49
|
version: 1.3.4
|
70
50
|
requirements: []
|
71
|
-
|
72
51
|
rubyforge_project:
|
73
|
-
rubygems_version:
|
52
|
+
rubygems_version: 2.4.5
|
74
53
|
signing_key:
|
75
|
-
specification_version:
|
54
|
+
specification_version: 4
|
76
55
|
summary: A very light yet powerful test factory framework.
|
77
56
|
test_files: []
|
78
|
-
|
data/README.rdoc
DELETED
@@ -1,265 +0,0 @@
|
|
1
|
-
= Cranky
|
2
|
-
|
3
|
-
Cranky is a fixtures replacement inspired by the excellent Factory Girl but with easier syntax and no external
|
4
|
-
dependencies, it will work straight out of the box with rails 10.
|
5
|
-
|
6
|
-
In short use this if you want to quickly and naturally create factory methods that you feel 100% in control of.
|
7
|
-
|
8
|
-
== Install
|
9
|
-
|
10
|
-
First install the gem...
|
11
|
-
|
12
|
-
gem install cranky
|
13
|
-
|
14
|
-
Or with bundler...
|
15
|
-
|
16
|
-
# Gemfile
|
17
|
-
gem "cranky"
|
18
|
-
|
19
|
-
Then in your spec_helper.rb ...
|
20
|
-
|
21
|
-
# spec_helper.rb
|
22
|
-
require "cranky"
|
23
|
-
require "factories/my_factories"
|
24
|
-
|
25
|
-
The above assumes that you have created your factory methods in a file called my_factories.rb in the spec/factories directory.
|
26
|
-
You can create as many different factory files as you want, just require them in the same way.
|
27
|
-
|
28
|
-
== In a Nutshell
|
29
|
-
|
30
|
-
The API to use in your tests is:
|
31
|
-
|
32
|
-
crank(:user) # Build a user instance without saving
|
33
|
-
crank!(:user) # Build and save a user instance
|
34
|
-
crank(:user, :name => "Ian") # Override a default attribute value
|
35
|
-
crank(:user_attrs) # Return a set of valid attributes rather than the object
|
36
|
-
|
37
|
-
Alternatively the Factory Girl syntax also works and therefore Cranky can drop into tests already written for that framework...
|
38
|
-
|
39
|
-
Factory.build(:user) # Build a user instance without saving
|
40
|
-
Factory.create(:user) # Build and save a user instance
|
41
|
-
Factory.build(:user, :name => "Ian") # Override a default attribute value
|
42
|
-
Factory.attributes_for(:user) # Return a set of valid attributes rather than the object
|
43
|
-
|
44
|
-
Or if you're coming from Machinist, you can make your Cranky factories drop into your existing tests by setting up make and make! methods as shown here.[http://gist.github.com/525653]
|
45
|
-
|
46
|
-
Cranky has a nice debug option (rails only) to warn you when your factory is broken, recommend you do this for your first spec...
|
47
|
-
|
48
|
-
describe User do
|
49
|
-
it "should have a working factory" do
|
50
|
-
# This will raise an error and report the validation errors should they occur
|
51
|
-
Factory.debug(:user).should be_valid
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
Cranky allows you to build factories via std Ruby methods, like this...
|
56
|
-
|
57
|
-
# factories/my_factories.rb
|
58
|
-
class Cranky::Factory # Your factory must reopen Cranky::Factory
|
59
|
-
|
60
|
-
# Simple factory method to create a user instance, you would call this via Factory.build(:user)
|
61
|
-
def user
|
62
|
-
# Define attributes via a hash, generate the values any way you want
|
63
|
-
define :name => "Jimmy",
|
64
|
-
:email => "jimmy#{n}@home.com", # An 'n' counter method is available to help make things unique
|
65
|
-
:role => "pleb",
|
66
|
-
:address => default_address # Call your own helper methods to wire up your associations
|
67
|
-
end
|
68
|
-
|
69
|
-
# Easily create variations via the inherit helper, callable via Factory.build(:admin)
|
70
|
-
def admin
|
71
|
-
inherit(:user, :role => "admin")
|
72
|
-
end
|
73
|
-
|
74
|
-
# Return a default address if it already exists, or call the address factory to make one
|
75
|
-
def default_address
|
76
|
-
@default_address ||= create(:address)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Alternatively loose the DSL altogether and define the factory yourself, still callable via Factory.build(:address)
|
80
|
-
def address
|
81
|
-
a = Address.new
|
82
|
-
a.street = "192 Broadway"
|
83
|
-
a.city = options[:city] || "New York" # You can get any caller overrides via the options hash
|
84
|
-
a # Only rule is the method must return the generated object
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
= Details
|
90
|
-
|
91
|
-
== Define Your Factories
|
92
|
-
|
93
|
-
This is where Cranky really shines, if you can create Ruby methods you can pretty much create your factories without having to refer to the syntax documentation ever again.
|
94
|
-
|
95
|
-
The only rules are:
|
96
|
-
|
97
|
-
1. Your factory must reopen the Cranky::Factory class
|
98
|
-
2. Your factory method must return the object you wanted to create
|
99
|
-
3. You can access the overrides passed in via options[:key] (not really a rule!)
|
100
|
-
|
101
|
-
So for example to create a simple user factory...
|
102
|
-
|
103
|
-
# factories/my_factories.rb
|
104
|
-
class Cranky::Factory
|
105
|
-
|
106
|
-
# Simple factory method to create a user instance, you would call this via Factory.build(:user)
|
107
|
-
def user
|
108
|
-
u = User.new
|
109
|
-
u.name = options[:name] || "Jimmy" # Use the passed in name if present, or the default
|
110
|
-
u.email = options[:email] || "jimmy#{n}@home.com" # Give each user a unique email address
|
111
|
-
u.role = options[:role] || "pleb"
|
112
|
-
u
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
Now of course you are working in straight Ruby here, so you can extend this any way you want as long as you follow the above rules.
|
118
|
-
|
119
|
-
For example here it is with the capability to automatically create a default address association...
|
120
|
-
|
121
|
-
# factories/my_factories.rb
|
122
|
-
class Cranky::Factory
|
123
|
-
|
124
|
-
# Return the default address if it already exists, or call the address factory to make one
|
125
|
-
def default_address
|
126
|
-
@default_address ||= create(:address)
|
127
|
-
end
|
128
|
-
|
129
|
-
def user
|
130
|
-
u = User.new
|
131
|
-
u.name = options[:name] || "Jimmy"
|
132
|
-
u.email = options[:email] || "jimmy#{n}@home.com"
|
133
|
-
u.role = options[:role] || "pleb"
|
134
|
-
u.address = default_address
|
135
|
-
u
|
136
|
-
end
|
137
|
-
|
138
|
-
... # Create the address factory in the same way
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
Quite often the database will be cleared between tests but the instance variable in the factory will not necessarily be reset which could lead to problems if the tests check for the associated record in the database.
|
143
|
-
So a nice tip is to implement default associations like this (assuming you're using Rails)...
|
144
|
-
|
145
|
-
# Return the default address if it already exists, or call the address factory to make one
|
146
|
-
def default_address
|
147
|
-
# If the default address exists, but has been cleared from the database...
|
148
|
-
@default_address = nil if @default_address && !Address.exists?(@default_address.id)
|
149
|
-
@default_address ||= create(:address)
|
150
|
-
end
|
151
|
-
|
152
|
-
You can pass additional arguments to your factories via the overrides hash...
|
153
|
-
|
154
|
-
Factory.build(:user, :new_address => true)
|
155
|
-
|
156
|
-
def user
|
157
|
-
u = User.new
|
158
|
-
u.name = options[:name] || "Jimmy"
|
159
|
-
u.email = options[:email] || "jimmy#{n}@home.com"
|
160
|
-
u.role = options[:role] || "pleb"
|
161
|
-
u.address = options[:new_address] ? create(:address) : default_address
|
162
|
-
u
|
163
|
-
end
|
164
|
-
|
165
|
-
== Helpers
|
166
|
-
|
167
|
-
Of course its nice to get some help...
|
168
|
-
|
169
|
-
=== Define
|
170
|
-
|
171
|
-
Most of your factories are likely to simply define a list of mimimum attribute values, use the define helper for this.
|
172
|
-
|
173
|
-
# The user factory re-written using the define helper
|
174
|
-
def user
|
175
|
-
define :name => "Jimmy",
|
176
|
-
:email => "jimmy#{n}@home.com",
|
177
|
-
:role => "pleb",
|
178
|
-
:address => default_address
|
179
|
-
end
|
180
|
-
|
181
|
-
Note that you don't have to worry about handling the overrides here, they will be applied automatically if present, just define the defaults.
|
182
|
-
|
183
|
-
The define argument is just a regular hash, you have complete freedom to choose how to generate the values to be passed into it.
|
184
|
-
|
185
|
-
If you like you can generate attributes with a block:
|
186
|
-
|
187
|
-
def user
|
188
|
-
define :name => "Jimmy",
|
189
|
-
:email => lambda{|u| "#{u.name.downcase}@home.com"},
|
190
|
-
:role => "pleb",
|
191
|
-
:address => default_address
|
192
|
-
end
|
193
|
-
|
194
|
-
The define method will return the object, you can grab this for additional manipulation as you would expect...
|
195
|
-
|
196
|
-
def user
|
197
|
-
u = define :name => "Jimmy",
|
198
|
-
:email => "jimmy#{n}@home.com",
|
199
|
-
:role => "pleb",
|
200
|
-
:address => default_address
|
201
|
-
u.do_something
|
202
|
-
u # Remember to return it at the end
|
203
|
-
end
|
204
|
-
|
205
|
-
If for any reason you want to have your factory method named differently from the model it instantiates you can pass in a :class attribute to the define method...
|
206
|
-
|
207
|
-
# Called via Factory.create(:jimmy)
|
208
|
-
def jimmy
|
209
|
-
u = define :class => :user,
|
210
|
-
:name => "Jimmy",
|
211
|
-
:email => "jimmy#{n}@home.com",
|
212
|
-
:role => "pleb",
|
213
|
-
:address => default_address
|
214
|
-
end
|
215
|
-
|
216
|
-
=== Inherit
|
217
|
-
|
218
|
-
You can inherit from other factories via the inherit method. So for example to create an admin user you might do...
|
219
|
-
|
220
|
-
# Called via Factory.create(:admin)
|
221
|
-
def admin
|
222
|
-
inherit(:user, :role => "admin") # Pass in any attribute overrides you want
|
223
|
-
end
|
224
|
-
|
225
|
-
=== Unique Attributes (n)
|
226
|
-
|
227
|
-
If you want to generate unique attributes you can call the n method which will automatically increment the next time it is called.
|
228
|
-
|
229
|
-
Note that every time n is called it will increment, it does not implement a unique counter per attribute.
|
230
|
-
|
231
|
-
=== Reset
|
232
|
-
|
233
|
-
Clear all instance variables in the factory. This may be useful to run between tests depending on your factory logic...
|
234
|
-
|
235
|
-
before(:each) do
|
236
|
-
Factory.reset
|
237
|
-
end
|
238
|
-
|
239
|
-
=== Debug
|
240
|
-
|
241
|
-
Sometimes it is useful to be warned that your factory is generating invalid instances (although quite often your tests may intentionally generate invalid instances, so use this with care). By turning on debug the Factory will raise an error if the generated instance is invalid...
|
242
|
-
|
243
|
-
Factory.debug(:user) # A replacement for Factory.build, with validation warnings enabled
|
244
|
-
Factory.debug!(:user) # Likewise for Factory.create
|
245
|
-
|
246
|
-
Note that this relies on the instance having a valid? method, so in practice this may only work with Rails.
|
247
|
-
|
248
|
-
=== Attributes For
|
249
|
-
|
250
|
-
Returns the attributes that would be applied by a given factory method...
|
251
|
-
|
252
|
-
valid_attributes = Factory.attributes_for(:user)
|
253
|
-
|
254
|
-
Requires that the instance has an attributes method, so again may only work under Rails.
|
255
|
-
|
256
|
-
== Additional Features
|
257
|
-
|
258
|
-
Want any? Feel free to let me know.
|
259
|
-
|
260
|
-
== Thanks
|
261
|
-
|
262
|
-
Cranky was inspired by factory_girl[http://github.com/thoughtbot/factory_girl] and miniskirt[http://gist.github.com/273579].
|
263
|
-
|
264
|
-
Thanks to both.
|
265
|
-
|