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.
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/LICENSE +16 -0
- data/README.txt +78 -0
- data/Rakefile +1 -0
- data/bin/whitestone +263 -0
- data/doc/README-snippets.rdoc +58 -0
- data/doc/whitestone.markdown +806 -0
- data/etc/aliases +5 -0
- data/etc/examples/example_1.rb +51 -0
- data/etc/examples/example_2.rb +51 -0
- data/etc/extra_tests/basic.rb +56 -0
- data/etc/extra_tests/error_should_not_also_fail.rb +17 -0
- data/etc/extra_tests/output_examples.rb +108 -0
- data/etc/extra_tests/output_examples_code.rb +38 -0
- data/etc/extra_tests/raise.rb +4 -0
- data/etc/extra_tests/realistic_example.rb +94 -0
- data/etc/extra_tests/specification_error.rb +8 -0
- data/etc/extra_tests/stop.rb +16 -0
- data/etc/extra_tests/terminate_suite.rb +56 -0
- data/etc/run-output-examples +1 -0
- data/etc/run-unit-tests +1 -0
- data/etc/ws +1 -0
- data/lib/whitestone.rb +710 -0
- data/lib/whitestone/assertion_classes.rb +418 -0
- data/lib/whitestone/auto.rb +20 -0
- data/lib/whitestone/custom_assertions.rb +252 -0
- data/lib/whitestone/include.rb +14 -0
- data/lib/whitestone/output.rb +335 -0
- data/lib/whitestone/support.rb +29 -0
- data/lib/whitestone/version.rb +3 -0
- data/test/_setup.rb +5 -0
- data/test/custom_assertions.rb +120 -0
- data/test/insulation.rb +202 -0
- data/test/whitestone_test.rb +616 -0
- data/whitestone.gemspec +31 -0
- metadata +125 -0
data/test/insulation.rb
ADDED
@@ -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
|