-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTESTS
175 lines (134 loc) · 4.87 KB
/
TESTS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
== TESTS
=== Defining tests
<%= method_api_docs 'D', 'The `D()` method' %> creates a new *test*, which is
analagous to the *describe* keyword in <<RSpec>> and also to the concept of a
"test case" in <<xUnit>>.
[source,ruby]
------------------------------------------------------------------------------
D "outer test" do
# assertions and logic here
D "inner test" do
# more assertions and logic here
end
end
------------------------------------------------------------------------------
A test may contain nested tests, as illustrated above.
=== Insulating tests
<%= method_api_docs 'D!', 'The `D!()` method' %> defines a new test that is
explicitly insulated from the tests that contain it and also from the
top-level Ruby environment.
Inside an insulated test, you are free to mix-in (using the *extend* keyword,
not the *include* keyword) any modules your test logic needs. You can also
define your own constants, methods, classes, and modules here.
NOTE: Root-level calls to the `D()` method are insulated by default.
.Insulated and uninsulated tests
%|example_test_run
D "a root-level test" do
@outside = 1
T { defined? @outside }
T { @outside == 1 }
D "an inner, non-insulated test" do
T { defined? @outside }
T { @outside == 1 }
end
D! "an inner, insulated test" do
F { defined? @outside }
F { @outside == 1 }
@inside = 2
T { defined? @inside }
T { @inside == 2 }
end
F { defined? @inside }
F { @inside == 2 }
end
=== Sharing tests
<%= method_api_docs 'S', 'The `S()` method' %> is a mechanism for sharing
code. It can be used in two ways:
1. When called with a block, it shares the given block (under a given
identifier) for injection into other tests.
2. When called without a block, it injects a previously shared block
(under a given identifier) into the environment where it is called.
<%= method_api_docs 'S!', 'The `S!()` method' %> is a combination of the two
uses of the `S()` method: it lets you simultaneously share a block of code
while injecting it into the environment where that method is called.
<%= method_api_docs 'S?', 'The `S?()` method' %> checks whether any code has
been shared under a given identifier.
.Sharing code between tests
%|example_test_run
S :knowledge do
I 'Knowledge is power!'
end
D 'Healer' do
S :knowledge
end
D 'Warrior' do
S! :strength do
I 'Strength is power!'
end
end
D 'Wizard' do
S :knowledge
S :strength
end
D 'King' do
T { S? :knowledge }
T { S? :strength }
F { S? :power }
I 'Power is power!'
end
=== Logging information
<%= method_api_docs 'I', 'The `I()` method' %> is a mechanism for inserting
arbitrary Ruby objects into the test execution report. You can think of this
method as being a way _to inform_ someone.
<%= method_api_docs 'I!', 'The `I!()` method' %> starts the interactive
debugger at the location where it is called. You can think of this
method as being a way _to investigate_ the state of your program.
.Logging information in the execution report
%|example_test_run
D 'Wizard' do
I 'Preparing spell to defeat mortal foes...'
end
D 'Magician' do
I 'Preparing rabbits to pull from hat...', rand(15)
end
D 'Calculator' do
I Math::PI, [1, 2, 3, ['a', 'b', 'c']], {:foo => 'bar!'}
end
=== Execution hooks
A *hook* is a scheduled point of entry into the test execution process. The
following *hook methods* allow you to register a block of code to execute
when a hook occurs:
[horizontal]
`D.<()` :: calls the given block _before each_ child test -- <%= method_api_docs '<' %>
`D.>()` :: calls the given block _after each_ child test -- <%= method_api_docs '>' %>
`D.<<()` :: calls the given block _before all_ child tests -- <%= method_api_docs '<<' %>
`D.>>()` :: calls the given block _after all_ child tests -- <%= method_api_docs '>>' %>
A hook method can be called multiple times. Each additional call schedules
more logic to be executed during the hook:
[source,ruby]
------------------------------------------------------------------------------
D .< { puts "do something" }
D .< { puts "do something more!" }
------------------------------------------------------------------------------
.Using hooks to perform before and after actions
%|example_test_run
D "outer test" do
D .< { I "(outer hook) before each" }
D .> { I "(outer hook) after each" }
D .<< { I "(outer hook) before all" }
D .>> { I "(outer hook) after all" }
D "inner test 1" do
D .< { I "(inner hook) before each" }
D .> { I "(inner hook) after each" }
D .<< { I "(inner hook) before all" }
D .>> { I "(inner hook) after all" }
D "inner test 1.1" do
I "hello world"
end
end
D "inner test 2" do
I "goodbye world"
end
D .< { I "(outer hook) before each, again" }
D .> { I "(outer hook) after each, again" }
end