whitestone 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,202 @@
1
+
2
+ # This file looks at the visibility of classes, modules, methods, constants and
3
+ # instance variables across insulated and non-insulated boundaries.
4
+ #
5
+ # Only T and F assertions are used so that Dfect's behaviour can be tested as
6
+ # well.
7
+
8
+ module Insulation
9
+ def answer
10
+ :foo
11
+ end
12
+ end
13
+
14
+ def ruby_version
15
+ @__ruby_version =
16
+ case RUBY_VERSION
17
+ when /^1.8/ then :v18
18
+ when /^1.9/ then :v19
19
+ else raise "Unknown version of Ruby: #{RUBY_VERSION}"
20
+ end
21
+ end
22
+
23
+ def D18(text, &block)
24
+ if ruby_version == :v18
25
+ D text, &block
26
+ end
27
+ end
28
+
29
+ def D19(text, &block)
30
+ if ruby_version == :v19
31
+ D text, &block
32
+ end
33
+ end
34
+
35
+ D "Modules" do
36
+ D "We can 'extend Insulation' in a non-insulated test" do
37
+ extend Insulation
38
+ T { answer() == :foo }
39
+
40
+ D "we can use Insulation in a sub-test" do
41
+ T { answer() == :foo }
42
+ end
43
+
44
+ D! "but we can't use Insulation in an insulated sub-test" do
45
+ E(NoMethodError) { answer() == :foo }
46
+ end
47
+ end
48
+
49
+ D "We can still use Insulation in a different (non-insulated) test" do
50
+ T { answer() == :foo }
51
+ end
52
+
53
+ D! "We CAN'T use Insulation in a different (insulated) test" do
54
+ E(NoMethodError) { answer() == :foo }
55
+ end
56
+
57
+ D! "If we 'extend Insulation' in an insulated test..." do
58
+ extend Insulation
59
+ T { answer() == :foo }
60
+ D "...we can use Insulation in a sub-test" do
61
+ T { answer() == :foo }
62
+ end
63
+ end
64
+ end # "Modules"
65
+
66
+ D "Modules (again)" do
67
+ E(NoMethodError) { answer() == :foo } # just checking...
68
+ D "[nesting]" do
69
+ D "[nesting]" do
70
+ D "A module inclusion in a deeply nested test..." do
71
+ extend Insulation
72
+ end
73
+ end
74
+ end
75
+ D "...can be used at an outer level" do
76
+ T { answer() == :foo }
77
+ end
78
+ D "(because there was no insulation anywhere)" do end
79
+ end
80
+
81
+
82
+ D "Methods" do
83
+ D "We can define a method (times2) even in a non-insulated test" do
84
+ def times2(x) x*2 end
85
+ T { times2(14) == 28 }
86
+ end
87
+
88
+ D "We can use 'times2' in a sibling test..." do
89
+ T { times2(-5) == -10 }
90
+ D "...and in a non-insulated sub-test" do
91
+ T { times2(916) == 1832 }
92
+ end
93
+ D! "...but we CAN'T can use 'times2' in an insulated sub-test" do
94
+ E(NoMethodError) { times2(916) == 1832 }
95
+ end
96
+ end
97
+
98
+ D "If we set up an insulated test..." do
99
+ D! "...here..." do
100
+ D "...and define a method (sum) ..." do
101
+ def sum(collection) collection.inject(0) { |acc, x| acc + x } end
102
+ end
103
+ D "...then we can use the method in a separate test" do
104
+ T { sum([1,4,2,-3]) == 4 }
105
+ end
106
+ end
107
+ D "...but we CAN'T use the method outside of the insulated environment" do
108
+ E(NoMethodError) { sum([10,9,8,7]) == 34 }
109
+ end
110
+ end
111
+ end # "Methods"
112
+
113
+ D "Methods (again)" do
114
+ D "We CAN'T reuse the times2 and sum in a different test" do
115
+ E(NoMethodError) { times2(-5) == -10 }
116
+ E(NoMethodError) { sum([5,100]) == 105 }
117
+ end
118
+ end
119
+
120
+ D "Methods (once more)" do
121
+ D "[nesting]" do
122
+ D "[nesting]" do
123
+ D "A method definition in a deeply nested test..." do
124
+ def empty_string?(str) str.strip.size == 0 end
125
+ end
126
+ end
127
+ end
128
+ D "...can be used at an outer level" do
129
+ T { empty_string? " \t\n " }
130
+ F { empty_string? " faf fsdf fd " }
131
+ end
132
+ D "(because there was no insulation anywhere)" do end
133
+ end
134
+
135
+ D "Instance variables" do
136
+ D "@x is defined in one test..." do
137
+ @x = 6
138
+ end
139
+ D "...and is accessible in another..." do
140
+ T { @x == 6 }
141
+ end
142
+ D! "...unless the test is insulated" do
143
+ F { @x == 6 }
144
+ D "We can reuse @x in here..." do
145
+ @x = -1
146
+ D "(sub-test)" do
147
+ T { @x == -1 }
148
+ end
149
+ end
150
+ end
151
+ D "...and it reverts to its previous value outside the insulated area" do
152
+ T { @x == 6 }
153
+ end
154
+ end
155
+
156
+ D "Instance variables (again) " do
157
+ D! "@y is defined in an insulated test..." do
158
+ @y = 10
159
+ D "...and is accessible in a non-insulated subtest" do
160
+ T { @y == 10 }
161
+ end
162
+ D! "...but is not accessible in an insulated subtest" do
163
+ F { @y == 10 }
164
+ end
165
+ end
166
+ D "...but is not accessible in a sibling test" do
167
+ F { @y == 10 }
168
+ end
169
+ end
170
+
171
+ D "An insulated test..." do
172
+ D.<< { @a = 32 }
173
+ D.< { @z = 99 }
174
+ D! "...does NOT see an instance variable defined in the setup blocks" do
175
+ F { @a == 32 }
176
+ F { @z == 99 }
177
+ end
178
+ end
179
+
180
+ # Given that all the above tests pass (in Whitestone and Dfect), here are my
181
+ # conclusions:
182
+ # * Class and constant definitions are globally accessible and are not affected
183
+ # by insulation.
184
+ # - This used to be tested differently in 1.8 and 1.9, but in 1.9.3 the
185
+ # difference appears to have vanished, so I removed the tests.
186
+ # * Methods definitions (whether direct or via 'extend Foo') are sealed by
187
+ # insulation. Nothing gets in or out.
188
+ # * The same is true for instance variables.
189
+ #
190
+ # The reason insulation is effective against methods and instance variables is
191
+ # that they rely on the value of _self_ to be resolved. An insulated
192
+ # environment introduces a new value of _self_. This is shown in the following
193
+ # (paraphrased) Whitestone code:
194
+ #
195
+ # def run_test(test)
196
+ # if test.insulated?
197
+ # Object.new.instance_eval(&test.block)
198
+ # else
199
+ # test.block.call
200
+ # end
201
+ # end
202
+
@@ -0,0 +1,616 @@
1
+
2
+ # Dfect's original test file, with Whitestone's extra assertions added (Eq, Mt, N).
3
+ #
4
+ # Some of the original tests have been commented out, with an explanation.
5
+ # These will probably be removed later on, but not before committing the reason
6
+ # for their removal.
7
+ #
8
+ # Tests that contain custom error messages have been removed because this
9
+ # facility has been removed from Whitestone.
10
+
11
+ D "Assertion classes" do
12
+ D 'T()' do
13
+ T { true }
14
+ T { !false }
15
+ T { !nil }
16
+
17
+ T { 0 } # zero is true in Ruby! :)
18
+ T { 1 }
19
+
20
+ # The following Dfect behaviour has been removed in Whitestone.
21
+ # I prefer assertions (of any kind) to return true or false.
22
+ # Comment kept here in case there's a good reason for the Dfect
23
+ # behaviour that I'm not currently aware of.
24
+ #
25
+ # D 'must return block value' do
26
+ # inner = rand()
27
+ # outer = T { inner }
28
+ #
29
+ # T { outer == inner }
30
+ # end
31
+ end
32
+
33
+ D 'T!()' do
34
+ T! { !true }
35
+ T! { false }
36
+ T! { nil }
37
+
38
+ # See comment above.
39
+ #
40
+ # D 'must return block value' do
41
+ # inner = nil
42
+ # outer = T! { inner }
43
+ #
44
+ # T { outer == inner }
45
+ # end
46
+ end
47
+
48
+ D 'T?()' do
49
+ T { T? { true } }
50
+ F { T? { false } }
51
+ F { T? { nil } }
52
+
53
+ # See above comment. This one passes anyway, but it's not behaviour I care
54
+ # to specify.
55
+ #
56
+ # D 'must not return block value' do
57
+ # inner = rand()
58
+ # outer = T? { inner }
59
+ #
60
+ # F { outer == inner }
61
+ # T { outer == true }
62
+ # end
63
+ end
64
+
65
+ D 'F?()' do
66
+ T { T? { true } }
67
+ F { T? { false } }
68
+ F { T? { nil } }
69
+
70
+ # See above comment.
71
+ #
72
+ # D 'must not return block value' do
73
+ # inner = rand()
74
+ # outer = F? { inner }
75
+ #
76
+ # F { outer == inner }
77
+ # T { outer == false }
78
+ # end
79
+ end
80
+
81
+ D 'Eq()' do
82
+ Eq 5, 5
83
+ Eq "foo", "foo"
84
+ Eq [1,2,3,:x], [1,2,3,:x]
85
+ Eq! "foo", 5
86
+ Eq! 5, "foo"
87
+ Eq! [1,2,3,:x], [1,2,3,:z]
88
+ T { Eq? 5, 5 }
89
+ F { Eq? 5, 6 }
90
+ end
91
+
92
+ D 'Mt, Mt!, Mt?' do
93
+ Mt "foo", /foo/
94
+ Mt /foo/, "fool" # Order is unimportant.
95
+ Mt "foo", /./
96
+ Mt! "foo", /egg/
97
+ T { Mt? "foo", /o+/ }
98
+ D "removes color codes before checking match" do
99
+ require 'col'
100
+ Mt Col["foo ", "bar"].fmt('rb,yb'), /foo bar/
101
+ Mt! Col["foo ", "bar"].fmt('rb,yb'), /foo bat/
102
+ end
103
+ end
104
+
105
+ D 'N, N!, N?' do
106
+ N nil
107
+ N { nil }
108
+ N! 0
109
+ N! { 0 }
110
+ N! false
111
+ N! { false }
112
+ T { N? { nil } }
113
+ F { N? { rand() } }
114
+ end
115
+
116
+ D 'Ko' do
117
+ Ko "foo", String
118
+ Ko "foo", Object
119
+ Ko! "foo", Numeric
120
+ Ko [1,2,3], Enumerable
121
+ E { Ko String, "foo" } # wrong order -- expect an error
122
+ end
123
+
124
+ D 'Ft' do
125
+ Ft Math::PI, 3.141592 # default tolerance 0.00001
126
+ Ft! Math::PI, 3.14
127
+ Ft Math::PI, 3.14, 0.1 # tolerance for this line is 0.1
128
+ Ft Math::PI, 3.14, 0.01
129
+ Ft Math::PI, 3.14, 0.001
130
+ Ft! Math::PI, 3.14, 0.0001
131
+ D 'test values of massively differing magnitude' do
132
+ a = 0.000000000837
133
+ b = 0.0000000004315 # a and b are _not_ "essentially" equal
134
+ c = 100.000000000837
135
+ d = 100.0000000004315 # c and d _are_ "essentially" equal
136
+ Ft! a, b
137
+ Ft! b, a
138
+ Ft c, d
139
+ Ft d, c
140
+ end
141
+ D 'integer values' do
142
+ Ft 4, 4
143
+ Ft 4.0, 4
144
+ Ft 4, 4.0
145
+ Ft -13, -13
146
+ Ft -13.0, -13
147
+ end
148
+ D 'zero' do
149
+ Ft 0, 0
150
+ Ft 0, 0.0
151
+ Ft 0.0, 0
152
+ Ft 0.0, 0.0
153
+ Ft 0.0, -1.1102230246251565e-16
154
+ Ft -1.1102230246251565e-16, 0.0
155
+ end
156
+ D 'numbers near zero' do
157
+ Ft 0, 0.00000000000124, 0.0000000001
158
+ Ft 0, 0.00000000000124, 0.00000000001
159
+ Ft 0, 0.00000000000124, 0.000000000001
160
+ Ft 0, 0.00000000000124, 0.0000000000001
161
+ # The next test fails but I don't know what we really should expect.
162
+ # Ft! 0, 0.00000000000124, 1e-25
163
+ end
164
+ D '(near) equal and negative' do
165
+ a = -2.0000051298352
166
+ b = -2.0000051298336
167
+ Ft a, b, 0.000000001
168
+ Ft b, a, 0.000000001
169
+ end
170
+ D 'tiny numbers' do
171
+ Ft 1.234567e-50, 1.234568e-50
172
+ Ft! 1.234567e-50, 1.234567e-51
173
+ end
174
+ D 'huge numbers' do
175
+ Ft 1.234567e50, 1.234568e50
176
+ Ft! 1.234567e50, 1.234567e51
177
+ end
178
+ end
179
+
180
+ D 'Id' do
181
+ Id 5, 5
182
+ Id (x = "foo"), x
183
+ Id! "foo", "foo"
184
+ T { Id? x, x }
185
+ a = [1,2,3]
186
+ b = a
187
+ Id a, b
188
+ Id a, a
189
+ Id b, b
190
+ Id! a, a.dup
191
+ end
192
+ end # Assertion methods
193
+
194
+ def foo
195
+ raise StandardError, "Error to help test E"
196
+ end
197
+
198
+ D "Exceptions: E, E!, E?" do
199
+ D 'E()' do
200
+ E { foo }
201
+ E(StandardError) { foo }
202
+ # There's no longer provisions for specifying an error message.
203
+ # E(SyntaxError, 'must raise SyntaxError') { raise SyntaxError }
204
+
205
+ D 'forbids block to not raise anything' do
206
+ F { E? {} }
207
+ end
208
+
209
+ # This seems wrong to me. The block will raise a SyntaxError. We can't
210
+ # ignore that; it has to be reported to the user. Therefore, it can't
211
+ # appear like that in a unit test.
212
+ #
213
+ # This reasoning can be called "Comment E" for reference below.
214
+ #
215
+ # D 'forbids block to raise something unexpected' do
216
+ # F { E?(ArgumentError) { raise SyntaxError } }
217
+ # end
218
+
219
+ D 'defaults to StandardError when no kinds specified' do
220
+ E { raise StandardError }
221
+ E { raise }
222
+ end
223
+
224
+ # See Comment E above.
225
+ #
226
+ # D 'does not default to StandardError when kinds are specified' do
227
+ # F { E?(SyntaxError) { raise } }
228
+ # end
229
+
230
+ D 'allows nested rescue' do
231
+ E ArgumentError do
232
+ begin
233
+ raise LoadError
234
+ rescue LoadError
235
+ end
236
+
237
+ raise rescue nil
238
+
239
+ raise ArgumentError
240
+ end
241
+ end
242
+ end
243
+
244
+ D 'E!()' do
245
+ # See Comment E above. Also, I'm not sure E! should actually be able to
246
+ # specify an Exception type. Surely the assertion is that it doesn't raise
247
+ # anything.
248
+ #
249
+ # E!(SyntaxError) { raise ArgumentError }
250
+
251
+ D 'allows block to not raise anything' do
252
+ E!() {}
253
+ E!(ArgumentError) {}
254
+ end
255
+
256
+ # See Comment E.
257
+ #
258
+ # D 'allows block to raise something unexpected' do
259
+ # T { not E?(ArgumentError) { raise SyntaxError } }
260
+ # end
261
+ #
262
+ # D 'defaults to StandardError when no kinds specified' do
263
+ # E! { raise LoadError }
264
+ # end
265
+ #
266
+ # D 'does not default to StandardError when kinds are specified' do
267
+ # T { not E?(SyntaxError) { raise } }
268
+ # end
269
+
270
+ end
271
+
272
+ D 'E?()' do
273
+ T E?(ArgumentError) { raise ArgumentError }
274
+ F E?(ArgumentError) { 1 + 1 }
275
+ # F E?(SyntaxError) { raise ArgumentError } Comment E
276
+ end
277
+ end # "Exceptions: E, E!, E?"
278
+
279
+ D "Catch: C, C!, C?" do
280
+ D 'C()' do
281
+ C(:foo) { throw :foo }
282
+ C(:foo) { throw :foo }
283
+
284
+ D 'forbids block to not throw anything' do
285
+ F { C?(:bar) {} }
286
+ end
287
+
288
+ D 'forbids block to throw something unexpected' do
289
+ F { C?(:bar) { throw :foo } }
290
+ end
291
+
292
+ D 'allows nested catch' do
293
+ C :foo do
294
+ catch :bar do
295
+ throw :bar
296
+ end
297
+
298
+ throw :foo
299
+ end
300
+ end
301
+
302
+ # Like other assertions, C returns true or false. Whatever value is thrown
303
+ # is lost. If I need to test that, I'm happy to do so more directly.
304
+ #
305
+ # D 'returns the value thrown along with symbol' do
306
+ # inner = rand()
307
+ # outer = C(:foo) { throw :foo, inner }
308
+ # T { outer == inner }
309
+ # end
310
+ end
311
+
312
+ D 'Whitestone.caught_value' do
313
+ def foo
314
+ throw :abc, 5
315
+ end
316
+ def bar
317
+ throw :abc
318
+ end
319
+ C(:abc) { foo }
320
+ Eq Whitestone.caught_value, 5
321
+ C(:abc) { bar }
322
+ Eq Whitestone.caught_value, nil
323
+ C?(:abc) { foo }
324
+ Eq Whitestone.caught_value, 5
325
+ C!(:def) { bar }
326
+ Eq Whitestone.caught_value, nil
327
+ C!(:def) { foo }
328
+ Eq Whitestone.caught_value, nil # Not updated in this instance.
329
+ end
330
+
331
+ D 'C!()' do
332
+ C!(:bar) { throw :foo }
333
+ C!(:bar) { throw :foo }
334
+
335
+ D 'allows block to not throw anything' do
336
+ C!(:bar) {}
337
+ end
338
+
339
+ D 'allows block to throw something unexpected' do
340
+ T { not C?(:bar) { throw :foo } }
341
+ end
342
+
343
+ D 'allows nested catch' do
344
+ C! :bar do
345
+ catch :moz do
346
+ throw :moz
347
+ end
348
+
349
+ throw :foo
350
+ end
351
+ end
352
+
353
+ # As per comment above, I have no interest in the value thrown.
354
+ #
355
+ # D 'does not return the value thrown along with symbol' do
356
+ # inner = rand()
357
+ # outer = C!(:foo) { throw :bar, inner }
358
+ #
359
+ # F { outer == inner }
360
+ # T { outer == nil }
361
+ # end
362
+ end
363
+
364
+ D 'C?()' do
365
+ T C?(:foo) { throw :foo }
366
+ F C?(:bar) { throw :foo }
367
+ end
368
+ end # "Catch: C, C!, C?"
369
+
370
+ D 'D' do
371
+ D 'D()' do
372
+ history = []
373
+
374
+ D .<< { history << :before_all }
375
+ D .< { history << :before_each }
376
+ D .> { history << :after_each }
377
+ D .>> { history << :after_all }
378
+
379
+ D 'first nesting' do
380
+ T { history.select {|x| x == :before_all }.length == 1 }
381
+ T { history.select {|x| x == :before_each }.length == 1 }
382
+ F { history.select {|x| x == :after_each }.length == 1 }
383
+ T { history.select {|x| x == :after_all }.length == 0 }
384
+ end
385
+
386
+ D 'second nesting' do
387
+ T { history.select {|x| x == :before_all }.length == 1 }
388
+ T { history.select {|x| x == :before_each }.length == 2 }
389
+ T { history.select {|x| x == :after_each }.length == 1 }
390
+ T { history.select {|x| x == :after_all }.length == 0 }
391
+ end
392
+
393
+ D 'third nesting' do
394
+ T { history.select {|x| x == :before_all }.length == 1 }
395
+ T { history.select {|x| x == :before_each }.length == 3 }
396
+ T { history.select {|x| x == :after_each }.length == 2 }
397
+ T { history.select {|x| x == :after_all }.length == 0 }
398
+ end
399
+
400
+ D 'fourth nesting' do
401
+ D .<< { history << :nested_before_all }
402
+ D .< { history << :nested_before_each }
403
+ D .> { history << :nested_after_each }
404
+ D .>> { history << :nested_after_all }
405
+
406
+ nested_before_each = 0
407
+
408
+ D .< do
409
+ # outer values remain the same for this nesting
410
+ T { history.select {|x| x == :before_all }.length == 1 }
411
+ T { history.select {|x| x == :before_each }.length == 4 }
412
+ T { history.select {|x| x == :after_each }.length == 3 }
413
+ T { history.select {|x| x == :after_all }.length == 0 }
414
+
415
+ nested_before_each += 1
416
+ T { history.select {|x| x == :nested_before_each }.length == nested_before_each }
417
+ end
418
+
419
+ D 'first double-nesting' do
420
+ T { history.select {|x| x == :nested_before_all }.length == 1 }
421
+ T { history.select {|x| x == :nested_before_each }.length == 1 }
422
+ F { history.select {|x| x == :nested_after_each }.length == 1 }
423
+ T { history.select {|x| x == :nested_after_all }.length == 0 }
424
+ end
425
+
426
+ D 'second double-nesting' do
427
+ T { history.select {|x| x == :nested_before_all }.length == 1 }
428
+ T { history.select {|x| x == :nested_before_each }.length == 2 }
429
+ T { history.select {|x| x == :nested_after_each }.length == 1 }
430
+ T { history.select {|x| x == :nested_after_all }.length == 0 }
431
+ end
432
+
433
+ D 'third double-nesting' do
434
+ T { history.select {|x| x == :nested_before_all }.length == 1 }
435
+ T { history.select {|x| x == :nested_before_each }.length == 3 }
436
+ T { history.select {|x| x == :nested_after_each }.length == 2 }
437
+ T { history.select {|x| x == :nested_after_all }.length == 0 }
438
+ end
439
+ end
440
+ end
441
+
442
+ D 'D.<() must allow inheritance checking when called without a block' do
443
+ F { D < Kernel }
444
+ F { D < Object }
445
+ F { D < Module }
446
+ T { D.class == Module }
447
+
448
+ c = Class.new { include D }
449
+ T { c < D }
450
+ end
451
+
452
+ # Whitestone doesn't use YAML output; this test is no longer relevant.
453
+ #
454
+ # D 'YAML must be able to serialize a class' do
455
+ # T { SyntaxError.to_yaml == "--- SyntaxError\n" }
456
+ # end
457
+
458
+ D! 'insulated root-level describe' do
459
+ @insulated = :insulated
460
+ non_closured = :non_closured
461
+ end
462
+
463
+ closured = :closured
464
+
465
+ D! 'another insulated root-level describe' do
466
+ # without insulation, instance variables
467
+ # from previous root-level describe
468
+ # environments will spill into this one
469
+ F { defined? @insulated }
470
+ F { @insulated == :insulated }
471
+
472
+ # however, this insulation must
473
+ # not prevent closure access to
474
+ # surrounding local variables
475
+ T { defined? closured }
476
+ T { closured == :closured }
477
+
478
+ # except local variables defined
479
+ # within another insulated environment
480
+ F { defined? non_closured }
481
+ E(NameError) { non_closured }
482
+
483
+ @insulated_again = :insulated_again
484
+
485
+ D 'non-insulated nested describe' do
486
+ D 'inherits instance variables' do
487
+ T { defined? @insulated_again }
488
+ T { @insulated_again == :insulated_again }
489
+ end
490
+
491
+ D 'inherits instance methods' do
492
+ E!(NoMethodError) { instance_level_helper_method }
493
+ T { instance_level_helper_method == :instance_level_helper_method }
494
+ end
495
+
496
+ D 'inherits class methods' do
497
+ E!(NoMethodError) { self.class_level_helper_method }
498
+ T { self.class_level_helper_method == :class_level_helper_method }
499
+
500
+ E!(NoMethodError) { class_level_helper_method }
501
+ T { class_level_helper_method == self.class_level_helper_method }
502
+ end
503
+
504
+ @non_insulated_from_nested = :non_insulated_from_nested
505
+ end
506
+
507
+ D! 'nested but explicitly insulated describe' do
508
+ D 'does not inherit instance variables' do
509
+ F { defined? @insulated_again }
510
+ F { @insulated_again == :insulated_again }
511
+ end
512
+
513
+ D 'does not inherit instance methods' do
514
+ E(NameError) { instance_level_helper_method }
515
+ end
516
+
517
+ D 'does not inherit class methods' do
518
+ E(NoMethodError) { self.class_level_helper_method }
519
+ E(NameError) { class_level_helper_method }
520
+ end
521
+
522
+ @non_insulated_from_nested = 123
523
+ end
524
+
525
+ D 'another non-insulated nested describe' do
526
+ T { defined? @non_insulated_from_nested }
527
+ T { @non_insulated_from_nested == :non_insulated_from_nested }
528
+ end
529
+
530
+ def instance_level_helper_method
531
+ :instance_level_helper_method
532
+ end
533
+
534
+ def self.class_level_helper_method
535
+ :class_level_helper_method
536
+ end
537
+ end
538
+
539
+ D 'yet another insulated root-level describe' do
540
+ F { defined? @insulated_again }
541
+ F { @insulated_again == :insulated_again }
542
+
543
+ F { defined? @non_insulated_from_nested }
544
+ F { @non_insulated_from_nested == :non_insulated_from_nested }
545
+ end
546
+ end # 'D'
547
+
548
+ D 'Sharing' do
549
+ S :knowledge do
550
+ @sharing_is_fun = :share_knowledge
551
+ end
552
+
553
+ S :money do
554
+ @sharing_is_fun = :share_money
555
+ end
556
+
557
+ D! 'share knowledge' do
558
+ F { defined? @sharing_is_fun }
559
+ S :knowledge
560
+ T { defined? @sharing_is_fun }
561
+ T { @sharing_is_fun == :share_knowledge }
562
+
563
+ F { S? :power }
564
+ S! :power do
565
+ @sharing_is_fun = :share_power
566
+ end
567
+ T { S? :power }
568
+ end
569
+
570
+ D! 'share money' do
571
+ F { defined? @sharing_is_fun }
572
+ S :money
573
+ T { defined? @sharing_is_fun }
574
+ T { @sharing_is_fun == :share_money }
575
+
576
+ S :power
577
+ T { defined? @sharing_is_fun }
578
+ T { @sharing_is_fun == :share_power }
579
+
580
+ D! 'share knowledge inside nested but explicitly insulated describe' do
581
+ F { defined? @sharing_is_fun }
582
+ S :knowledge
583
+ T { defined? @sharing_is_fun }
584
+ T { @sharing_is_fun == :share_knowledge }
585
+ end
586
+ end
587
+
588
+ D 're-sharing under a previously shared identifier' do
589
+ E ArgumentError do
590
+ S :knowledge do
591
+ @sharing_is_fun = :overwrite_previous_share
592
+ end
593
+ end
594
+
595
+ F { defined? @sharing_is_fun }
596
+ F { @sharing_is_fun == :overwrite_previous_share }
597
+ end
598
+
599
+ D 'injecting an unshared code block' do
600
+ E ArgumentError do
601
+ S :foobar
602
+ end
603
+ end
604
+ end # 'Sharing'
605
+
606
+ #E 'injecting shared block outside of a test' do
607
+ E {
608
+ # It's an error to inject a shared block outside of a test.
609
+ S :knowledge
610
+ }
611
+
612
+ # Cancelling this test because it prevents others in the directory from being run.
613
+ xD 'stoping #run' do
614
+ Whitestone.stop
615
+ raise 'this must not be reached!'
616
+ end