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.
data/test/run_all.rb ADDED
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ #Dir.chdir File.dirname(__FILE__) do
4
+ # Dir.glob("**/*_test.rb") do |x|
5
+ # require_relative "./#{x}"
6
+ # end
7
+ #end
8
+
9
+ Dir.glob(File.join(File.dirname(__FILE__), '**/*_test.rb')).each do |x|
10
+ #require x
11
+ #require File.absolute_path(x)
12
+ load x
13
+ end
@@ -0,0 +1,544 @@
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 Runner_TC < TC
13
+
14
+ class DummyReporter < Oktest::Reporter
15
+ def enter_all(runner); end
16
+ def exit_all(runner); end
17
+ def enter_scope(scope)
18
+ puts "file: #{scope.filename.inspect}"
19
+ end
20
+ def exit_scope(scope)
21
+ puts "/file"
22
+ end
23
+ def enter_topic(topic, depth)
24
+ puts "#{' '*(depth-1)}topic: #{topic.target.inspect}"
25
+ end
26
+ def exit_topic(topic, depth)
27
+ puts "#{' '*(depth-1)}/topic"
28
+ end
29
+ def enter_spec(spec, depth)
30
+ puts "#{' '*(depth-1)}spec: #{spec.desc.inspect}"
31
+ end
32
+ def exit_spec(spec, depth, status, error, parent)
33
+ if error
34
+ if status == :FAIL
35
+ puts "#{' '*(depth-1)}/spec: status=#{status.inspect}, error=#<ASSERTION: #{error.message}>"
36
+ else
37
+ puts "#{' '*(depth-1)}/spec: status=#{status.inspect}, error=#{error.inspect}"
38
+ end
39
+ else
40
+ puts "#{' '*(depth-1)}/spec: status=#{status.inspect}"
41
+ end
42
+ end
43
+ #
44
+ def counts; {}; end
45
+ end
46
+
47
+ describe "#start()" do
48
+ build_topics = proc {
49
+ Oktest.scope do
50
+ topic "Parent" do
51
+ topic "Child1" do
52
+ spec "1+1 should be 2" do
53
+ ok {1+1} == 2
54
+ end
55
+ end
56
+ end
57
+ end
58
+ }
59
+ it "[!xrisl] runs topics and specs." do
60
+ sout, serr = capture do
61
+ build_topics.call
62
+ Oktest::Runner.new(DummyReporter.new).start()
63
+ end
64
+ expected = <<'END'
65
+ file: "test/runner_test.rb"
66
+ topic: "Parent"
67
+ topic: "Child1"
68
+ spec: "1+1 should be 2"
69
+ /spec: status=:PASS
70
+ /topic
71
+ /topic
72
+ /file
73
+ END
74
+ assert_eq sout, expected
75
+ assert_eq serr, ""
76
+ end
77
+ it "[!dth2c] clears toplvel scope list." do
78
+ assert_eq Oktest::THE_GLOBAL_SCOPE.has_child?, false
79
+ sout, serr = capture do
80
+ build_topics.call
81
+ assert_eq Oktest::THE_GLOBAL_SCOPE.has_child?, true
82
+ Oktest::Runner.new(DummyReporter.new).start()
83
+ end
84
+ assert_eq Oktest::THE_GLOBAL_SCOPE.has_child?, false
85
+ end
86
+ end
87
+
88
+ describe "#visit_spec()" do
89
+ it "[!yd24o] runs spec body, catching assertions or exceptions." do
90
+ Oktest.scope do
91
+ topic "Parent" do
92
+ topic "Child" do
93
+ spec("spec#1") { ok {1+1} == 2 } # pass
94
+ spec("spec#2") { ok {1+1} == 1 } # fail
95
+ spec("spec#3") { "".null? } # error
96
+ spec("spec#4") { skip_when(true, "REASON") } # skip
97
+ spec("spec#5") { TODO(); ok {1+1} == 1 } # todo (fail, so passed)
98
+ spec("spec#6") { TODO(); ok {1+1} == 2 } # todo (pass, but failed)
99
+ spec("spec#7") # todo
100
+ end
101
+ end
102
+ end
103
+ sout, serr = capture do
104
+ runner = Oktest::Runner.new(DummyReporter.new).start()
105
+ end
106
+ expected = <<'END'
107
+ file: "test/runner_test.rb"
108
+ topic: "Parent"
109
+ topic: "Child"
110
+ spec: "spec#1"
111
+ /spec: status=:PASS
112
+ spec: "spec#2"
113
+ /spec: status=:FAIL, error=#<ASSERTION: $<actual> == $<expected>: failed.
114
+ $<actual>: 2
115
+ $<expected>: 1>
116
+ spec: "spec#3"
117
+ /spec: status=:ERROR, error=#<NoMethodError: undefined method `null?' for "":String>
118
+ spec: "spec#4"
119
+ /spec: status=:SKIP, error=#<Oktest::SkipException: REASON>
120
+ spec: "spec#5"
121
+ /spec: status=:TODO, error=#<Oktest::TodoException: not implemented yet>
122
+ spec: "spec#6"
123
+ /spec: status=:FAIL, error=#<ASSERTION: spec should be failed (because not implemented yet), but passed unexpectedly.>
124
+ spec: "spec#7"
125
+ /spec: status=:TODO, error=#<Oktest::TodoException: not implemented yet>
126
+ /topic
127
+ /topic
128
+ /file
129
+ END
130
+ assert_eq sout, expected
131
+ assert_eq serr, ""
132
+ end
133
+ it "[!u45di] runs spec block with context object which allows to call methods defined in topics." do
134
+ Oktest.scope do
135
+ def v1; "V1"; end
136
+ topic "Parent" do
137
+ def v2; "V2"; end
138
+ topic "Child" do
139
+ def v3; "V3"; end
140
+ spec "spec#1" do
141
+ p v1
142
+ p v2
143
+ p v3
144
+ end
145
+ end
146
+ end
147
+ end
148
+ sout, serr = capture do
149
+ runner = Oktest::Runner.new(DummyReporter.new).start()
150
+ end
151
+ expected = <<'END'
152
+ file: "test/runner_test.rb"
153
+ topic: "Parent"
154
+ topic: "Child"
155
+ spec: "spec#1"
156
+ "V1"
157
+ "V2"
158
+ "V3"
159
+ /spec: status=:PASS
160
+ /topic
161
+ /topic
162
+ /file
163
+ END
164
+ assert_eq sout, expected
165
+ assert_eq serr, ""
166
+ end
167
+ it "[!yagka] calls 'before' and 'after' blocks with context object as self." do
168
+ sout, serr = capture do
169
+ Oktest.scope do
170
+ before { @x ||= 1; puts " [all] before: @x=#{@x}" }
171
+ after { puts " [all] after: @x=#{@x}" }
172
+ topic "Parent" do
173
+ before { @x ||= 2; puts " [Parent] before: @x=#{@x}" }
174
+ after { puts " [Parent] after: @x=#{@x}" }
175
+ topic "Child1" do
176
+ before { @x ||= 3; puts " [Child1] before: @x=#{@x}" }
177
+ after { puts " [Child1] after: @x=#{@x}" }
178
+ spec("spec#1") { puts " @x=#{@x}" }
179
+ spec("spec#2") { puts " @x=#{@x}" }
180
+ end
181
+ topic "Child2" do
182
+ spec("spec#3") { puts " @x=#{@x}" }
183
+ spec("spec#4") { puts " @x=#{@x}" }
184
+ end
185
+ end
186
+ end
187
+ runner = Oktest::Runner.new(DummyReporter.new).start()
188
+ end
189
+ expected = <<'END'
190
+ file: "test/runner_test.rb"
191
+ topic: "Parent"
192
+ topic: "Child1"
193
+ spec: "spec#1"
194
+ [all] before: @x=1
195
+ [Parent] before: @x=1
196
+ [Child1] before: @x=1
197
+ @x=1
198
+ [Child1] after: @x=1
199
+ [Parent] after: @x=1
200
+ [all] after: @x=1
201
+ /spec: status=:PASS
202
+ spec: "spec#2"
203
+ [all] before: @x=1
204
+ [Parent] before: @x=1
205
+ [Child1] before: @x=1
206
+ @x=1
207
+ [Child1] after: @x=1
208
+ [Parent] after: @x=1
209
+ [all] after: @x=1
210
+ /spec: status=:PASS
211
+ /topic
212
+ topic: "Child2"
213
+ spec: "spec#3"
214
+ [all] before: @x=1
215
+ [Parent] before: @x=1
216
+ @x=1
217
+ [Parent] after: @x=1
218
+ [all] after: @x=1
219
+ /spec: status=:PASS
220
+ spec: "spec#4"
221
+ [all] before: @x=1
222
+ [Parent] before: @x=1
223
+ @x=1
224
+ [Parent] after: @x=1
225
+ [all] after: @x=1
226
+ /spec: status=:PASS
227
+ /topic
228
+ /topic
229
+ /file
230
+ END
231
+ assert_eq sout, expected
232
+ assert_eq serr, ""
233
+ end
234
+ it "[!76g7q] calls 'after' blocks even when exception raised." do
235
+ sout, serr = capture do
236
+ Oktest.scope do
237
+ after { puts "[all] after" }
238
+ topic "Parent" do
239
+ after { puts "[Parent] after" }
240
+ topic "Child" do
241
+ after { puts "[Child] after" }
242
+ spec("spec#1") { ok {1+1} == 1 }
243
+ end
244
+ end
245
+ end
246
+ runner = Oktest::Runner.new(DummyReporter.new).start()
247
+ end
248
+ expected = <<'END'
249
+ file: "test/runner_test.rb"
250
+ topic: "Parent"
251
+ topic: "Child"
252
+ spec: "spec#1"
253
+ [Child] after
254
+ [Parent] after
255
+ [all] after
256
+ /spec: status=:FAIL, error=#<ASSERTION: $<actual> == $<expected>: failed.
257
+ $<actual>: 2
258
+ $<expected>: 1>
259
+ /topic
260
+ /topic
261
+ /file
262
+ END
263
+ assert_eq sout, expected
264
+ assert_eq serr, ""
265
+ end
266
+ it "[!dihkr] calls 'at_end' blocks, even when exception raised." do
267
+ sout, serr = capture do
268
+ Oktest.scope do
269
+ topic "topic#A" do
270
+ spec("spec#1") { at_end { puts " - at_end A1" } }
271
+ spec("spec#2") { at_end { puts " - at_end A2" }; "".null? } # raises NoMethodError
272
+ end
273
+ end
274
+ runner = Oktest::Runner.new(DummyReporter.new).start()
275
+ end
276
+ expected = <<'END'
277
+ file: "test/runner_test.rb"
278
+ topic: "topic#A"
279
+ spec: "spec#1"
280
+ - at_end A1
281
+ /spec: status=:PASS
282
+ spec: "spec#2"
283
+ - at_end A2
284
+ /spec: status=:ERROR, error=#<NoMethodError: undefined method `null?' for "":String>
285
+ /topic
286
+ /file
287
+ END
288
+ assert_eq sout, expected
289
+ assert_eq serr, ""
290
+ end
291
+ describe "[!68cnr] if TODO() called in spec..." do
292
+ it "[!6ol3p] changes PASS status to FAIL because test passed unexpectedly." do
293
+ Oktest.scope do
294
+ topic "topic#A" do
295
+ spec("spec#1") { TODO(); ok {1+1} == 2 } # passed unexpectedly
296
+ end
297
+ end
298
+ sout, serr = capture { Oktest::Runner.new(DummyReporter.new).start() }
299
+ expected = <<'END'
300
+ file: "test/runner_test.rb"
301
+ topic: "topic#A"
302
+ spec: "spec#1"
303
+ /spec: status=:FAIL, error=#<ASSERTION: spec should be failed (because not implemented yet), but passed unexpectedly.>
304
+ /topic
305
+ /file
306
+ END
307
+ assert_eq sout, expected
308
+ end
309
+ it "[!6syw4] changes FAIL status to TODO because test failed expectedly." do
310
+ Oktest.scope do
311
+ topic "topic#A" do
312
+ spec("spec#1") { TODO(); ok {1+1} == 1 } # failed expectedly
313
+ end
314
+ end
315
+ sout, serr = capture { Oktest::Runner.new(DummyReporter.new).start() }
316
+ expected = <<'END'
317
+ file: "test/runner_test.rb"
318
+ topic: "topic#A"
319
+ spec: "spec#1"
320
+ /spec: status=:TODO, error=#<Oktest::TodoException: not implemented yet>
321
+ /topic
322
+ /file
323
+ END
324
+ assert_eq sout, expected
325
+ end
326
+ it "[!4aecm] changes also ERROR status to TODO because test failed expectedly." do
327
+ Oktest.scope do
328
+ topic "topic#B" do
329
+ spec("spec#2") { TODO(); ok {foobar} == nil } # will be error expectedly
330
+ end
331
+ end
332
+ sout, serr = capture { Oktest::Runner.new(DummyReporter.new).start() }
333
+ expected = <<'END'
334
+ file: "test/runner_test.rb"
335
+ topic: "topic#B"
336
+ spec: "spec#2"
337
+ /spec: status=:TODO, error=#<Oktest::TodoException: NameError raised because not implemented yet>
338
+ /topic
339
+ /file
340
+ END
341
+ assert_eq sout, expected
342
+ end
343
+ end
344
+ end
345
+
346
+ describe "#visit_topic()" do
347
+ it "[!i3yfv] calls 'before_all' and 'after_all' blocks." do
348
+ sout, serr = capture do
349
+ Oktest.scope do
350
+ before_all { puts "[all] before_all" }
351
+ after_all { puts "[all] after_all" }
352
+ topic "Parent" do
353
+ before_all { puts " [Parent] before_all" }
354
+ after_all { puts " [Parent] after_all" }
355
+ topic "Child1" do
356
+ before_all { puts " [Child1] before_all" }
357
+ after_all { puts " [Child1] after_all" }
358
+ spec("1+1 should be 2") { ok {1+1} == 2 }
359
+ spec("1-1 should be 0") { ok {1-1} == 0 }
360
+ end
361
+ topic "Child2" do
362
+ spec("1*1 should be 1") { ok {1*1} == 1 }
363
+ spec("1/1 should be 1") { ok {1/1} == 1 }
364
+ end
365
+ end
366
+ end
367
+ Oktest::Runner.new(DummyReporter.new).start()
368
+ end
369
+ expected = <<'END'
370
+ file: "test/runner_test.rb"
371
+ [all] before_all
372
+ topic: "Parent"
373
+ [Parent] before_all
374
+ topic: "Child1"
375
+ [Child1] before_all
376
+ spec: "1+1 should be 2"
377
+ /spec: status=:PASS
378
+ spec: "1-1 should be 0"
379
+ /spec: status=:PASS
380
+ [Child1] after_all
381
+ /topic
382
+ topic: "Child2"
383
+ spec: "1*1 should be 1"
384
+ /spec: status=:PASS
385
+ spec: "1/1 should be 1"
386
+ /spec: status=:PASS
387
+ /topic
388
+ [Parent] after_all
389
+ /topic
390
+ [all] after_all
391
+ /file
392
+ END
393
+ assert_eq sout, expected
394
+ assert_eq serr, ""
395
+ end
396
+ end
397
+
398
+ describe "#visit_scope()" do
399
+ it "[!5anr7] calls before_all and after_all blocks." do
400
+ sout, serr = capture do
401
+ Oktest.scope do
402
+ before_all { puts "[all] before_all#1" }
403
+ after_all { puts "[all] after_all#1" }
404
+ end
405
+ Oktest.scope do
406
+ before_all { puts "[all] before_all#2" }
407
+ after_all { puts "[all] after_all#2" }
408
+ end
409
+ Oktest::Runner.new(DummyReporter.new).start()
410
+ end
411
+ expected = <<'END'
412
+ file: "test/runner_test.rb"
413
+ [all] before_all#1
414
+ [all] after_all#1
415
+ /file
416
+ file: "test/runner_test.rb"
417
+ [all] before_all#2
418
+ [all] after_all#2
419
+ /file
420
+ END
421
+ assert_eq sout, expected
422
+ assert_eq serr, ""
423
+ end
424
+ end
425
+
426
+
427
+ end
428
+
429
+
430
+ class RunnerFunctions_TC < TC
431
+
432
+ def setup()
433
+ end
434
+
435
+ def teardown()
436
+ Oktest::THE_GLOBAL_SCOPE.clear_children()
437
+ end
438
+
439
+ def plain2colored(str)
440
+ str = str.gsub(/<R>(.*?)<\/R>/) { Oktest::Color.red($1) }
441
+ str = str.gsub(/<G>(.*?)<\/G>/) { Oktest::Color.green($1) }
442
+ str = str.gsub(/<B>(.*?)<\/B>/) { Oktest::Color.blue($1) }
443
+ str = str.gsub(/<Y>(.*?)<\/Y>/) { Oktest::Color.yellow($1) }
444
+ str = str.gsub(/<b>(.*?)<\/b>/) { Oktest::Color.bold($1) }
445
+ return str
446
+ end
447
+
448
+ def edit_actual(output)
449
+ bkup = output.dup
450
+ output = output.gsub(/^.*\r/, '')
451
+ output = output.gsub(/^ .*(_test\.tmp:\d+)/, ' \1')
452
+ output = output.gsub(/^ .*test.reporter_test\.rb:.*\n( .*\n)*/, "%%%\n")
453
+ output = output.sub(/ in \d+\.\d\d\ds/, ' in 0.000s')
454
+ return output
455
+ end
456
+
457
+ def edit_expected(expected)
458
+ expected = expected.gsub(/^ (.*:\d+)(:in `block .*)/, ' \1') if RUBY_VERSION < "1.9"
459
+ expected = plain2colored(expected)
460
+ return expected
461
+ end
462
+
463
+ def prepare()
464
+ Oktest.scope do
465
+ topic 'Example' do
466
+ spec '1+1 should be 2' do
467
+ ok {1+1} == 2
468
+ end
469
+ spec '1-1 should be 0' do
470
+ ok {1-1} == 0
471
+ end
472
+ end
473
+ end
474
+ end
475
+
476
+ VERBOSE_OUTPUT = <<'END'
477
+ * <b>Example</b>
478
+ - [<B>pass</B>] 1+1 should be 2
479
+ - [<B>pass</B>] 1-1 should be 0
480
+ ## total:2 (<B>pass:2</B>, fail:0, error:0, skip:0, todo:0) in 0.000s
481
+ END
482
+ SIMPLE_OUTPUT = <<'END'
483
+ test/runner_test.rb: <B>.</B><B>.</B>
484
+ ## total:2 (<B>pass:2</B>, fail:0, error:0, skip:0, todo:0) in 0.000s
485
+ END
486
+ PLAIN_OUTPUT = <<'END'
487
+ <B>.</B><B>.</B>
488
+ ## total:2 (<B>pass:2</B>, fail:0, error:0, skip:0, todo:0) in 0.000s
489
+ END
490
+
491
+
492
+ describe 'Oktest.run()' do
493
+ it "[!mn451] run test cases." do
494
+ expected = VERBOSE_OUTPUT
495
+ prepare()
496
+ sout, serr = capture { Oktest.run() }
497
+ assert_eq edit_actual(sout), edit_expected(expected)
498
+ assert_eq serr, ""
499
+ end
500
+ it "[!kfi8b] do nothing when 'Oktest.scope()' not called." do
501
+ sout, serr = capture { Oktest.run() }
502
+ assert_eq sout, ""
503
+ assert_eq serr, ""
504
+ end
505
+ it "[!6xn3t] creates reporter object according to 'style:' keyword arg." do
506
+ expected = VERBOSE_OUTPUT
507
+ prepare()
508
+ sout, serr = capture { Oktest.run(:style=>"verbose") }
509
+ assert_eq edit_actual(sout), edit_expected(expected)
510
+ assert_eq serr, ""
511
+ #
512
+ expected = SIMPLE_OUTPUT
513
+ prepare()
514
+ sout, serr = capture { Oktest.run(:style=>"simple") }
515
+ assert_eq edit_actual(sout), edit_expected(expected)
516
+ assert_eq serr, ""
517
+ #
518
+ expected = PLAIN_OUTPUT
519
+ prepare()
520
+ sout, serr = capture { Oktest.run(:style=>"plain") }
521
+ assert_eq edit_actual(sout), edit_expected(expected)
522
+ assert_eq serr, ""
523
+ end
524
+ it "[!p52se] returns total number of failures and errors." do
525
+ prepare()
526
+ ret = nil
527
+ _ = capture { ret = Oktest.run() }
528
+ assert_eq ret, 0 # no failures, no errors
529
+ #
530
+ Oktest.scope do
531
+ topic 'Example' do
532
+ spec('pass') { ok {1+1} == 2 }
533
+ spec('fail') { ok {1*1} == 2 }
534
+ spec('error') { ok {1/0} == 0 }
535
+ spec('skip') { skip_when true, "reason" }
536
+ spec('todo')
537
+ end
538
+ end
539
+ _ = capture { ret = Oktest.run() }
540
+ assert_eq ret, 2 # 1 failure, 1 error
541
+ end
542
+ end
543
+
544
+ end