cranky 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +90 -36
- data/lib/cranky.rb +2 -2
- data/spec/cranky_spec.rb +6 -0
- data/spec/spec_helper.rb +8 -5
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -27,13 +27,50 @@ Then in your spec_helper.rb ...
|
|
27
27
|
The above assumes that you have created your factory methods in a file called my_factories.rb in the spec/factories directory.
|
28
28
|
You can create as many different factory files as you want, just require them in the same way.
|
29
29
|
|
30
|
-
==
|
30
|
+
== In a Nutshell
|
31
31
|
|
32
32
|
Cranky steals its core syntax from Factory Girl...
|
33
33
|
|
34
34
|
Factory.build(:user) # Build a user instance without saving
|
35
35
|
Factory.create(:user) # Build and save a user instance
|
36
36
|
Factory.build(:user, :name => "Ian") # Override a default attribute value
|
37
|
+
Factory.attributes_for(:user) # Return a set of valid attributes rather than the object
|
38
|
+
|
39
|
+
Cranky allows you to build factories via std Ruby methods, like this...
|
40
|
+
|
41
|
+
# factories/my_factories.rb
|
42
|
+
class Cranky # Your factory must use the Cranky class
|
43
|
+
|
44
|
+
# Simple factory method to create a user instance, you would call this via Factory.build(:user)
|
45
|
+
def user
|
46
|
+
# Define attributes via a hash, generate the values any way you want
|
47
|
+
define :name => "Jimmy",
|
48
|
+
:email => "jimmy#{n}@home.com", # An 'n' counter method is available to help make things unique
|
49
|
+
:role => :user,
|
50
|
+
:address => default_address # Call your own helper methods to wire up your associations
|
51
|
+
end
|
52
|
+
|
53
|
+
# Easily create variations via the inherit helper, callable via Factory.build(:admin)
|
54
|
+
def admin
|
55
|
+
inherit(:user, :role => :admin)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return a default address if it already exists, or call the address factory to make one
|
59
|
+
def default_address
|
60
|
+
@default_address ||= create(:address)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Alternatively loose the DSL altogether and define the factory yourself, still callable via Factory.build(:address)
|
64
|
+
def address
|
65
|
+
a = Address.new
|
66
|
+
a.street = "192 Broadway"
|
67
|
+
a.city = options[:city] || "New York" # You can get any caller overrides via the options hash
|
68
|
+
a # Only rule is the method must return the generated object
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
= Details
|
37
74
|
|
38
75
|
== Define Your Factories
|
39
76
|
|
@@ -52,8 +89,10 @@ So for example to create a simple user factory...
|
|
52
89
|
|
53
90
|
# Simple factory method to create a user instance, you would call this via Factory.build(:user)
|
54
91
|
def user
|
55
|
-
u
|
56
|
-
u.name
|
92
|
+
u = User.new
|
93
|
+
u.name = options[:name] || "Jimmy" # Use the passed in name if present, or the default
|
94
|
+
u.email = options[:email] || "jimmy#{n}@home.com" # Give each user a unique email address
|
95
|
+
u.role = options[:role] || :user
|
57
96
|
u
|
58
97
|
end
|
59
98
|
|
@@ -61,37 +100,50 @@ So for example to create a simple user factory...
|
|
61
100
|
|
62
101
|
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.
|
63
102
|
|
64
|
-
For example here it is with the capability to automatically create a default
|
103
|
+
For example here it is with the capability to automatically create a default address association...
|
65
104
|
|
66
105
|
# factories/my_factories.rb
|
67
106
|
class Cranky
|
68
107
|
|
69
|
-
# Return the default
|
70
|
-
def
|
71
|
-
@
|
108
|
+
# Return the default address if it already exists, or call the address factory to make one
|
109
|
+
def default_address
|
110
|
+
@default_address ||= create(:address)
|
72
111
|
end
|
73
112
|
|
74
113
|
def user
|
75
|
-
u
|
76
|
-
u.name
|
77
|
-
u.
|
114
|
+
u = User.new
|
115
|
+
u.name = options[:name] || "Jimmy"
|
116
|
+
u.email = options[:email] || "jimmy#{n}@home.com"
|
117
|
+
u.role = options[:role] || :user
|
118
|
+
u.address = default_address
|
78
119
|
u
|
79
120
|
end
|
80
121
|
|
81
|
-
... # Create the
|
122
|
+
... # Create the address factory in the same way
|
82
123
|
|
83
124
|
end
|
84
125
|
|
85
|
-
Quite often the database will be cleared between tests
|
126
|
+
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.
|
86
127
|
So a nice tip is to implement default associations like this (assuming you're using Rails)...
|
87
128
|
|
88
|
-
# Return the default
|
89
|
-
def
|
90
|
-
# If the default
|
91
|
-
if @
|
92
|
-
|
93
|
-
|
94
|
-
|
129
|
+
# Return the default address if it already exists, or call the address factory to make one
|
130
|
+
def default_address
|
131
|
+
# If the default address exists, but has been cleared from the database...
|
132
|
+
@default_address = nil if @default_address && !Account.exists?(@default_address.id)
|
133
|
+
@default_address ||= create(:address)
|
134
|
+
end
|
135
|
+
|
136
|
+
You can pass additional arguments to your factories via the overrides hash...
|
137
|
+
|
138
|
+
Factory.build(:user, :new_address => true)
|
139
|
+
|
140
|
+
def user
|
141
|
+
u = User.new
|
142
|
+
u.name = options[:name] || "Jimmy"
|
143
|
+
u.email = options[:email] || "jimmy#{n}@home.com"
|
144
|
+
u.role = options[:role] || :user
|
145
|
+
u.address = options[:new_address] ? create(:address) : default_address
|
146
|
+
u
|
95
147
|
end
|
96
148
|
|
97
149
|
== Helpers
|
@@ -104,19 +156,23 @@ Most of your factories are likely to simply define a list of mimimum attribute v
|
|
104
156
|
|
105
157
|
# The user factory re-written using the define helper
|
106
158
|
def user
|
107
|
-
define :name
|
108
|
-
:
|
159
|
+
define :name => "Jimmy",
|
160
|
+
:email => "jimmy#{n}@home.com",
|
161
|
+
:role => :user,
|
162
|
+
:address => default_address
|
109
163
|
end
|
110
164
|
|
111
165
|
Note that you don't have to worry about handling the overrides here, they will be applied automatically if present, just define the defaults.
|
112
166
|
|
113
|
-
The best thing about this is that there are no pesky blocks to worry about. The define argument is just a regular hash, you have complete freedom to choose how
|
167
|
+
The best thing about this is that there are no pesky blocks to worry about. The define argument is just a regular hash, you have complete freedom to choose how to generate the values to be passed into it.
|
114
168
|
|
115
169
|
The define method will return the object, you can grab this for additional manipulation as you would expect...
|
116
170
|
|
117
171
|
def user
|
118
|
-
u = define :name
|
119
|
-
:
|
172
|
+
u = define :name => "Jimmy",
|
173
|
+
:email => "jimmy#{n}@home.com",
|
174
|
+
:role => :user,
|
175
|
+
:address => default_address
|
120
176
|
u.do_something
|
121
177
|
u # Remember to return it at the end
|
122
178
|
end
|
@@ -125,9 +181,11 @@ If for any reason you want to have your factory method named differently from th
|
|
125
181
|
|
126
182
|
# Called via Factory.create(:jimmy)
|
127
183
|
def jimmy
|
128
|
-
define :class
|
129
|
-
|
130
|
-
|
184
|
+
u = define :class => :user,
|
185
|
+
:name => "Jimmy",
|
186
|
+
:email => "jimmy#{n}@home.com",
|
187
|
+
:role => :user,
|
188
|
+
:address => default_address
|
131
189
|
end
|
132
190
|
|
133
191
|
=== Inherit
|
@@ -136,24 +194,18 @@ You can inherit from other factories via the inherit method. So for example to c
|
|
136
194
|
|
137
195
|
# Called via Factory.create(:admin)
|
138
196
|
def admin
|
139
|
-
inherit(:user, :
|
197
|
+
inherit(:user, :role => :admin) # Pass in any attribute overrides you want
|
140
198
|
end
|
141
199
|
|
142
200
|
=== Unique Attributes (n)
|
143
201
|
|
144
202
|
If you want to generate unique attributes you can call the n method which will automatically increment the next time it is called.
|
145
|
-
For example to give each user a unique name...
|
146
|
-
|
147
|
-
def user
|
148
|
-
define :name => "Jimmy#{n}",
|
149
|
-
:account => default_account
|
150
|
-
end
|
151
203
|
|
152
204
|
Note that every time n is called it will increment, it does not implement a unique counter per attribute.
|
153
205
|
|
154
206
|
=== Reset
|
155
207
|
|
156
|
-
|
208
|
+
Clear all instance variables in the factory. This may be useful to run between tests depending on your factory logic...
|
157
209
|
|
158
210
|
before(:each) do
|
159
211
|
Factory.reset
|
@@ -169,7 +221,7 @@ Note that this relies on the instance having a valid? method, so in practice thi
|
|
169
221
|
|
170
222
|
=== Attributes For
|
171
223
|
|
172
|
-
Returns the attributes that would be applied
|
224
|
+
Returns the attributes that would be applied by a given factory method...
|
173
225
|
|
174
226
|
valid_attributes = Factory.attributes_for(:user)
|
175
227
|
|
@@ -182,4 +234,6 @@ Want any? Feel free to let me know.
|
|
182
234
|
== Thanks
|
183
235
|
|
184
236
|
Cranky was inspired by factory_girl[http://github.com/thoughtbot/factory_girl] and miniskirt[http://gist.github.com/273579].
|
237
|
+
|
185
238
|
Thanks to both.
|
239
|
+
|
data/lib/cranky.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class Cranky
|
2
2
|
|
3
|
-
VERSION = "0.0.
|
3
|
+
VERSION = "0.0.4"
|
4
4
|
|
5
5
|
# Dir.glob("#{File.expand_path(File.dirname(__FILE__))}/*.rb").each do |file|
|
6
6
|
# require file
|
@@ -66,7 +66,7 @@ class Cranky
|
|
66
66
|
item = get_constant(attrs[:class] ? attrs[:class] : @what.last).new
|
67
67
|
final_attrs.delete(:class)
|
68
68
|
final_attrs.each do |attr, value|
|
69
|
-
item.send("#{attr}=", value)
|
69
|
+
item.send("#{attr}=", value) if item.respond_to?("#{attr}=")
|
70
70
|
end
|
71
71
|
item
|
72
72
|
end
|
data/spec/cranky_spec.rb
CHANGED
@@ -72,6 +72,12 @@ describe Cranky do
|
|
72
72
|
error = true
|
73
73
|
end
|
74
74
|
error.should == true
|
75
|
+
Factory.debug = false
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should allow arguments to be passed in the overrides hash" do
|
79
|
+
Factory.build(:user).argument_received.should == nil
|
80
|
+
Factory.build(:user, :argument_supplied => true).argument_received.should == true
|
75
81
|
end
|
76
82
|
|
77
83
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,7 @@ class User
|
|
8
8
|
attr_accessor :role
|
9
9
|
attr_accessor :email
|
10
10
|
attr_accessor :unique
|
11
|
+
attr_accessor :argument_received
|
11
12
|
|
12
13
|
def save
|
13
14
|
@saved = true
|
@@ -46,11 +47,13 @@ class Cranky
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def user_by_define
|
49
|
-
define :class => :user,
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
u = define :class => :user,
|
51
|
+
:name => "Fred",
|
52
|
+
:role => :user,
|
53
|
+
:unique => "value#{n}",
|
54
|
+
:email => "fred@home.com"
|
55
|
+
u.argument_received = true if options[:argument_supplied]
|
56
|
+
u
|
54
57
|
end
|
55
58
|
alias :user :user_by_define
|
56
59
|
|