shared_should 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +238 -0
- data/VERSION +1 -1
- data/lib/shared_should.rb +22 -10
- data/shared_should.gemspec +5 -5
- data/test/test_shared_should.rb +83 -41
- metadata +19 -19
- data/README.rdoc +0 -235
data/README.md
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
# Shared Should - Share and reuse shoulds, contexts, and setups with Shoulda - easy, schmeasy.
|
2
|
+
|
3
|
+
Shared Should allows you to easily create reusable shoulds, contexts and setups with familiar looking Shoulda syntax. Inspired by Rspec's shared example groups for context reuse, Shared Should allows sharing of contexts, shoulds,
|
4
|
+
and setup blocks. Shared Should goes even further by allowing an initialization block and parameterization to fine-tune the usage of the shared functionality.
|
5
|
+
|
6
|
+
## Quick-Start Examples
|
7
|
+
|
8
|
+
Some quick examples to get you started using Shared Should. The domain of the examples is customers renting and purchasing textbooks - like we do at [BookRenter.com](http://www.bookrenter.com "BookRenter.com").
|
9
|
+
|
10
|
+
### Shared Should
|
11
|
+
|
12
|
+
Sharing shoulds is easy.
|
13
|
+
|
14
|
+
context "Book" do
|
15
|
+
context "with an in-stock book" do
|
16
|
+
setup { @book = Book.new(:quantity => 1, :price => 10_00 }
|
17
|
+
|
18
|
+
### Define a shared should
|
19
|
+
share_should "be available for checkout" { assert @book.available_for_checkout? }
|
20
|
+
|
21
|
+
context "with a rentable book" do
|
22
|
+
setup { @book.rentable = true }
|
23
|
+
|
24
|
+
### Use the "be available for checkout" share_should
|
25
|
+
use_should "be available for checkout"
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with a purchasable book" do
|
29
|
+
setup { @book.purchasable = true }
|
30
|
+
|
31
|
+
### Use the "be available for checkout" share_should in this context too
|
32
|
+
use_should "be available for checkout"
|
33
|
+
end
|
34
|
+
|
35
|
+
### ...or DRY it up by using .when and an initialization block
|
36
|
+
use_should("be available for checkout").when("rentable") { @book.rentable = true }
|
37
|
+
use_should("be available for checkout").when("purchasable") { @book.purchasable = true }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
### Shared Setup
|
42
|
+
|
43
|
+
Sharing setups is easy, too.
|
44
|
+
|
45
|
+
context "Book" do
|
46
|
+
### Define a shared setup
|
47
|
+
share_setup "for an in-stock book" { @book = Book.new(:quantity => 1, :price => 10_00) }
|
48
|
+
|
49
|
+
context "with an in-stock rentable book" do
|
50
|
+
### Use the shared setup here
|
51
|
+
use_setup "for an in-stock book"
|
52
|
+
|
53
|
+
### Do some additional setup after the shared setup
|
54
|
+
setup { @book.rentable = true }
|
55
|
+
|
56
|
+
should "be available for checkout" { assert @book.available_for_checkout? }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "with an in-stock purchasable book" do
|
60
|
+
### Use the shared setup again
|
61
|
+
use_setup "for an in-stock book"
|
62
|
+
|
63
|
+
setup { @book.purchasable = true }
|
64
|
+
|
65
|
+
should "be available for checkout" { assert @book.available_for_checkout? }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
### Shared Context
|
70
|
+
|
71
|
+
Sharing whole contexts? Schmeasy!
|
72
|
+
|
73
|
+
context "Book" do
|
74
|
+
context "with an in-stock book" do
|
75
|
+
setup { @book = Book.new(:quantity => 1, :price => 10_00) }
|
76
|
+
|
77
|
+
### Define a shared context
|
78
|
+
share_context "for a book available for checkout" do
|
79
|
+
should "be in stock" { assert @book.quantity > 0 }
|
80
|
+
should "have a non-negative price" { assert @book.price > 0 }
|
81
|
+
should "be rentable or purchasable" { assert @book.rentable || @book.purchasable }
|
82
|
+
end
|
83
|
+
|
84
|
+
context "with a rentable book" do
|
85
|
+
setup { @book.rentable = true }
|
86
|
+
|
87
|
+
### Run the shoulds inside the shared context with a rentable book
|
88
|
+
use_context "for a book available for checkout"
|
89
|
+
end
|
90
|
+
|
91
|
+
context "with a purchasable book" do
|
92
|
+
setup { @book.purchasable = true }
|
93
|
+
|
94
|
+
### Run the shoulds inside the shared context again with a purchasable book
|
95
|
+
use_context "for a book available for checkout"
|
96
|
+
end
|
97
|
+
|
98
|
+
### ...or DRY it up by using .when and an initialization block
|
99
|
+
use_context("for a book available for checkout").when("rentable") { @book.rentable = true }
|
100
|
+
use_context("for a book available for checkout").when("purchasable") { @book.purchasable = true }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
## More Information on Syntax and Usage
|
105
|
+
|
106
|
+
### Finding Your Share
|
107
|
+
|
108
|
+
Some rules:
|
109
|
+
|
110
|
+
* When <tt>use\_should</tt>, <tt>use\_context</tt> or <tt>use\_setup</tt> is invoked, it searches up the context hierarchy to find a matching shared definition.
|
111
|
+
* You can redefine your shares by using the same name. These shares will only be available in in the current and descendant contexts.
|
112
|
+
* Shares defined at the root (on your TestCase) are available in all contexts.
|
113
|
+
* If you define a shared setup at the root level, you will need to call <tt>super</tt> if you have a setup instance method for your test.
|
114
|
+
|
115
|
+
### Initialization Block
|
116
|
+
|
117
|
+
The shared invocation accepts an initialization block by chaining <tt>when</tt> followed by a block. This block can be used to create or modify instance variables used by the shared functionality. It always executes before the shared functionality.
|
118
|
+
|
119
|
+
context "Book" do
|
120
|
+
setup { @book = Book.new(:quantity => 1, :price => 10_00) }
|
121
|
+
|
122
|
+
share_should "be available for checkout" { assert @book.available_for_checkout? }
|
123
|
+
|
124
|
+
context "with a rentable book" do
|
125
|
+
# when share_should "be available for checkout" is executed, @book will have rentable equal to true
|
126
|
+
use_should("be available for checkout").when("rentable") { @book.rentable = true }
|
127
|
+
end
|
128
|
+
|
129
|
+
context "with a purchasable book" do
|
130
|
+
use_should("be available for checkout").when("purchasable") { @book.purchasable = true }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
### Parameterizing Shares
|
135
|
+
|
136
|
+
Shared functions can also be parameterized using block parameters. This can be done for shared setups, shoulds, and the setups and shoulds contained within a shared context. The value passed to the shared function is the return value of the <tt>with</tt> parameterization block. The below example parameterizes a shared setup.
|
137
|
+
|
138
|
+
context "Book" do
|
139
|
+
share_setup "for an in-stock book" do |rentable|
|
140
|
+
@book = Book.new(:quantity => 1, :price => 10_00, :rentable => rentable, :purchasable => false)
|
141
|
+
end
|
142
|
+
|
143
|
+
context "with rentable book" do
|
144
|
+
# the return value of the block is "true" which will be passed as the block parameter "rentable"
|
145
|
+
use_setup("for an in-stock book").with { true }
|
146
|
+
|
147
|
+
should "be available for checkout" { assert @book.available_for_checkout? }
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
Here is a parameterized shared should.
|
152
|
+
|
153
|
+
context "Book" do
|
154
|
+
context "with in-stock book" do
|
155
|
+
setup { @book = Book.new(:quantity => 1) }
|
156
|
+
|
157
|
+
share_should "be unavailable for checkout for price" do |price|
|
158
|
+
@book.price = price
|
159
|
+
assert_false @book.available_for_checkout?
|
160
|
+
end
|
161
|
+
|
162
|
+
use_should("be unavailable for checkout for price").with("zero") { 0 }
|
163
|
+
use_should("be unavailable for checkout for price").with("a negative price") { -1 }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
And a parameterized shared context.
|
168
|
+
|
169
|
+
context "Book" do
|
170
|
+
context "with in-stock book" do
|
171
|
+
setup { @book = Book.new(:quantity => 1) }
|
172
|
+
|
173
|
+
share_context "for a book available for checkout at price" do
|
174
|
+
# parameters are on the setup and shoulds, not on the context
|
175
|
+
setup { |price| @book.price = price }
|
176
|
+
|
177
|
+
# we could also access price in the should blocks, but we don't need it again
|
178
|
+
should "be in stock" { assert @book.quantity > 0 }
|
179
|
+
should "have a non-negative price" { assert @book.price > 0 }
|
180
|
+
should "be rentable or purchasable" { assert @book.rentable || @book.purchasable }
|
181
|
+
end
|
182
|
+
|
183
|
+
use_context("for a book available for checkout at price").with("a positive price") { 10_00 }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
The shared functions also accept multiple parameters when the parameterization block returns an array.
|
188
|
+
|
189
|
+
context "Book" do
|
190
|
+
context "with rentable book" do
|
191
|
+
setup { @book = Book.new(:rentable => true) }
|
192
|
+
|
193
|
+
share_should "be unavailable for checkout for quantity and price" do |quantity, price|
|
194
|
+
@book.quantity = quantity
|
195
|
+
@book.price = price
|
196
|
+
assert_false @book.available_for_checkout?
|
197
|
+
end
|
198
|
+
|
199
|
+
use_should("be unavailable for checkout for quantity and price").with("a zero quantity") { [0, 10_00] }
|
200
|
+
use_should("be unavailable for checkout for quantity and price").with("a zero price") { [1, 0] }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
### Creating a Library of Shared Functionality
|
205
|
+
|
206
|
+
The shared functions can also be re-usable across multiple test cases.
|
207
|
+
|
208
|
+
In your test helper file:
|
209
|
+
|
210
|
+
class Test::Unit::TestCase
|
211
|
+
share_setup "for an in-stock book" do |rentable, purchasable|
|
212
|
+
@book = Book.new(:quantity => 1, :price => 10_00, :rentable => rentable, :purchasable => purchasable)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
In your test file:
|
217
|
+
|
218
|
+
class BookTest < Test::Unit::TestCase
|
219
|
+
context "with an in-stock book" do
|
220
|
+
use_setup("for an in-stock book").with { [true, true] }
|
221
|
+
|
222
|
+
should "be in stock" { assert @book.quantity > 0 }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
# Credits
|
228
|
+
|
229
|
+
Shared Shoulda is maintained by [Michael Pearce](http://github.com/michaelgpearce) and is funded by [BookRenter.com](http://www.bookrenter.com "BookRenter.com"). Many of the ideas that have inspired Shared Should come
|
230
|
+
from practical usage by the Bookrenter software development team and conversations with Bookrenter developers [Andrew Wheeler](http://github.com/jawheeler), [Ben Somers](http://github.com/bensomers), and [Philippe Huibonhoa](http://github.com/phuibonhoa).
|
231
|
+
|
232
|
+
![BookRenter.com Logo](http://assets0.bookrenter.com/images/header/bookrenter_logo.gif "BookRenter.com")
|
233
|
+
|
234
|
+
|
235
|
+
# Copyright
|
236
|
+
|
237
|
+
Copyright (c) 2011 Michael Pearce, Bookrenter.com. See LICENSE.txt for further details.
|
238
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.1
|
data/lib/shared_should.rb
CHANGED
@@ -120,7 +120,7 @@ module Shoulda::SharedContext
|
|
120
120
|
shared_setup_block = find_shared_setup_block(shared_name)
|
121
121
|
setup do
|
122
122
|
if initialization_block = shared_proxy.initialization_block
|
123
|
-
setup_shared_values(shared_proxy.
|
123
|
+
setup_shared_values(shared_proxy.description, shared_proxy.initialization_block)
|
124
124
|
end
|
125
125
|
call_block_with_shared_value(shared_setup_block)
|
126
126
|
end
|
@@ -310,29 +310,41 @@ end
|
|
310
310
|
|
311
311
|
|
312
312
|
class Shoulda::SharedProxy
|
313
|
-
attr_accessor :shared_name, :
|
313
|
+
attr_accessor :shared_name, :description, :initialization_blocks
|
314
314
|
|
315
315
|
def initialize(shared_name)
|
316
316
|
self.shared_name = shared_name
|
317
|
+
self.initialization_blocks = []
|
317
318
|
end
|
318
319
|
|
319
|
-
def when(
|
320
|
-
when_helper("when",
|
320
|
+
def when(description = nil, &initialization_block)
|
321
|
+
when_helper("when", description, &initialization_block)
|
322
|
+
return self
|
321
323
|
end
|
322
324
|
|
323
|
-
def with(
|
324
|
-
when_helper("with",
|
325
|
+
def with(description = nil, &initialization_block)
|
326
|
+
when_helper("with", description, &initialization_block)
|
327
|
+
return nil
|
325
328
|
end
|
326
329
|
|
327
330
|
def execute(context)
|
328
331
|
method_name = context.send(:shared_method_name, :should, shared_name)
|
329
|
-
context.send(method_name,
|
332
|
+
context.send(method_name, description, &initialization_block)
|
333
|
+
end
|
334
|
+
|
335
|
+
def initialization_block
|
336
|
+
blocks = initialization_blocks
|
337
|
+
return Proc.new do
|
338
|
+
blocks.collect {|block| block.bind(self).call}.last
|
339
|
+
end
|
330
340
|
end
|
331
341
|
|
332
342
|
private
|
333
343
|
|
334
|
-
def when_helper(
|
335
|
-
|
336
|
-
|
344
|
+
def when_helper(conditional, description = nil, &initialization_block)
|
345
|
+
if description
|
346
|
+
self.description = "#{self.description}#{self.description.nil? ? nil : ' and '}#{conditional} #{description}"
|
347
|
+
end
|
348
|
+
self.initialization_blocks << initialization_block
|
337
349
|
end
|
338
350
|
end
|
data/shared_should.gemspec
CHANGED
@@ -5,23 +5,23 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{shared_should}
|
8
|
-
s.version = "0.6.
|
8
|
+
s.version = "0.6.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Michael Pearce"]
|
12
|
-
s.date = %q{2011-02
|
12
|
+
s.date = %q{2011-03-02}
|
13
13
|
s.description = %q{Share and reuse shoulds, contexts, and setup in Shoulda.}
|
14
14
|
s.email = %q{michael.pearce@bookrenter.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE.txt",
|
17
|
-
"README.
|
17
|
+
"README.md"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
21
|
"Gemfile",
|
22
22
|
"Gemfile.lock",
|
23
23
|
"LICENSE.txt",
|
24
|
-
"README.
|
24
|
+
"README.md",
|
25
25
|
"Rakefile",
|
26
26
|
"VERSION",
|
27
27
|
"lib/shared_should.rb",
|
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.homepage = %q{http://github.com/michaelgpearce/shared_should}
|
34
34
|
s.licenses = ["MIT"]
|
35
35
|
s.require_paths = ["lib"]
|
36
|
-
s.rubygems_version = %q{1.
|
36
|
+
s.rubygems_version = %q{1.5.2}
|
37
37
|
s.summary = %q{Share and reuse shoulds, contexts, and setup in Shoulda.}
|
38
38
|
s.test_files = [
|
39
39
|
"test/helper.rb",
|
data/test/test_shared_should.rb
CHANGED
@@ -64,7 +64,18 @@ class TestSharedShould < Test::Unit::TestCase
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
use_context("for a valid specified value").
|
67
|
+
use_context("for a valid specified value").with("true") { true }
|
68
|
+
|
69
|
+
context "with chaining" do
|
70
|
+
share_context "for a chained value" do
|
71
|
+
should "chain initialization block and be with params" do |value|
|
72
|
+
assert @chain
|
73
|
+
assert value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
use_context("for a chained value").when("using initialization chain") { @chain = true }.with("true") { true }
|
78
|
+
end
|
68
79
|
end
|
69
80
|
end
|
70
81
|
|
@@ -138,7 +149,7 @@ class TestSharedShould < Test::Unit::TestCase
|
|
138
149
|
end
|
139
150
|
|
140
151
|
context "with value in initializer" do
|
141
|
-
use_should("be a true value").
|
152
|
+
use_should("be a true value").when("value is true") { @value = true }
|
142
153
|
end
|
143
154
|
end
|
144
155
|
|
@@ -151,7 +162,17 @@ class TestSharedShould < Test::Unit::TestCase
|
|
151
162
|
assert_equal value, @value
|
152
163
|
end
|
153
164
|
|
154
|
-
use_should("be a valid specified value").
|
165
|
+
use_should("be a valid specified value").with("true") { true }
|
166
|
+
|
167
|
+
context "with chaining" do
|
168
|
+
share_should "be a valid specified value" do |value|
|
169
|
+
assert @chain
|
170
|
+
assert value
|
171
|
+
end
|
172
|
+
|
173
|
+
use_should("be a valid specified value").when("using initialization chain") { @chain = true }.with("true") { true }
|
174
|
+
use_should("be a valid specified value").when("using initialization chain xxxx") { @chain = true }.with("true") { true }
|
175
|
+
end
|
155
176
|
end
|
156
177
|
end
|
157
178
|
|
@@ -248,7 +269,7 @@ class TestSharedShould < Test::Unit::TestCase
|
|
248
269
|
@value = @initialization_value
|
249
270
|
end
|
250
271
|
|
251
|
-
use_setup("for value").
|
272
|
+
use_setup("for value").when("initialization value is true") { @initialization_value = true }
|
252
273
|
|
253
274
|
should "have a true value from shared setup" do
|
254
275
|
assert @value
|
@@ -256,7 +277,7 @@ class TestSharedShould < Test::Unit::TestCase
|
|
256
277
|
end
|
257
278
|
end
|
258
279
|
|
259
|
-
context "with
|
280
|
+
context "with param block" do
|
260
281
|
share_setup "for value" do |value|
|
261
282
|
@value = value
|
262
283
|
end
|
@@ -267,12 +288,30 @@ class TestSharedShould < Test::Unit::TestCase
|
|
267
288
|
@value = false
|
268
289
|
end
|
269
290
|
|
270
|
-
use_setup("for value").with("true
|
291
|
+
use_setup("for value").with("true") { true }
|
271
292
|
|
272
293
|
should "have a true value from shared setup" do
|
273
294
|
assert @value
|
274
295
|
end
|
275
296
|
end
|
297
|
+
|
298
|
+
context "with chaining" do
|
299
|
+
setup do
|
300
|
+
@chain = nil
|
301
|
+
@value = nil
|
302
|
+
end
|
303
|
+
|
304
|
+
share_setup "for value" do |value|
|
305
|
+
@value = value
|
306
|
+
end
|
307
|
+
|
308
|
+
use_setup("for value").when("using initialization chain") { @chain = true }.with("true") { true }
|
309
|
+
|
310
|
+
should "have used share with chain and params" do
|
311
|
+
assert @chain
|
312
|
+
assert @value
|
313
|
+
end
|
314
|
+
end
|
276
315
|
end
|
277
316
|
end
|
278
317
|
|
@@ -394,41 +433,44 @@ class TestSharedShould < Test::Unit::TestCase
|
|
394
433
|
|
395
434
|
# ensure test methods are created
|
396
435
|
expected_method_names = [
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
436
|
+
'test: should be a valid should test in class. ',
|
437
|
+
'test: .share_context with params with chaining when using initialization chain and with true for a chained value should chain initialization block and be with params. ',
|
438
|
+
'test: .share_context with params with true for a valid specified value should call setup in shared context. ',
|
439
|
+
'test: .share_context with params with true for a valid specified value should have specified value. ',
|
440
|
+
'test: .share_context with params with true for a valid specified value should setup @expected_value. ',
|
441
|
+
'test: .share_context without params with value in initializer when a true value for a valid value should call setup in shared context. ',
|
442
|
+
'test: .share_context without params with value in initializer when a true value for a valid value should have true value. ',
|
443
|
+
'test: .share_context without params with value in setup for a valid value should call setup in shared context. ',
|
444
|
+
'test: .share_context without params with value in setup for a valid value should have true value. ',
|
445
|
+
'test: .share_setup with param block with chaining should have used share with chain and params. ',
|
446
|
+
'test: .share_setup with param block with shared setup value should have a true value from shared setup. ',
|
447
|
+
'test: .share_setup without params with initialization block should have a true value from shared setup. ',
|
448
|
+
'test: .share_setup without params without initialization block should have a true value from shared setup. ',
|
449
|
+
'test: .share_should with params with chaining when using initialization chain and with true should be a valid specified value. ',
|
450
|
+
'test: .share_should with params with chaining when using initialization chain xxxx and with true should be a valid specified value. ',
|
451
|
+
'test: .share_should with params with true should be a valid specified value. ',
|
452
|
+
'test: .share_should without params when value in initializer when value is true should be a true value. ',
|
453
|
+
'test: .share_should without params with value in initializer when value is true should be a true value. ',
|
454
|
+
'test: .share_should without params with value in setup should be a true value. ',
|
455
|
+
'test: .shared_context_should with params be valid for specified value should call setup in shared context. ',
|
456
|
+
'test: .shared_context_should with params be valid for specified value should have specified value. ',
|
457
|
+
'test: .shared_context_should with params be valid for specified value should setup @expected_value. ',
|
458
|
+
'test: .shared_context_should without params be valid should call setup in shared context. ',
|
459
|
+
'test: .shared_context_should without params be valid should have true value. ',
|
460
|
+
'test: .shared_setup with params with shared setup value should have a true value from shared setup. ',
|
461
|
+
'test: .shared_setup without params with shared setup value should have a true value from shared setup. ',
|
462
|
+
'test: .shared_should with params should have specified value. ',
|
463
|
+
'test: .shared_should without params should have true value. ',
|
464
|
+
'test: SharedShould should execute setup instance method. ',
|
465
|
+
'test: context directly under test class for a valid context test should have a true value. ',
|
466
|
+
'test: context directly under test class should be a valid should test. ',
|
467
|
+
'test: for a valid context test in class should have a true value. ',
|
468
|
+
'test: parameterized block with an array be valid with shared context should do something with shared_value. ',
|
469
|
+
'test: parameterized block with an array be valid with shared context should do something with value block param. ',
|
470
|
+
'test: parameterized block with an array be valid with shared context should do something with value block params. ',
|
471
|
+
'test: parameterized block with an array should be valid with shared should. ',
|
472
|
+
'test: shoulda macro should be a valid macro. '
|
473
|
+
].inject({}) do |hash, expected_method_name|
|
432
474
|
hash[expected_method_name] = true
|
433
475
|
hash
|
434
476
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shared_should
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 0.6.
|
9
|
+
- 1
|
10
|
+
version: 0.6.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Michael Pearce
|
@@ -15,13 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-02
|
18
|
+
date: 2011-03-02 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
prerelease: false
|
23
22
|
name: shoulda
|
24
|
-
type: :development
|
25
23
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
24
|
none: false
|
27
25
|
requirements:
|
@@ -31,11 +29,11 @@ dependencies:
|
|
31
29
|
segments:
|
32
30
|
- 0
|
33
31
|
version: "0"
|
32
|
+
prerelease: false
|
33
|
+
type: :development
|
34
34
|
requirement: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
prerelease: false
|
37
36
|
name: bundler
|
38
|
-
type: :development
|
39
37
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
38
|
none: false
|
41
39
|
requirements:
|
@@ -47,11 +45,11 @@ dependencies:
|
|
47
45
|
- 0
|
48
46
|
- 0
|
49
47
|
version: 1.0.0
|
48
|
+
prerelease: false
|
49
|
+
type: :development
|
50
50
|
requirement: *id002
|
51
51
|
- !ruby/object:Gem::Dependency
|
52
|
-
prerelease: false
|
53
52
|
name: jeweler
|
54
|
-
type: :development
|
55
53
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
56
54
|
none: false
|
57
55
|
requirements:
|
@@ -63,11 +61,11 @@ dependencies:
|
|
63
61
|
- 5
|
64
62
|
- 2
|
65
63
|
version: 1.5.2
|
64
|
+
prerelease: false
|
65
|
+
type: :development
|
66
66
|
requirement: *id003
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
|
-
prerelease: false
|
69
68
|
name: rcov
|
70
|
-
type: :development
|
71
69
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
72
70
|
none: false
|
73
71
|
requirements:
|
@@ -77,11 +75,11 @@ dependencies:
|
|
77
75
|
segments:
|
78
76
|
- 0
|
79
77
|
version: "0"
|
78
|
+
prerelease: false
|
79
|
+
type: :development
|
80
80
|
requirement: *id004
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
|
-
prerelease: false
|
83
82
|
name: shoulda
|
84
|
-
type: :runtime
|
85
83
|
version_requirements: &id005 !ruby/object:Gem::Requirement
|
86
84
|
none: false
|
87
85
|
requirements:
|
@@ -91,11 +89,11 @@ dependencies:
|
|
91
89
|
segments:
|
92
90
|
- 0
|
93
91
|
version: "0"
|
92
|
+
prerelease: false
|
93
|
+
type: :runtime
|
94
94
|
requirement: *id005
|
95
95
|
- !ruby/object:Gem::Dependency
|
96
|
-
prerelease: false
|
97
96
|
name: shoulda
|
98
|
-
type: :development
|
99
97
|
version_requirements: &id006 !ruby/object:Gem::Requirement
|
100
98
|
none: false
|
101
99
|
requirements:
|
@@ -105,6 +103,8 @@ dependencies:
|
|
105
103
|
segments:
|
106
104
|
- 0
|
107
105
|
version: "0"
|
106
|
+
prerelease: false
|
107
|
+
type: :development
|
108
108
|
requirement: *id006
|
109
109
|
description: Share and reuse shoulds, contexts, and setup in Shoulda.
|
110
110
|
email: michael.pearce@bookrenter.com
|
@@ -114,13 +114,13 @@ extensions: []
|
|
114
114
|
|
115
115
|
extra_rdoc_files:
|
116
116
|
- LICENSE.txt
|
117
|
-
- README.
|
117
|
+
- README.md
|
118
118
|
files:
|
119
119
|
- .document
|
120
120
|
- Gemfile
|
121
121
|
- Gemfile.lock
|
122
122
|
- LICENSE.txt
|
123
|
-
- README.
|
123
|
+
- README.md
|
124
124
|
- Rakefile
|
125
125
|
- VERSION
|
126
126
|
- lib/shared_should.rb
|
@@ -158,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
158
|
requirements: []
|
159
159
|
|
160
160
|
rubyforge_project:
|
161
|
-
rubygems_version: 1.
|
161
|
+
rubygems_version: 1.5.2
|
162
162
|
signing_key:
|
163
163
|
specification_version: 3
|
164
164
|
summary: Share and reuse shoulds, contexts, and setup in Shoulda.
|
data/README.rdoc
DELETED
@@ -1,235 +0,0 @@
|
|
1
|
-
= Shared Should - Share and reuse shoulds, contexts, and setups with Shoulda - easy, schmeasy.
|
2
|
-
|
3
|
-
Shared Should allows you to easily create reusable shoulds, contexts and setups with familiar looking Shoulda syntax. Inspired by Rspec's shared example groups for context reuse, Shared Should allows sharing of contexts, shoulds,
|
4
|
-
and setup blocks. Shared Should goes even further by allowing an initialization block and parameterization to fine-tune the usage of the shared functionality.
|
5
|
-
|
6
|
-
== Quick-Start Examples
|
7
|
-
|
8
|
-
Some quick examples to get you started using Shared Should. The domain is customers renting and purchasing textbooks - like we do at Bookrenter.com.
|
9
|
-
|
10
|
-
=== Shared Should
|
11
|
-
|
12
|
-
Sharing shoulds is easy.
|
13
|
-
|
14
|
-
context "Book" do
|
15
|
-
context "with an in-stock book" do
|
16
|
-
setup { @book = Book.new(:quantity => 1, :price => 10_00 }
|
17
|
-
|
18
|
-
### Define a shared should
|
19
|
-
share_should "be available for checkout" { assert @book.available_for_checkout? }
|
20
|
-
|
21
|
-
context "with a rentable book" do
|
22
|
-
setup { @book.rentable = true }
|
23
|
-
|
24
|
-
### Use the "be available for checkout" share_should
|
25
|
-
use_should "be available for checkout"
|
26
|
-
end
|
27
|
-
|
28
|
-
context "with a purchasable book" do
|
29
|
-
setup { @book.purchasable = true }
|
30
|
-
|
31
|
-
### Use the "be available for checkout" share_should in this context too
|
32
|
-
use_should "be available for checkout"
|
33
|
-
end
|
34
|
-
|
35
|
-
### ...or DRY it up by using .with or .when and an initialization block
|
36
|
-
use_should("be available for checkout").when("rentable") { @book.rentable = true }
|
37
|
-
use_should("be available for checkout").when("purchasable") { @book.purchasable = true }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
=== Shared Setup
|
42
|
-
|
43
|
-
Sharing setups is easy, too.
|
44
|
-
|
45
|
-
context "Book" do
|
46
|
-
### Define a shared setup
|
47
|
-
share_setup "for an in-stock book" { @book = Book.new(:quantity => 1, :price => 10_00) }
|
48
|
-
|
49
|
-
context "with an in-stock rentable book" do
|
50
|
-
### Use the shared setup here
|
51
|
-
use_setup "for an in-stock book"
|
52
|
-
|
53
|
-
### Do some additional setup after the shared setup
|
54
|
-
setup { @book.rentable = true }
|
55
|
-
|
56
|
-
should "be available for checkout" { assert @book.available_for_checkout? }
|
57
|
-
end
|
58
|
-
|
59
|
-
context "with an in-stock purchasable book" do
|
60
|
-
### Use the shared setup again
|
61
|
-
use_setup "for an in-stock book"
|
62
|
-
|
63
|
-
setup { @book.purchasable = true }
|
64
|
-
|
65
|
-
should "be available for checkout" { assert @book.available_for_checkout? }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
=== Shared Context
|
70
|
-
|
71
|
-
Sharing whole contexts? Schmeasy!
|
72
|
-
|
73
|
-
context "Book" do
|
74
|
-
context "with an in-stock book" do
|
75
|
-
setup { @book = Book.new(:quantity => 1, :price => 10_00) }
|
76
|
-
|
77
|
-
### Define a shared context
|
78
|
-
share_context "for a book available for checkout" do
|
79
|
-
should "be in stock" { assert @book.quantity > 0 }
|
80
|
-
should "have a non-negative price" { assert @book.price > 0 }
|
81
|
-
should "be rentable or purchasable" { assert @book.rentable || @book.purchasable }
|
82
|
-
end
|
83
|
-
|
84
|
-
context "with a rentable book" do
|
85
|
-
setup { @book.rentable = true }
|
86
|
-
|
87
|
-
### Run the shoulds inside the shared context with a rentable book
|
88
|
-
use_context "for a book available for checkout"
|
89
|
-
end
|
90
|
-
|
91
|
-
context "with a purchasable book" do
|
92
|
-
setup { @book.purchasable = true }
|
93
|
-
|
94
|
-
### Run the shoulds inside the shared context again with a purchasable book
|
95
|
-
use_context "for a book available for checkout"
|
96
|
-
end
|
97
|
-
|
98
|
-
### ...or DRY it up by using .with or .when and an initialization block
|
99
|
-
use_context("for a book available for checkout").when("rentable") { @book.rentable = true }
|
100
|
-
use_context("for a book available for checkout").when("purchasable") { @book.purchasable = true }
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
== More Information on Syntax and Usage
|
105
|
-
|
106
|
-
=== Finding Your Share
|
107
|
-
|
108
|
-
Some rules:
|
109
|
-
* When <tt>use_should</tt>, <tt>use_context</tt> or <tt>use_setup</tt> is invoked, it searches up the context hierarchy to find a matching shared definition.
|
110
|
-
* You can redefine your shares by using the same name. These shares will only be available in in the current and descendant contexts.
|
111
|
-
* Shares defined at the root (on your TestCase) are available in all contexts.
|
112
|
-
* If you define a shared setup at the root level, you will need to call <tt>super</tt> if you have a setup instance method for your test.
|
113
|
-
|
114
|
-
=== Initialization Block
|
115
|
-
|
116
|
-
The shared invocation accepts an initialization block by chaining <tt>when</tt> or <tt>with</tt>. This block can be used to create or modify instance variables used by the shared functionality. It always executes before the shared functionality.
|
117
|
-
|
118
|
-
context "Book" do
|
119
|
-
setup { @book = Book.new(:quantity => 1, :price => 10_00) }
|
120
|
-
|
121
|
-
share_should "be available for checkout" { assert @book.available_for_checkout? }
|
122
|
-
|
123
|
-
context "with a rentable book" do
|
124
|
-
# when share_should "be available for checkout" is executed, @book will have rentable equal to true
|
125
|
-
use_should "be available for checkout".when("rentable") { @book.rentable = true }
|
126
|
-
end
|
127
|
-
|
128
|
-
context "with a purchasable book" do
|
129
|
-
use_should "be available for checkout".when("purchasable") { @book.purchasable = true }
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
=== Parameterizing Shares
|
134
|
-
|
135
|
-
Shared functions can also be parameterized using block parameters. This can be done for shared setups, shoulds, and the setups and shoulds contained within a shared context. The value passed to the declared shared function is the return value of the initialization block. The below example parameterizes a shared setup.
|
136
|
-
|
137
|
-
context "Book" do
|
138
|
-
share_setup "for an in-stock book" do |rentable|
|
139
|
-
@book = Book.new(:quantity => 1, :price => 10_00, :rentable => rentable, :purchasable => false)
|
140
|
-
end
|
141
|
-
|
142
|
-
context "with rentable book" do
|
143
|
-
# the return value of the block is "true" which will be passed as the block parameter "rentable"
|
144
|
-
use_setup("for an in-stock book").with("a rentable book") { true }
|
145
|
-
|
146
|
-
should "be available for checkout" { assert @book.available_for_checkout? }
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
Here is a parameterized shared should.
|
151
|
-
|
152
|
-
context "Book" do
|
153
|
-
context "with in-stock book" do
|
154
|
-
setup { @book = Book.new(:quantity => 1) }
|
155
|
-
|
156
|
-
share_should "be unavailable for checkout for price" do |price|
|
157
|
-
@book.price = price
|
158
|
-
assert_false @book.available_for_checkout?
|
159
|
-
end
|
160
|
-
|
161
|
-
use_should("be unavailable for checkout for price").when("zero") { 0 }
|
162
|
-
use_should("be unavailable for checkout for price").when("negative") { -1 }
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
And a parameterized shared context.
|
167
|
-
|
168
|
-
context "Book" do
|
169
|
-
context "with in-stock book" do
|
170
|
-
setup { @book = Book.new(:quantity => 1) }
|
171
|
-
|
172
|
-
share_context "for a book available for checkout at price" do
|
173
|
-
# parameters are on the setup and shoulds, not on the context
|
174
|
-
setup { |price| @book.price = price }
|
175
|
-
|
176
|
-
# we could also access price in the should blocks, but we don't need it again
|
177
|
-
should "be in stock" { assert @book.quantity > 0 }
|
178
|
-
should "have a non-negative price" { assert @book.price > 0 }
|
179
|
-
should "be rentable or purchasable" { assert @book.rentable || @book.purchasable }
|
180
|
-
end
|
181
|
-
|
182
|
-
use_context("for a book available for checkout at price").when("positive") { 10_00 }
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
The shared functions also accept multiple parameters when the initialization block returns an array.
|
187
|
-
|
188
|
-
context "Book" do
|
189
|
-
context "with rentable book" do
|
190
|
-
setup { @book = Book.new(:rentable => true) }
|
191
|
-
|
192
|
-
share_should "be unavailable for checkout for quantity and price" do |quantity, price|
|
193
|
-
@book.quantity = quantity
|
194
|
-
@book.price = price
|
195
|
-
assert_false @book.available_for_checkout?
|
196
|
-
end
|
197
|
-
|
198
|
-
use_should("be unavailable for checkout for quantity and price").when("zero quantity") { [0, 10_00] }
|
199
|
-
use_should("be unavailable for checkout for quantity and price").when("zero price") { [1, 0] }
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
=== Creating a Library of Shared Functionality
|
204
|
-
|
205
|
-
The shared functions can also be re-usable across multiple test cases.
|
206
|
-
|
207
|
-
In your test helper file:
|
208
|
-
|
209
|
-
class Test::Unit::TestCase
|
210
|
-
share_setup "for an in-stock book" do |rentable, purchasable|
|
211
|
-
@book = Book.new(:quantity => 1, :price => 10_00, :rentable => rentable, :purchasable => purchasable)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
In your test file:
|
216
|
-
|
217
|
-
class BookTest < Test::Unit::TestCase
|
218
|
-
context "with an in-stock book" do
|
219
|
-
share_setup "for an in-stock book".with { [true, true] }
|
220
|
-
|
221
|
-
should "be in stock" { assert @book.quantity > 0 }
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
|
226
|
-
= Credits
|
227
|
-
|
228
|
-
Shared Shoulda is maintained by Michael Pearce (michael.pearce__at__bookrenter__com) and is funded by Bookrenter.com[http://www.bookrenter.com]. Many of the ideas that have inspired Shared Should come
|
229
|
-
from practical usage by the Bookrenter software development team and conversations with Bookrenter developers Andrew Wheeler and Philippe Huibonhoa.
|
230
|
-
|
231
|
-
|
232
|
-
= Copyright
|
233
|
-
|
234
|
-
Copyright (c) 2011 Michael Pearce, Bookrenter.com. See LICENSE.txt for further details.
|
235
|
-
|