whitestone 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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