test-unit 2.5.1 → 2.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +7 -2
- data/Rakefile +1 -1
- data/lib/test-unit.rb +19 -0
- data/lib/test/unit.rb +183 -12
- data/lib/test/unit/assertions.rb +9 -6
- data/lib/test/unit/autorunner.rb +17 -0
- data/lib/test/unit/collector.rb +33 -1
- data/lib/test/unit/collector/descendant.rb +1 -5
- data/lib/test/unit/collector/load.rb +1 -3
- data/lib/test/unit/color-scheme.rb +36 -30
- data/lib/test/unit/color.rb +19 -8
- data/lib/test/unit/error.rb +6 -3
- data/lib/test/unit/exceptionhandler.rb +48 -5
- data/lib/test/unit/failure.rb +39 -6
- data/lib/test/unit/fault-location-detector.rb +95 -0
- data/lib/test/unit/notification.rb +5 -2
- data/lib/test/unit/omission.rb +7 -3
- data/lib/test/unit/pending.rb +7 -3
- data/lib/test/unit/testcase.rb +132 -9
- data/lib/test/unit/testsuite.rb +1 -1
- data/lib/test/unit/ui/console/testrunner.rb +14 -6
- data/lib/test/unit/ui/testrunnermediator.rb +18 -6
- data/lib/test/unit/util/backtracefilter.rb +1 -1
- data/lib/test/unit/version.rb +1 -1
- data/test/test-color-scheme.rb +29 -22
- data/test/test-color.rb +1 -1
- data/test/test-fault-location-detector.rb +125 -0
- data/test/test-testcase.rb +156 -2
- data/test/testunit-test-util.rb +2 -2
- metadata +5 -2
data/lib/test/unit/testsuite.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
|
9
9
|
require 'test/unit/color-scheme'
|
10
10
|
require 'test/unit/code-snippet-fetcher'
|
11
|
+
require 'test/unit/fault-location-detector'
|
11
12
|
require 'test/unit/diff'
|
12
13
|
require 'test/unit/ui/testrunner'
|
13
14
|
require 'test/unit/ui/testrunnermediator'
|
@@ -47,6 +48,7 @@ module Test
|
|
47
48
|
@current_output_level = NORMAL
|
48
49
|
@faults = []
|
49
50
|
@code_snippet_fetcher = CodeSnippetFetcher.new
|
51
|
+
@test_suites = []
|
50
52
|
end
|
51
53
|
|
52
54
|
private
|
@@ -202,6 +204,7 @@ module Test
|
|
202
204
|
|
203
205
|
def output_fault_backtrace(fault)
|
204
206
|
snippet_is_shown = false
|
207
|
+
detector = FaultLocationDetector.new(fault, @code_snippet_fetcher)
|
205
208
|
backtrace = fault.location
|
206
209
|
# workaround for test-spec. :<
|
207
210
|
# see also GitHub:#22
|
@@ -209,14 +212,14 @@ module Test
|
|
209
212
|
backtrace.each_with_index do |entry, i|
|
210
213
|
output(entry)
|
211
214
|
next if snippet_is_shown
|
212
|
-
|
215
|
+
next unless detector.target?(entry)
|
216
|
+
file, line_number, = detector.split_backtrace_entry(entry)
|
217
|
+
snippet_is_shown = output_code_snippet(file, line_number,
|
218
|
+
fault_color(fault))
|
213
219
|
end
|
214
220
|
end
|
215
221
|
|
216
|
-
def output_code_snippet(
|
217
|
-
return false unless /\A(.*):(\d+)/ =~ entry
|
218
|
-
file = $1
|
219
|
-
line_number = $2.to_i
|
222
|
+
def output_code_snippet(file, line_number, target_line_color=nil)
|
220
223
|
lines = @code_snippet_fetcher.fetch(file, line_number)
|
221
224
|
return false if lines.empty?
|
222
225
|
|
@@ -333,6 +336,8 @@ module Test
|
|
333
336
|
end
|
334
337
|
|
335
338
|
def test_suite_started(suite)
|
339
|
+
last_test_suite = @test_suites.last
|
340
|
+
@test_suites << suite
|
336
341
|
if @top_level
|
337
342
|
@top_level = false
|
338
343
|
return
|
@@ -344,13 +349,16 @@ module Test
|
|
344
349
|
else
|
345
350
|
_color = color("case")
|
346
351
|
end
|
347
|
-
|
352
|
+
prefix = "#{last_test_suite.name}::"
|
353
|
+
suite_name = suite.name.sub(/\A#{Regexp.escape(prefix)}/, "")
|
354
|
+
output_single(suite_name, _color, VERBOSE)
|
348
355
|
output(": ", nil, VERBOSE)
|
349
356
|
@indent += 2
|
350
357
|
end
|
351
358
|
|
352
359
|
def test_suite_finished(suite)
|
353
360
|
@indent -= 2
|
361
|
+
@test_suites.pop
|
354
362
|
end
|
355
363
|
|
356
364
|
def indent
|
@@ -34,6 +34,7 @@ module Test
|
|
34
34
|
|
35
35
|
result = create_result
|
36
36
|
|
37
|
+
Test::Unit.run_at_start_hooks
|
37
38
|
start_time = Time.now
|
38
39
|
begin
|
39
40
|
with_listener(result) do
|
@@ -46,10 +47,27 @@ module Test
|
|
46
47
|
elapsed_time = Time.now - start_time
|
47
48
|
notify_listeners(FINISHED, elapsed_time)
|
48
49
|
end
|
50
|
+
Test::Unit.run_at_exit_hooks
|
49
51
|
|
50
52
|
result
|
51
53
|
end
|
52
54
|
|
55
|
+
# Just for backward compatibility for NetBeans.
|
56
|
+
# NetBeans should not use monkey patching. NetBeans
|
57
|
+
# should use runner change public API.
|
58
|
+
#
|
59
|
+
# See GitHub#38
|
60
|
+
# https://github.com/test-unit/test-unit/issues/38
|
61
|
+
def run_suite(result=nil)
|
62
|
+
if result.nil?
|
63
|
+
run
|
64
|
+
else
|
65
|
+
@suite.run(result) do |channel, value|
|
66
|
+
notify_listeners(channel, value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
53
71
|
private
|
54
72
|
# A factory method to create the result the mediator
|
55
73
|
# should run with. Can be overridden by subclasses if
|
@@ -88,12 +106,6 @@ module Test
|
|
88
106
|
pass_assertion_listener)
|
89
107
|
end
|
90
108
|
end
|
91
|
-
|
92
|
-
def run_suite(result)
|
93
|
-
@suite.run(result) do |channel, value|
|
94
|
-
notify_listeners(channel, value)
|
95
|
-
end
|
96
|
-
end
|
97
109
|
end
|
98
110
|
end
|
99
111
|
end
|
data/lib/test/unit/version.rb
CHANGED
data/test/test-color-scheme.rb
CHANGED
@@ -54,28 +54,35 @@ class TestUnitColorScheme < Test::Unit::TestCase
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def test_default
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
57
|
+
expected_schema = {
|
58
|
+
"pass" => color("green", :background => true) +
|
59
|
+
color("white", :bold => true),
|
60
|
+
"failure" => color("red", :background => true) +
|
61
|
+
color("white", :bold => true),
|
62
|
+
"pending" => color("magenta", :background => true) +
|
63
|
+
color("white", :bold => true),
|
64
|
+
"omission" => color("blue", :background => true) +
|
65
|
+
color("white", :bold => true),
|
66
|
+
"notification" => color("cyan", :background => true) +
|
67
|
+
color("white", :bold => true),
|
68
|
+
"error" => color("black", :background => true) +
|
69
|
+
color("yellow", :bold => true),
|
70
|
+
"case" => color("blue", :background => true) +
|
71
|
+
color("white", :bold => true),
|
72
|
+
"suite" => color("green", :background => true) +
|
73
|
+
color("white", :bold => true),
|
74
|
+
"diff-inserted-tag" => color("red", :background => true) +
|
75
|
+
color("black", :bold => true),
|
76
|
+
"diff-deleted-tag" => color("green", :background => true) +
|
77
|
+
color("black", :bold => true),
|
78
|
+
"diff-difference-tag" => color("cyan", :background => true) +
|
79
|
+
color("white", :bold => true),
|
80
|
+
"diff-inserted" => color("red", :background => true) +
|
81
|
+
color("white", :bold => true),
|
82
|
+
"diff-deleted" => color("green", :background => true) +
|
83
|
+
color("white", :bold => true),
|
84
|
+
}
|
85
|
+
assert_equal(expected_schema,
|
79
86
|
Test::Unit::ColorScheme.default.to_hash)
|
80
87
|
end
|
81
88
|
end
|
data/test/test-color.rb
CHANGED
@@ -3,7 +3,7 @@ class TestUnitColor < Test::Unit::TestCase
|
|
3
3
|
assert_escape_sequence(["31"], color("red"))
|
4
4
|
assert_escape_sequence(["32", "1"], color("green", :bold => true))
|
5
5
|
assert_escape_sequence(["0"], color("reset"))
|
6
|
-
assert_escape_sequence(["45"], color("magenta", :
|
6
|
+
assert_escape_sequence(["45"], color("magenta", :background => true))
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_mix_color_escape_sequence
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
|
2
|
+
#
|
3
|
+
# License: Ruby's
|
4
|
+
|
5
|
+
require "test-unit"
|
6
|
+
require "test/unit/fault-location-detector"
|
7
|
+
require "testunit-test-util"
|
8
|
+
|
9
|
+
class TestFaultLocationDetector < Test::Unit::TestCase
|
10
|
+
include TestUnitTestUtil
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@fetcher = Test::Unit::CodeSnippetFetcher.new
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def run_test_case(test_case)
|
18
|
+
suite = test_case.suite
|
19
|
+
result = Test::Unit::TestResult.new
|
20
|
+
suite.run(result) {}
|
21
|
+
result.faults[0]
|
22
|
+
end
|
23
|
+
|
24
|
+
def assert_detect(fault, target_line_number)
|
25
|
+
detector = Test::Unit::FaultLocationDetector.new(fault, @fetcher)
|
26
|
+
|
27
|
+
expected = fault.location.collect do |backtrace_entry|
|
28
|
+
_, line_number, = detector.split_backtrace_entry(backtrace_entry)
|
29
|
+
[backtrace_entry, target_line_number == line_number]
|
30
|
+
end
|
31
|
+
actual = fault.location.collect do |backtrace_entry|
|
32
|
+
[backtrace_entry, detector.target?(backtrace_entry)]
|
33
|
+
end
|
34
|
+
assert_equal(expected, actual)
|
35
|
+
end
|
36
|
+
|
37
|
+
module AlwaysFailAssertion
|
38
|
+
private
|
39
|
+
def assert_always_failed
|
40
|
+
assert_true(false)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class TestSourceLocation < self
|
45
|
+
setup
|
46
|
+
def setup_check_source_location
|
47
|
+
unless lambda {}.respond_to?(:source_location)
|
48
|
+
omit("Need Proc#source_location")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_detected
|
53
|
+
target_line_number = nil
|
54
|
+
test_case = Class.new(Test::Unit::TestCase) do
|
55
|
+
include AlwaysFailAssertion
|
56
|
+
|
57
|
+
test "failed" do
|
58
|
+
target_line_number = __LINE__; assert_always_failed
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
fault = run_test_case(test_case)
|
63
|
+
assert_detect(fault, target_line_number)
|
64
|
+
end
|
65
|
+
|
66
|
+
class TestOneLine < self
|
67
|
+
def test_brace
|
68
|
+
target_line_number = nil
|
69
|
+
test_case = Class.new(Test::Unit::TestCase) do
|
70
|
+
include AlwaysFailAssertion
|
71
|
+
|
72
|
+
test("failed") {target_line_number = __LINE__; assert_always_failed}
|
73
|
+
|
74
|
+
def other_method
|
75
|
+
# body
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
fault = run_test_case(test_case)
|
80
|
+
assert_detect(fault, target_line_number)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_do_end
|
84
|
+
target_line_number = nil
|
85
|
+
test_case = Class.new(Test::Unit::TestCase) do
|
86
|
+
include AlwaysFailAssertion
|
87
|
+
|
88
|
+
test "failed" do target_line_number = __LINE__; assert_always_failed; end
|
89
|
+
|
90
|
+
def other_method
|
91
|
+
# body
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
fault = run_test_case(test_case)
|
96
|
+
assert_detect(fault, target_line_number)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class TestMethodName < self
|
102
|
+
def test_detected
|
103
|
+
test_case = Class.new(Test::Unit::TestCase) do
|
104
|
+
include AlwaysFailAssertion
|
105
|
+
|
106
|
+
class << self
|
107
|
+
def target_line_number
|
108
|
+
@@target_line_number
|
109
|
+
end
|
110
|
+
|
111
|
+
def target_line_number=(line_number)
|
112
|
+
@@target_line_number = line_number
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_failed
|
117
|
+
self.class.target_line_number = __LINE__; assert_always_failed
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
fault = run_test_case(test_case)
|
122
|
+
assert_detect(fault, test_case.target_line_number)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/test/test-testcase.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Author:: Nathaniel Talbott.
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2008-2012 Kouhei Sutou <kou@clear-code.com>
|
3
|
+
# Copyright:: Copyright (c) 2011 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
|
+
# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott
|
3
5
|
# License:: Ruby license.
|
4
6
|
|
5
7
|
require 'test/unit'
|
@@ -46,7 +48,7 @@ module Test
|
|
46
48
|
"TC_FailureError"
|
47
49
|
end
|
48
50
|
end
|
49
|
-
|
51
|
+
|
50
52
|
def test_add_failed_assertion
|
51
53
|
test_case = @tc_failure_error.new(:test_failure)
|
52
54
|
check("passed? should start out true", test_case.return_passed?)
|
@@ -585,6 +587,158 @@ module Test
|
|
585
587
|
add_assertion
|
586
588
|
raise AssertionFailedError.new(message) unless passed
|
587
589
|
end
|
590
|
+
|
591
|
+
class TestTestDefined < self
|
592
|
+
class TestNoQuery < self
|
593
|
+
def test_have_test
|
594
|
+
test_case = Class.new(TestCase) do
|
595
|
+
def test_nothing
|
596
|
+
end
|
597
|
+
end
|
598
|
+
assert_true(test_case.test_defined?({}))
|
599
|
+
end
|
600
|
+
|
601
|
+
def test_no_test
|
602
|
+
test_case = Class.new(TestCase) do
|
603
|
+
end
|
604
|
+
assert_false(test_case.test_defined?({}))
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
class TestPath < self
|
609
|
+
def test_base_name
|
610
|
+
test_case = Class.new(TestCase) do
|
611
|
+
def test_nothing
|
612
|
+
end
|
613
|
+
end
|
614
|
+
base_name = File.basename(__FILE__)
|
615
|
+
assert_true(test_case.test_defined?(:path => base_name))
|
616
|
+
end
|
617
|
+
|
618
|
+
def test_absolute_path
|
619
|
+
test_case = Class.new(TestCase) do
|
620
|
+
def test_nothing
|
621
|
+
end
|
622
|
+
end
|
623
|
+
assert_true(test_case.test_defined?(:path => __FILE__))
|
624
|
+
end
|
625
|
+
|
626
|
+
def test_not_match
|
627
|
+
test_case = Class.new(TestCase) do
|
628
|
+
def test_nothing
|
629
|
+
end
|
630
|
+
end
|
631
|
+
assert_false(test_case.test_defined?(:path => "nonexistent.rb"))
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
class TestLine < self
|
636
|
+
def test_before
|
637
|
+
line_before = nil
|
638
|
+
test_case = Class.new(TestCase) do
|
639
|
+
line_before = __LINE__
|
640
|
+
def test_nothing
|
641
|
+
end
|
642
|
+
end
|
643
|
+
assert_false(test_case.test_defined?(:line => line_before))
|
644
|
+
end
|
645
|
+
|
646
|
+
def test_def
|
647
|
+
line_def = nil
|
648
|
+
test_case = Class.new(TestCase) do
|
649
|
+
line_def = __LINE__; def test_nothing
|
650
|
+
end
|
651
|
+
end
|
652
|
+
assert_true(test_case.test_defined?(:line => line_def))
|
653
|
+
end
|
654
|
+
|
655
|
+
def test_after
|
656
|
+
line_after = nil
|
657
|
+
test_case = Class.new(TestCase) do
|
658
|
+
def test_nothing
|
659
|
+
end
|
660
|
+
line_after = __LINE__
|
661
|
+
end
|
662
|
+
assert_true(test_case.test_defined?(:line => line_after))
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
class TestMethodName < self
|
667
|
+
def test_match
|
668
|
+
test_case = Class.new(TestCase) do
|
669
|
+
def test_nothing
|
670
|
+
end
|
671
|
+
end
|
672
|
+
assert_true(test_case.test_defined?(:method_name => "test_nothing"))
|
673
|
+
end
|
674
|
+
|
675
|
+
def test_not_match
|
676
|
+
test_case = Class.new(TestCase) do
|
677
|
+
def test_nothing
|
678
|
+
end
|
679
|
+
end
|
680
|
+
query = {:method_name => "test_nonexistent"}
|
681
|
+
assert_false(test_case.test_defined?(query))
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
685
|
+
class TestCombine < self
|
686
|
+
def test_line_middle
|
687
|
+
line_middle = nil
|
688
|
+
test_case = Class.new(TestCase) do
|
689
|
+
def test_before
|
690
|
+
end
|
691
|
+
line_middle = __LINE__
|
692
|
+
def test_after
|
693
|
+
end
|
694
|
+
end
|
695
|
+
query = {
|
696
|
+
:path => __FILE__,
|
697
|
+
:line => line_middle,
|
698
|
+
:method_name => "test_before",
|
699
|
+
}
|
700
|
+
assert_true(test_case.test_defined?(query))
|
701
|
+
end
|
702
|
+
|
703
|
+
def test_line_after_def
|
704
|
+
line_after_def = nil
|
705
|
+
test_case = Class.new(TestCase) do
|
706
|
+
def test_before
|
707
|
+
end
|
708
|
+
|
709
|
+
line_after_def = __LINE__; def test_after
|
710
|
+
end
|
711
|
+
end
|
712
|
+
query = {
|
713
|
+
:path => __FILE__,
|
714
|
+
:line => line_after_def,
|
715
|
+
:method_name => "test_before",
|
716
|
+
}
|
717
|
+
assert_false(test_case.test_defined?(query))
|
718
|
+
end
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
class TestSubTestCase < self
|
723
|
+
def test_name
|
724
|
+
test_case = Class.new(TestCase)
|
725
|
+
sub_test_case = test_case.sub_test_case("sub test case") do
|
726
|
+
end
|
727
|
+
assert_equal("sub test case", sub_test_case.name)
|
728
|
+
end
|
729
|
+
|
730
|
+
def test_suite
|
731
|
+
test_case = Class.new(TestCase)
|
732
|
+
sub_test_case = test_case.sub_test_case("sub test case") do
|
733
|
+
def test_nothing
|
734
|
+
end
|
735
|
+
end
|
736
|
+
test_method_names = sub_test_case.suite.tests.collect do |test|
|
737
|
+
test.method_name
|
738
|
+
end
|
739
|
+
assert_equal(["test_nothing"], test_method_names)
|
740
|
+
end
|
741
|
+
end
|
588
742
|
end
|
589
743
|
end
|
590
744
|
end
|