oktest 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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +21 -0
- data/README.md +1856 -0
- data/Rakefile.rb +61 -0
- data/benchmark/Rakefile.rb +230 -0
- data/benchmark/run_all.rb +6 -0
- data/bin/oktest +3 -0
- data/lib/oktest.rb +2359 -0
- data/oktest.gemspec +45 -0
- data/test/assertion_test.rb +817 -0
- data/test/filter_test.rb +379 -0
- data/test/fixture_test.rb +205 -0
- data/test/generator_test.rb +123 -0
- data/test/helper_test.rb +542 -0
- data/test/initialize.rb +14 -0
- data/test/mainapp_test.rb +625 -0
- data/test/misc_test.rb +80 -0
- data/test/node_test.rb +669 -0
- data/test/reporter_test.rb +547 -0
- data/test/run_all.rb +13 -0
- data/test/runner_test.rb +544 -0
- data/test/tc.rb +115 -0
- data/test/util_test.rb +258 -0
- data/test/visitor_test.rb +292 -0
- metadata +105 -0
data/test/tc.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
## micro test case class
|
4
|
+
class TC
|
5
|
+
|
6
|
+
COUNTS = {:ok => 0, :fail => 0, :error => 0}
|
7
|
+
|
8
|
+
def self.report_result()
|
9
|
+
ok, fail, error = COUNTS[:ok], COUNTS[:fail], COUNTS[:error]
|
10
|
+
COUNTS.keys.each {|k| COUNTS[k] = 0 }
|
11
|
+
red = proc {|s| "\033[0;31m#{s}\033[0m" }
|
12
|
+
fail_s = "fail: #{fail}" ; fail_s = red.call(fail_s) if fail > 0
|
13
|
+
error_s = "error: #{error}" ; error_s = red.call(error_s) if error > 0
|
14
|
+
STDOUT.puts "## total: #{ok+fail+error} (ok: #{ok}, #{fail_s}, #{error_s})"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.describe(target, &b)
|
18
|
+
prev, @curr_target = @curr_target, target
|
19
|
+
yield
|
20
|
+
ensure
|
21
|
+
@curr_target = prev
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.curr_target()
|
25
|
+
@curr_target
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.it(spec, &b)
|
29
|
+
t = @curr_target
|
30
|
+
print "[#{self.name}#{t ? ' > ' : ''}#{t}] #{spec} ... " unless ENV['TC_QUIET']
|
31
|
+
obj = self.new
|
32
|
+
obj.setup()
|
33
|
+
begin
|
34
|
+
obj.instance_eval(&b)
|
35
|
+
rescue => exc
|
36
|
+
if exc.is_a?(AssertionFailed)
|
37
|
+
COUNTS[:fail] += 1; puts "FAILED!" unless ENV['TC_QUIET']
|
38
|
+
else
|
39
|
+
COUNTS[:error] += 1; puts "ERROR!" unless ENV['TC_QUIET']
|
40
|
+
end
|
41
|
+
puts " #{exc.class.name}: #{exc.message}"
|
42
|
+
exc.backtrace.each do |bt|
|
43
|
+
puts " #{bt}" if bt.index(__FILE__) == nil
|
44
|
+
end
|
45
|
+
else
|
46
|
+
COUNTS[:ok] += 1; puts "ok." unless ENV['TC_QUIET']
|
47
|
+
ensure
|
48
|
+
obj.teardown()
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def setup
|
53
|
+
end
|
54
|
+
|
55
|
+
def teardown
|
56
|
+
end
|
57
|
+
|
58
|
+
class AssertionFailed < StandardError
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert(cond, msg="assertion failed")
|
62
|
+
raise msg unless cond
|
63
|
+
end
|
64
|
+
|
65
|
+
def assert_eq(actual, expected)
|
66
|
+
return if actual == expected
|
67
|
+
multiline_p = actual.is_a?(String) && actual =~ /\n/ \
|
68
|
+
&& expected.is_a?(String) && expected =~ /\n/
|
69
|
+
errmsg = (multiline_p \
|
70
|
+
? "$<actual> == $<expected> : failed.\n" +
|
71
|
+
" $<actual>: <<END\n#{actual}END\n" +
|
72
|
+
" $<expected>: <<END\n#{expected}END"
|
73
|
+
: "$<actual> == $<expected> : failed.\n" +
|
74
|
+
" $<actual>: #{actual.inspect}\n" +
|
75
|
+
" $<expected>: #{expected.inspect}")
|
76
|
+
raise AssertionFailed, errmsg
|
77
|
+
end
|
78
|
+
|
79
|
+
def assert_exc(errcls, errmsg=nil, &b)
|
80
|
+
begin
|
81
|
+
yield
|
82
|
+
rescue NoMemoryError, SystemExit, SyntaxError, SignalException
|
83
|
+
raise
|
84
|
+
rescue Exception => exc
|
85
|
+
exc.class == errcls or
|
86
|
+
raise AssertionFailed, "#{errcls} should be raised but got #{exc.inspect}"
|
87
|
+
errmsg.nil? || errmsg === exc.message or
|
88
|
+
raise AssertionFailed, ("invalid error message.\n"\
|
89
|
+
" $<actual>: #{exc.message.inspect}\n"\
|
90
|
+
" $<expected>: #{errmsg.inspect}")
|
91
|
+
return exc
|
92
|
+
else
|
93
|
+
raise AssertionFailed, "#{errcls.name} should be raised but not."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def capture(input="", tty: true, &b)
|
98
|
+
require 'stringio' unless defined?(StringIO)
|
99
|
+
stdin, stdout, stderr = $stdin, $stdout, $stderr
|
100
|
+
$stdin = sin = StringIO.new(input)
|
101
|
+
$stdout = sout = StringIO.new
|
102
|
+
$stderr = serr = StringIO.new
|
103
|
+
def sin.tty? ; true; end if tty
|
104
|
+
def sout.tty?; true; end if tty
|
105
|
+
def sout.tty?; true; end if tty
|
106
|
+
yield
|
107
|
+
return sout.string, serr.string
|
108
|
+
ensure
|
109
|
+
$stdin, $stdout, $stderr = stdin, stdout, stderr
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
at_exit { TC.report_result() }
|
data/test/util_test.rb
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 1.0.0 $
|
5
|
+
### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
require_relative './initialize'
|
10
|
+
|
11
|
+
|
12
|
+
class Util_TC < TC
|
13
|
+
include Oktest::Util
|
14
|
+
|
15
|
+
describe Oktest::Util do
|
16
|
+
|
17
|
+
describe '.file_line()' do
|
18
|
+
it "[!4z65g] returns nil if file not exist or not a file." do
|
19
|
+
assert_eq Oktest::Util.file_line("not-exist-file", 1), nil
|
20
|
+
assert_eq Oktest::Util.file_line(".", 1), nil
|
21
|
+
end
|
22
|
+
it "[!162e1] returns line string." do
|
23
|
+
lineno = __LINE__ + 2
|
24
|
+
_ = <<END
|
25
|
+
U6XYR-SH08J
|
26
|
+
END
|
27
|
+
assert_eq Oktest::Util.file_line(__FILE__, lineno), "U6XYR-SH08J\n"
|
28
|
+
end
|
29
|
+
it "[!4a2ji] caches recent file content for performance reason." do
|
30
|
+
_ = Oktest::Util.file_line(__FILE__, 1)
|
31
|
+
c = Oktest::Util.instance_variable_get('@__cache')
|
32
|
+
assert c.is_a?(Array), "array object expected."
|
33
|
+
assert_eq c[0], __FILE__
|
34
|
+
assert_eq c[1][0], "# -*- coding: utf-8 -*-\n"
|
35
|
+
assert_eq c[1][11], "class Util_TC < TC\n"
|
36
|
+
#
|
37
|
+
data1 = c[1]
|
38
|
+
_ = Oktest::Util.file_line(__FILE__, 1)
|
39
|
+
c2 = Oktest::Util.instance_variable_get('@__cache')
|
40
|
+
assert c2[1].equal?(data1), "cache object changed unexpectedly."
|
41
|
+
end
|
42
|
+
it "[!wtrl5] recreates cache data if other file requested." do
|
43
|
+
_ = Oktest::Util.file_line(__FILE__, 1)
|
44
|
+
c = Oktest::Util.instance_variable_get('@__cache')
|
45
|
+
data1 = c[1]
|
46
|
+
#
|
47
|
+
otherfile = File.join(File.dirname(__FILE__), "initialize.rb")
|
48
|
+
_ = Oktest::Util.file_line(otherfile, 1)
|
49
|
+
c3 = Oktest::Util.instance_variable_get('@__cache')
|
50
|
+
assert_eq c3[0], otherfile
|
51
|
+
assert ! c3[1].equal?(data1), "cache object should be recreated, but not."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '.required_param_names_of_block()' do
|
56
|
+
it "[!a9n46] returns nil if argument is nil." do
|
57
|
+
assert_eq required_param_names_of_block(nil), nil
|
58
|
+
end
|
59
|
+
it "[!7m81p] returns empty array if block has no parameters." do
|
60
|
+
pr = proc { nil }
|
61
|
+
assert_eq required_param_names_of_block(pr), []
|
62
|
+
end
|
63
|
+
it "[!n3g63] returns parameter names of block." do
|
64
|
+
pr = proc {|x, y, z| nil }
|
65
|
+
assert_eq required_param_names_of_block(pr), [:x, :y, :z]
|
66
|
+
end
|
67
|
+
it "[!d5kym] collects only normal parameter names." do
|
68
|
+
pr = proc {|x, y, z=1, *rest, a: 1, b: 2, &blk| nil }
|
69
|
+
assert_eq required_param_names_of_block(pr), [:x, :y]
|
70
|
+
pr = proc {|a: 1, b: 2, &blk| nil }
|
71
|
+
assert_eq required_param_names_of_block(pr), []
|
72
|
+
pr = proc {|*rest, &blk| nil }
|
73
|
+
assert_eq required_param_names_of_block(pr), []
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '.strfold()' do
|
78
|
+
it "[!wb7m8] returns string as it is if string is not long." do
|
79
|
+
s = "*" * 79
|
80
|
+
assert_eq strfold(s, 80), s
|
81
|
+
s = "*" * 80
|
82
|
+
assert_eq strfold(s, 80), s
|
83
|
+
end
|
84
|
+
it "[!a2igb] shorten string if it is enough long." do
|
85
|
+
expected = "*" * 77 + "..."
|
86
|
+
s = "*" * 81
|
87
|
+
assert_eq strfold(s, 80), expected
|
88
|
+
end
|
89
|
+
it "[!0gjye] supports non-ascii characters." do
|
90
|
+
expected = "あ" * 38 + "..."
|
91
|
+
s = "あ" * 41
|
92
|
+
assert_eq strfold(s, 80), expected
|
93
|
+
#
|
94
|
+
expected = "x" + "あ" * 37 + "..."
|
95
|
+
s = "x" + "あ" * 40
|
96
|
+
assert_eq strfold(s, 80), expected
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '.hhmmss()' do
|
101
|
+
it "[!shyl1] converts 400953.444 into '111:22:33.4'." do
|
102
|
+
x = 111*60*60 + 22*60 + 33.444
|
103
|
+
assert_eq x, 400953.444
|
104
|
+
assert_eq hhmmss(x), "111:22:33.4"
|
105
|
+
end
|
106
|
+
it "[!vyi2v] converts 5025.678 into '1:23:45.7'." do
|
107
|
+
x = 1*60*60 + 23*60 + 45.678
|
108
|
+
assert_eq x, 5025.678
|
109
|
+
assert_eq hhmmss(x), "1:23:45.7"
|
110
|
+
end
|
111
|
+
it "[!pm4xf] converts 754.888 into '12:34.9'." do
|
112
|
+
x = 12*60 + 34.888
|
113
|
+
assert_eq x, 754.888
|
114
|
+
assert_eq hhmmss(x), "12:34.9"
|
115
|
+
end
|
116
|
+
it "[!lwewr] converts 83.444 into '1:23.4'." do
|
117
|
+
x = 1*60 + 23.444
|
118
|
+
assert_eq x, 83.444
|
119
|
+
assert_eq hhmmss(x), "1:23.4"
|
120
|
+
end
|
121
|
+
it "[!ijx52] converts 56.8888 into '56.9'." do
|
122
|
+
x = 56.8888
|
123
|
+
assert_eq hhmmss(x), "56.9"
|
124
|
+
end
|
125
|
+
it "[!2kra2] converts 9.777 into '9.78'." do
|
126
|
+
x = 9.777
|
127
|
+
assert_eq hhmmss(x), "9.78"
|
128
|
+
end
|
129
|
+
it "[!4aomb] converts 0.7777 into '0.778'." do
|
130
|
+
x = 0.7777
|
131
|
+
assert_eq hhmmss(x), "0.778"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '.hhmmss()' do
|
136
|
+
it "[!wf4ns] calculates unified diff from two text strings." do
|
137
|
+
s1 = <<'END'
|
138
|
+
Haruhi
|
139
|
+
Mikuru
|
140
|
+
Yuki
|
141
|
+
END
|
142
|
+
s2 = <<'END'
|
143
|
+
Haruhi
|
144
|
+
Michiru
|
145
|
+
Yuki
|
146
|
+
END
|
147
|
+
expected = <<'END'
|
148
|
+
--- old
|
149
|
+
+++ new
|
150
|
+
@@ -1,4 +1,4 @@
|
151
|
+
Haruhi
|
152
|
+
-Mikuru
|
153
|
+
+Michiru
|
154
|
+
Yuki
|
155
|
+
END
|
156
|
+
diff = Oktest::Util.unified_diff(s1, s2)
|
157
|
+
assert_eq diff, expected
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '.unified_diff()' do
|
162
|
+
it "[!rnx4f] checks whether text string ends with newline char." do
|
163
|
+
s1 = <<'END'
|
164
|
+
Haruhi
|
165
|
+
Mikuru
|
166
|
+
Yuki
|
167
|
+
END
|
168
|
+
s2 = s1
|
169
|
+
#
|
170
|
+
expected1 = <<'END'
|
171
|
+
--- old
|
172
|
+
+++ new
|
173
|
+
@@ -1,4 +1,4 @@
|
174
|
+
Haruhi
|
175
|
+
Mikuru
|
176
|
+
-Yuki\ No newline at end of string
|
177
|
+
+Yuki
|
178
|
+
END
|
179
|
+
diff = Oktest::Util.unified_diff(s1.chomp, s2)
|
180
|
+
assert_eq diff, expected1
|
181
|
+
#
|
182
|
+
expected2 = <<'END'
|
183
|
+
--- old
|
184
|
+
+++ new
|
185
|
+
@@ -1,4 +1,4 @@
|
186
|
+
Haruhi
|
187
|
+
Mikuru
|
188
|
+
-Yuki
|
189
|
+
+Yuki\ No newline at end of string
|
190
|
+
END
|
191
|
+
diff = Oktest::Util.unified_diff(s1, s2.chomp)
|
192
|
+
assert_eq diff, expected2
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '.diff_unified()' do
|
197
|
+
it "[!ulyq5] returns unified diff string of two text strings." do
|
198
|
+
s1 = <<'END'
|
199
|
+
Haruhi
|
200
|
+
Mikuru
|
201
|
+
Yuki
|
202
|
+
END
|
203
|
+
s2 = <<'END'
|
204
|
+
Haruhi
|
205
|
+
Michiru
|
206
|
+
Yuki
|
207
|
+
END
|
208
|
+
expected = <<'END'
|
209
|
+
--- old
|
210
|
+
+++ new
|
211
|
+
@@ -1,3 +1,3 @@
|
212
|
+
Haruhi
|
213
|
+
-Mikuru
|
214
|
+
+Michiru
|
215
|
+
Yuki
|
216
|
+
END
|
217
|
+
diff = Oktest::Util.diff_unified(s1, s2)
|
218
|
+
assert_eq diff, expected
|
219
|
+
end
|
220
|
+
it "[!6tgum] detects whether char at end of file is newline or not." do
|
221
|
+
s1 = <<'END'
|
222
|
+
Haruhi
|
223
|
+
Mikuru
|
224
|
+
Yuki
|
225
|
+
END
|
226
|
+
s2 = s1
|
227
|
+
#
|
228
|
+
expected1 = <<'END'
|
229
|
+
--- old
|
230
|
+
+++ new
|
231
|
+
@@ -1,3 +1,3 @@
|
232
|
+
Haruhi
|
233
|
+
Mikuru
|
234
|
+
-Yuki
|
235
|
+
|
236
|
+
+Yuki
|
237
|
+
END
|
238
|
+
diff = Oktest::Util.diff_unified(s1.chomp, s2)
|
239
|
+
assert_eq diff, expected1
|
240
|
+
#
|
241
|
+
expected2 = <<'END'
|
242
|
+
--- old
|
243
|
+
+++ new
|
244
|
+
@@ -1,3 +1,3 @@
|
245
|
+
Haruhi
|
246
|
+
Mikuru
|
247
|
+
-Yuki
|
248
|
+
+Yuki
|
249
|
+
|
250
|
+
END
|
251
|
+
diff = Oktest::Util.diff_unified(s1, s2.chomp)
|
252
|
+
assert_eq diff, expected2
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 1.0.0 $
|
5
|
+
### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
require_relative './initialize'
|
10
|
+
|
11
|
+
|
12
|
+
class Visitor_TC < TC
|
13
|
+
|
14
|
+
class DummyVisitor0 < Oktest::Visitor
|
15
|
+
def initialize
|
16
|
+
@log = []
|
17
|
+
end
|
18
|
+
attr_reader :log
|
19
|
+
def visit_scope(spec, depth, parent)
|
20
|
+
indent = depth >= 0 ? " " * depth : ""
|
21
|
+
@log << "#{indent}scope: #{spec.filename} {\n"
|
22
|
+
super
|
23
|
+
@log << "#{indent}}\n"
|
24
|
+
end
|
25
|
+
def visit_topic(topic, depth, parent)
|
26
|
+
indent = depth >= 0 ? " " * depth : ""
|
27
|
+
@log << "#{indent}topic: #{topic.target} {\n"
|
28
|
+
super
|
29
|
+
@log << "#{indent}}\n"
|
30
|
+
end
|
31
|
+
def visit_spec(spec, depth, parent)
|
32
|
+
indent = depth >= 0 ? " " * depth : ""
|
33
|
+
@log << "#{indent}spec: #{spec.desc} {\n"
|
34
|
+
super
|
35
|
+
@log << "#{indent}}\n"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def prepare()
|
40
|
+
Oktest.scope do
|
41
|
+
topic 'Example1' do
|
42
|
+
topic 'sample1-1' do
|
43
|
+
spec("1+1 should be 2") { ok {1+1} == 2 }
|
44
|
+
spec("1-1 should be 0") { ok {1-1} == 0 }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup
|
51
|
+
end
|
52
|
+
|
53
|
+
def teardown
|
54
|
+
Oktest::THE_GLOBAL_SCOPE.clear_children()
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#visit_spec()' do
|
58
|
+
it "[!9f7i9] do something on spec." do
|
59
|
+
expected = <<'END'
|
60
|
+
spec: sample {
|
61
|
+
}
|
62
|
+
END
|
63
|
+
sp = Oktest::SpecLeaf.new(nil, "sample")
|
64
|
+
visitor = DummyVisitor0.new
|
65
|
+
visitor.visit_spec(sp, 0, nil)
|
66
|
+
assert_eq visitor.log.join(), expected
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#visit_topic()' do
|
71
|
+
it "[!mu3fn] visits each child of topic." do
|
72
|
+
expected = <<'END'
|
73
|
+
topic: example {
|
74
|
+
spec: sample {
|
75
|
+
}
|
76
|
+
}
|
77
|
+
END
|
78
|
+
to = Oktest::TopicNode.new(nil, "example")
|
79
|
+
sp = Oktest::SpecLeaf.new(to, "sample")
|
80
|
+
visitor = DummyVisitor0.new
|
81
|
+
visitor.visit_topic(to, 0, nil)
|
82
|
+
assert_eq visitor.log.join(), expected
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#visit_scope()' do
|
87
|
+
it "[!hebhz] visits each child scope." do
|
88
|
+
expected = <<'END'
|
89
|
+
scope: file.rb {
|
90
|
+
topic: example {
|
91
|
+
}
|
92
|
+
spec: sample {
|
93
|
+
}
|
94
|
+
}
|
95
|
+
END
|
96
|
+
sc = Oktest::ScopeNode.new(nil, "file.rb")
|
97
|
+
to = Oktest::TopicNode.new(sc, "example")
|
98
|
+
sp = Oktest::SpecLeaf.new(sc, "sample")
|
99
|
+
visitor = DummyVisitor0.new
|
100
|
+
visitor.visit_scope(sc, 0, nil)
|
101
|
+
assert_eq visitor.log.join(), expected
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#start()' do
|
106
|
+
it "[!8h8qf] start visiting tree." do
|
107
|
+
expected = <<'END'
|
108
|
+
scope: test/visitor_test.rb {
|
109
|
+
topic: Example1 {
|
110
|
+
topic: sample1-1 {
|
111
|
+
spec: 1+1 should be 2 {
|
112
|
+
}
|
113
|
+
spec: 1-1 should be 0 {
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
END
|
119
|
+
prepare()
|
120
|
+
visitor = DummyVisitor0.new
|
121
|
+
visitor.start()
|
122
|
+
assert_eq visitor.log.join(), expected
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
class Traverser_TC < TC
|
130
|
+
|
131
|
+
class MyTraverser < Oktest::Traverser
|
132
|
+
def on_scope(filename, tag, depth)
|
133
|
+
print " " * depth if depth >= 0
|
134
|
+
print "* scope: #{filename}"
|
135
|
+
print " (tag: #{tag})" if tag
|
136
|
+
print "\n"
|
137
|
+
yield
|
138
|
+
end
|
139
|
+
def on_topic(target, tag, depth)
|
140
|
+
print " " * depth
|
141
|
+
print "+ topic: #{target}"
|
142
|
+
print " (tag: #{tag})" if tag
|
143
|
+
print "\n"
|
144
|
+
yield
|
145
|
+
end
|
146
|
+
def on_case(desc, tag, depth)
|
147
|
+
print " " * depth
|
148
|
+
print "- case: #{desc}"
|
149
|
+
print " (tag: #{tag})" if tag
|
150
|
+
print "\n"
|
151
|
+
yield
|
152
|
+
end
|
153
|
+
def on_spec(desc, tag, depth)
|
154
|
+
print " " * depth
|
155
|
+
print "- spec: #{desc}"
|
156
|
+
print " (tag: #{tag})" if tag
|
157
|
+
print "\n"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def prepare()
|
162
|
+
Oktest.scope do
|
163
|
+
topic 'Example' do
|
164
|
+
topic Integer, tag: 'cls' do
|
165
|
+
spec "1+1 should be 2." do ok {1+1} == 2 end
|
166
|
+
spec "1-1 should be 0." do ok {1-1} == 0 end
|
167
|
+
case_when 'negative...' do
|
168
|
+
spec "abs() returns sign-reversed value." do ok {-3.abs()} == 3 end
|
169
|
+
end
|
170
|
+
case_else do
|
171
|
+
spec "abs() returns positive value." do ok {4.abs()} == 4 end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
topic Float, tag: 'cls' do
|
175
|
+
spec "1*1 should be 1.", tag: 'err' do ok {1*1} == 2 end # fail
|
176
|
+
spec "1/1 should be 1.", tag: 'err' do ok {1/0} == 1 end # error
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def teardown()
|
183
|
+
Oktest::THE_GLOBAL_SCOPE.clear_children()
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
describe '#start()' do
|
188
|
+
it "[!5zonp] visits topics and specs and calls callbacks." do
|
189
|
+
expected = <<'END'
|
190
|
+
* scope: test/visitor_test.rb
|
191
|
+
+ topic: Example
|
192
|
+
+ topic: Integer (tag: cls)
|
193
|
+
- spec: 1+1 should be 2.
|
194
|
+
- spec: 1-1 should be 0.
|
195
|
+
- case: When negative...
|
196
|
+
- spec: abs() returns sign-reversed value.
|
197
|
+
- case: Else
|
198
|
+
- spec: abs() returns positive value.
|
199
|
+
+ topic: Float (tag: cls)
|
200
|
+
- spec: 1*1 should be 1. (tag: err)
|
201
|
+
- spec: 1/1 should be 1. (tag: err)
|
202
|
+
END
|
203
|
+
prepare()
|
204
|
+
sout, serr = capture { MyTraverser.new.start() }
|
205
|
+
assert_eq sout, expected
|
206
|
+
assert_eq serr, ""
|
207
|
+
end
|
208
|
+
it "[!gkopz] doesn't change Oktest::THE_GLOBAL_SCOPE." do
|
209
|
+
prepare()
|
210
|
+
n = Oktest::THE_GLOBAL_SCOPE.each_child.to_a.length
|
211
|
+
sout, serr = capture do
|
212
|
+
MyTraverser.new.start()
|
213
|
+
end
|
214
|
+
assert_eq Oktest::THE_GLOBAL_SCOPE.each_child.to_a.length, n
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe '#visit_scope()' do
|
219
|
+
it "[!ledj3] calls on_scope() callback on scope." do
|
220
|
+
expected = <<'END'
|
221
|
+
* scope: test/visitor_test.rb
|
222
|
+
* scope: test/visitor_test.rb
|
223
|
+
END
|
224
|
+
Oktest.scope do
|
225
|
+
end
|
226
|
+
Oktest.scope do
|
227
|
+
end
|
228
|
+
sout, serr = capture { MyTraverser.new.start() }
|
229
|
+
assert_eq sout, expected
|
230
|
+
assert_eq serr, ""
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe '#visit_topic()' do
|
235
|
+
it "[!x8r9w] calls on_topic() callback on topic." do
|
236
|
+
expected = <<'END'
|
237
|
+
* scope: test/visitor_test.rb
|
238
|
+
+ topic: Parent
|
239
|
+
+ topic: Child
|
240
|
+
END
|
241
|
+
Oktest.scope do
|
242
|
+
topic 'Parent' do
|
243
|
+
topic 'Child' do
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
sout, serr = capture { MyTraverser.new.start() }
|
248
|
+
assert_eq sout, expected
|
249
|
+
assert_eq serr, ""
|
250
|
+
end
|
251
|
+
it "[!qh0q3] calls on_case() callback on case_when or case_else." do
|
252
|
+
expected = <<'END'
|
253
|
+
* scope: test/visitor_test.rb
|
254
|
+
+ topic: Parent
|
255
|
+
- case: When some condition
|
256
|
+
- case: Else
|
257
|
+
END
|
258
|
+
Oktest.scope do
|
259
|
+
topic 'Parent' do
|
260
|
+
case_when 'some condition' do
|
261
|
+
end
|
262
|
+
case_else do
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
sout, serr = capture { MyTraverser.new.start() }
|
267
|
+
assert_eq sout, expected
|
268
|
+
assert_eq serr, ""
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe '#visit_spec()' do
|
273
|
+
it "[!41uyj] calls on_spec() callback." do
|
274
|
+
expected = <<'END'
|
275
|
+
* scope: test/visitor_test.rb
|
276
|
+
+ topic: Example
|
277
|
+
- spec: sample #1
|
278
|
+
- spec: sample #2
|
279
|
+
END
|
280
|
+
Oktest.scope do
|
281
|
+
topic 'Example' do
|
282
|
+
spec "sample #1" do ok {1+1} == 2 end
|
283
|
+
spec "sample #2" do ok {1-1} == 0 end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
sout, serr = capture { MyTraverser.new.start() }
|
287
|
+
assert_eq sout, expected
|
288
|
+
assert_eq serr, ""
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|