oktest 1.0.0

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