test-unit-ext 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS.en +7 -0
- data/NEWS.ja +7 -0
- data/README.en +51 -0
- data/README.ja +51 -0
- data/Rakefile +106 -0
- data/html/index.html +21 -0
- data/html/news.html +18 -0
- data/html/news.html.en +18 -0
- data/html/news.html.ja +18 -0
- data/html/readme.html +42 -0
- data/html/readme.html.en +42 -0
- data/html/readme.html.ja +42 -0
- data/lib/test-unit-ext.rb +11 -0
- data/lib/test-unit-ext/always-show-result.rb +28 -0
- data/lib/test-unit-ext/backtrace-filter.rb +17 -0
- data/lib/test-unit-ext/color.rb +59 -0
- data/lib/test-unit-ext/colorized-runner.rb +101 -0
- data/lib/test-unit-ext/diff.rb +187 -0
- data/lib/test-unit-ext/long-display-for-emacs.rb +25 -0
- data/lib/test-unit-ext/metadata.rb +111 -0
- data/lib/test-unit-ext/priority.rb +186 -0
- data/lib/test-unit-ext/version.rb +3 -0
- data/misc/rd2html.rb +42 -0
- data/test/run-test.rb +14 -0
- data/test/test_color.rb +39 -0
- data/test/test_diff.rb +109 -0
- data/test/test_metadata.rb +127 -0
- metadata +83 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
module Test
|
6
|
+
module Unit
|
7
|
+
class TestCase
|
8
|
+
class << self
|
9
|
+
def inherited(sub)
|
10
|
+
super
|
11
|
+
sub.instance_variable_set("@priority_initialized", true)
|
12
|
+
sub.instance_variable_set("@priority_table", {})
|
13
|
+
sub.priority :normal
|
14
|
+
end
|
15
|
+
|
16
|
+
def include(*args)
|
17
|
+
args.reverse_each do |mod|
|
18
|
+
super(mod)
|
19
|
+
next unless defined?(@priority_initialized)
|
20
|
+
mod.instance_methods(false).each do |name|
|
21
|
+
set_priority(name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :method_added_without_priority, :method_added
|
27
|
+
def method_added(name)
|
28
|
+
method_added_without_priority(name)
|
29
|
+
set_priority(name) if defined?(@priority_initialized)
|
30
|
+
end
|
31
|
+
|
32
|
+
def priority(name, *tests)
|
33
|
+
singleton_class = (class << self; self; end)
|
34
|
+
priority_check_method = priority_check_method_name(name)
|
35
|
+
unless singleton_class.private_method_defined?(priority_check_method)
|
36
|
+
raise ArgumentError, "unknown priority: #{name}"
|
37
|
+
end
|
38
|
+
if tests.empty?
|
39
|
+
@current_priority = name
|
40
|
+
else
|
41
|
+
tests.each do |test|
|
42
|
+
set_priority(test, name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def need_to_run?(test_name)
|
48
|
+
normalized_test_name = normalize_test_name(test_name)
|
49
|
+
priority = @priority_table[normalized_test_name]
|
50
|
+
return true unless priority
|
51
|
+
__send__(priority_check_method_name(priority), test_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def priority_check_method_name(priority_name)
|
56
|
+
"run_priority_#{priority_name}?"
|
57
|
+
end
|
58
|
+
|
59
|
+
def normalize_test_name(test_name)
|
60
|
+
"test_#{test_name.to_s.sub(/^test_/, '')}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_priority(name, priority=@current_priority)
|
64
|
+
@priority_table[normalize_test_name(name)] = priority
|
65
|
+
end
|
66
|
+
|
67
|
+
def run_priority_must?(test_name)
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
def run_priority_important?(test_name)
|
72
|
+
rand > 0.1
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_priority_high?(test_name)
|
76
|
+
rand > 0.3
|
77
|
+
end
|
78
|
+
|
79
|
+
def run_priority_normal?(test_name)
|
80
|
+
rand > 0.5
|
81
|
+
end
|
82
|
+
|
83
|
+
def run_priority_low?(test_name)
|
84
|
+
rand > 0.75
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_priority_never?(test_name)
|
88
|
+
false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def need_to_run?
|
93
|
+
!previous_test_success? or self.class.need_to_run?(@method_name)
|
94
|
+
end
|
95
|
+
|
96
|
+
alias_method :run_without_priority, :run
|
97
|
+
def run(result, &block)
|
98
|
+
run_without_priority(result, &block)
|
99
|
+
ensure
|
100
|
+
if passed?
|
101
|
+
FileUtils.touch(passed_file)
|
102
|
+
else
|
103
|
+
FileUtils.rm_f(passed_file)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def previous_test_success?
|
109
|
+
File.exist?(passed_file)
|
110
|
+
end
|
111
|
+
|
112
|
+
def result_dir
|
113
|
+
components = [".test-result", self.class.name, @method_name.to_s]
|
114
|
+
dir = File.join(File.dirname($0), *components)
|
115
|
+
dir = File.expand_path(dir)
|
116
|
+
begin
|
117
|
+
FileUtils.mkdir_p(dir)
|
118
|
+
rescue Errno::EACCES
|
119
|
+
retry_dir = File.join(File.dirname(__FILE__), "..", *components)
|
120
|
+
retry_dir = File.expand_path(retry_dir)
|
121
|
+
raise if retry_dir == dir
|
122
|
+
dir = retry_dir
|
123
|
+
retry
|
124
|
+
end
|
125
|
+
dir
|
126
|
+
end
|
127
|
+
|
128
|
+
def passed_file
|
129
|
+
File.join(result_dir, "passed")
|
130
|
+
end
|
131
|
+
|
132
|
+
def escaped_method_name
|
133
|
+
@method_name.to_s.gsub(/[!?]$/) do |matched|
|
134
|
+
case matched
|
135
|
+
when "!"
|
136
|
+
".destructive"
|
137
|
+
when "?"
|
138
|
+
".predicate"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class TestSuite
|
145
|
+
@@priority_mode = false
|
146
|
+
|
147
|
+
class << self
|
148
|
+
def priority_mode=(bool)
|
149
|
+
@@priority_mode = bool
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
alias_method :original_run, :run
|
154
|
+
def run(*args, &block)
|
155
|
+
priority_mode = @@priority_mode
|
156
|
+
if priority_mode
|
157
|
+
@original_tests = @tests
|
158
|
+
apply_priority
|
159
|
+
end
|
160
|
+
original_run(*args, &block)
|
161
|
+
ensure
|
162
|
+
@tests = @original_tests if priority_mode
|
163
|
+
end
|
164
|
+
|
165
|
+
def apply_priority
|
166
|
+
@tests = @tests.reject {|test| !test.need_to_run?}
|
167
|
+
end
|
168
|
+
|
169
|
+
def need_to_run?
|
170
|
+
apply_priority
|
171
|
+
!@tests.empty?
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class AutoRunner
|
176
|
+
alias_method :options_without_priority, :options
|
177
|
+
def options
|
178
|
+
opts = options_without_priority
|
179
|
+
opts.on("--[no-]priority", "use priority mode") do |bool|
|
180
|
+
TestSuite.priority_mode = bool
|
181
|
+
end
|
182
|
+
opts
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/misc/rd2html.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
top = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
4
|
+
html_dir = File.join(top, "html")
|
5
|
+
|
6
|
+
require "fileutils"
|
7
|
+
|
8
|
+
css = "base.css"
|
9
|
+
kcode = "utf8"
|
10
|
+
|
11
|
+
options = [
|
12
|
+
"-I#{File.join(top, 'misc')}",
|
13
|
+
"-S",
|
14
|
+
"rd2",
|
15
|
+
"-rrd/rd2html-lib",
|
16
|
+
"--out-code=#{kcode}",
|
17
|
+
proc do |f|
|
18
|
+
"--html-title=#{File.basename(f)}"
|
19
|
+
end,
|
20
|
+
# proc do |f|
|
21
|
+
# "--with-css=#{css}"
|
22
|
+
# end,
|
23
|
+
proc do |f|
|
24
|
+
f
|
25
|
+
end
|
26
|
+
]
|
27
|
+
|
28
|
+
Dir[File.join(top, "*.{ja,en}")].each do |f|
|
29
|
+
if /(README|NEWS)\.(ja|en)\z/ =~ f
|
30
|
+
args = options.collect do |x|
|
31
|
+
if x.respond_to?(:call)
|
32
|
+
x.call(f)
|
33
|
+
else
|
34
|
+
x
|
35
|
+
end
|
36
|
+
end
|
37
|
+
output_base = File.basename(f).downcase.sub(/(ja|en)\z/, "html.\\1")
|
38
|
+
File.open(File.join(html_dir, output_base), "w") do |out|
|
39
|
+
out.puts(`ruby #{args.flatten.join(' ')}`)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/test/run-test.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift("./lib")
|
4
|
+
$LOAD_PATH.unshift("./test")
|
5
|
+
|
6
|
+
require "test-unit-ext"
|
7
|
+
|
8
|
+
Dir.glob("test/**/test_*.rb") do |test|
|
9
|
+
begin
|
10
|
+
require test
|
11
|
+
rescue LoadError
|
12
|
+
puts "Can't load: #{test}: #{$!.message}"
|
13
|
+
end
|
14
|
+
end
|
data/test/test_color.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test-unit-ext'
|
2
|
+
|
3
|
+
class TestColor < Test::Unit::TestCase
|
4
|
+
def test_color_escape_sequence
|
5
|
+
assert_escape_sequence(["31"], color("red"))
|
6
|
+
assert_escape_sequence(["32", "1"], color("green", :bold => true))
|
7
|
+
assert_escape_sequence(["0"], color("reset"))
|
8
|
+
assert_escape_sequence(["45"], color("magenta", :foreground => false))
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_mix_color_escape_sequence
|
12
|
+
assert_escape_sequence(["34", "1"],
|
13
|
+
mix_color([color("blue"),
|
14
|
+
color("none", :bold => true)]))
|
15
|
+
assert_escape_sequence(["34", "1", "4"],
|
16
|
+
mix_color([color("blue"),
|
17
|
+
color("none", :bold => true)]) +
|
18
|
+
color("none", :underline => true))
|
19
|
+
assert_escape_sequence(["34", "1", "4"],
|
20
|
+
color("blue") +
|
21
|
+
color("none", :bold => true) +
|
22
|
+
color("none", :underline => true))
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def color(name, options={})
|
27
|
+
Test::Color.new(name, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def mix_color(colors)
|
31
|
+
Test::MixColor.new(colors)
|
32
|
+
end
|
33
|
+
|
34
|
+
def assert_escape_sequence(expected, color)
|
35
|
+
assert_equal(expected, color.sequence)
|
36
|
+
assert_match(/\e\[(?:\d+;)*\d+m/, color.escape_sequence)
|
37
|
+
assert_equal(expected, color.escape_sequence[2..-2].split(";"))
|
38
|
+
end
|
39
|
+
end
|
data/test/test_diff.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'test-unit-ext'
|
2
|
+
|
3
|
+
class TestDiff < Test::Unit::TestCase
|
4
|
+
def test_to_indexes
|
5
|
+
assert_to_indexes({"abc def" => [0, 2], "abc" => [1]},
|
6
|
+
["abc def", "abc", "abc def"])
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_longest_match
|
10
|
+
assert_longest_match([0, 1, 3],
|
11
|
+
%w(b c d), %w(a b c d x y z),
|
12
|
+
0, 2, 0, 7)
|
13
|
+
assert_longest_match([1, 2, 2],
|
14
|
+
%w(b c d), %w(a b c d x y z),
|
15
|
+
1, 2, 0, 6)
|
16
|
+
assert_longest_match([0, 0, 0],
|
17
|
+
%w(a b), %w(c),
|
18
|
+
0, 1, 0, 0)
|
19
|
+
assert_longest_match([1, 0, 2],
|
20
|
+
%w(q a b x c d), %w(a b y c d f),
|
21
|
+
0, 5, 0, 5)
|
22
|
+
end
|
23
|
+
|
24
|
+
def _test_matching_blocks
|
25
|
+
assert_matching_blocks([[0, 0, 2],
|
26
|
+
[3, 2, 2],
|
27
|
+
[5, 4, 0]],
|
28
|
+
%w(a b x c d), %w(a b c d))
|
29
|
+
assert_matching_blocks([[1, 0, 2],
|
30
|
+
[4, 3, 2],
|
31
|
+
[6, 6, 0]],
|
32
|
+
%w(q a b x c d), %q(a b y c d f))
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_operations
|
36
|
+
assert_operations([[:delete, 0, 1, 0, 0],
|
37
|
+
[:equal, 1, 3, 0, 2],
|
38
|
+
[:replace, 3, 4, 2, 3],
|
39
|
+
[:equal, 4, 6, 3, 5],
|
40
|
+
[:insert, 6, 6, 5, 6]],
|
41
|
+
%w(q a b x c d), %w(a b y c d f))
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_same_contents
|
45
|
+
assert_ndiff(" aaa", ["aaa"], ["aaa"])
|
46
|
+
assert_ndiff(" aaa\n" \
|
47
|
+
" bbb",
|
48
|
+
["aaa", "bbb"], ["aaa", "bbb"])
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_deleted
|
52
|
+
assert_ndiff(" aaa\n" \
|
53
|
+
" bbb\n" \
|
54
|
+
"- bbb",
|
55
|
+
["aaa", "bbb"], ["aaa"])
|
56
|
+
assert_ndiff(" aaa\n" \
|
57
|
+
" bbb\n" \
|
58
|
+
"- bbb\n" \
|
59
|
+
"- ccc\n" \
|
60
|
+
"- ddd",
|
61
|
+
["aaa", "bbb", "ccc", "ddd"], ["aaa"])
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_format_diff_point
|
65
|
+
assert_format_diff_point(["- \tabcDefghiJkl",
|
66
|
+
"? \t ^ ^ ^",
|
67
|
+
"+ \t\tabcdefGhijkl",
|
68
|
+
"? \t ^ ^ ^"],
|
69
|
+
"\tabcDefghiJkl",
|
70
|
+
"\t\tabcdefGhijkl",
|
71
|
+
" ^ ^ ^ ",
|
72
|
+
"+ ^ ^ ^ ")
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def assert_to_indexes(expected, to)
|
77
|
+
matcher = Test::Diff::SequenceMatcher.new([""], to)
|
78
|
+
assert_equal(expected, matcher.instance_variable_get("@to_indexes"))
|
79
|
+
end
|
80
|
+
|
81
|
+
def assert_longest_match(expected, from, to,
|
82
|
+
from_start, from_end,
|
83
|
+
to_start, to_end)
|
84
|
+
matcher = Test::Diff::SequenceMatcher.new(from, to)
|
85
|
+
assert_equal(expected, matcher.longest_match(from_start, from_end,
|
86
|
+
to_start, to_end))
|
87
|
+
end
|
88
|
+
|
89
|
+
def assert_matching_blocks(expected, from, to)
|
90
|
+
matcher = Test::Diff::SequenceMatcher.new(from, to)
|
91
|
+
assert_equal(expected, matcher.matching_blocks)
|
92
|
+
end
|
93
|
+
|
94
|
+
def assert_operations(expected, from, to)
|
95
|
+
matcher = Test::Diff::SequenceMatcher.new(from, to)
|
96
|
+
assert_equal(expected, matcher.operations)
|
97
|
+
end
|
98
|
+
|
99
|
+
def assert_ndiff(expected, from, to)
|
100
|
+
assert_equal(expected, Test::Diff.ndiff(from, to))
|
101
|
+
end
|
102
|
+
|
103
|
+
def assert_format_diff_point(expected, from_line, to_line, from_tags, to_tags)
|
104
|
+
differ = Test::Diff::Differ.new([""], [""])
|
105
|
+
assert_equal(expected, differ.send(:format_diff_point,
|
106
|
+
from_line, to_line,
|
107
|
+
from_tags, to_tags))
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'test-unit-ext'
|
2
|
+
|
3
|
+
class TestMetadata < Test::Unit::TestCase
|
4
|
+
class TestStack < Test::Unit::TestCase
|
5
|
+
class << self
|
6
|
+
def suite
|
7
|
+
Test::Unit::TestSuite.new(name)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Stack
|
12
|
+
def initialize
|
13
|
+
@data = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def push(data)
|
17
|
+
@data.push(data)
|
18
|
+
end
|
19
|
+
|
20
|
+
def peek
|
21
|
+
@data[-2]
|
22
|
+
end
|
23
|
+
|
24
|
+
def empty?
|
25
|
+
@data.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
@data.size + 11
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup
|
34
|
+
@stack = Stack.new
|
35
|
+
end
|
36
|
+
|
37
|
+
metadata :category, :accessor
|
38
|
+
def test_peek
|
39
|
+
@stack.push(1)
|
40
|
+
@stack.push(2)
|
41
|
+
assert_equal(2, @stack.peek)
|
42
|
+
end
|
43
|
+
|
44
|
+
metadata :bug, 1234
|
45
|
+
def test_bug_1234
|
46
|
+
assert_equal(0, @stack.size)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_no_metadata
|
50
|
+
assert(@stack.empty?)
|
51
|
+
@stack.push(1)
|
52
|
+
assert(!@stack.empty?)
|
53
|
+
assert_equal(1, @stack.size)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_set_metadata
|
58
|
+
test_for_bug_1234 = TestStack.new("test_bug_1234")
|
59
|
+
assert_equal({:bug => 1234}, test_for_bug_1234.metadata)
|
60
|
+
|
61
|
+
test_no_metadata = TestStack.new("test_no_metadata")
|
62
|
+
assert_equal({}, test_no_metadata.metadata)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_show_metadata
|
66
|
+
assert_stack_size_line = search_line('assert_equal(0, @stack.size)')
|
67
|
+
assert_peek_line = search_line('assert_equal(2, @stack.peek)')
|
68
|
+
first_arg_end_line = search_line("\"<11>.\"],")
|
69
|
+
method_name = "test_show_metadata"
|
70
|
+
assert_result(["Failure:\n" \
|
71
|
+
"test_peek(TestMetadata::TestStack)\n" \
|
72
|
+
" category: accessor\n" \
|
73
|
+
"#{__FILE__}:#{assert_peek_line}:in `test_peek'\n" \
|
74
|
+
"#{__FILE__}:#{first_arg_end_line}:in `#{method_name}':\n" \
|
75
|
+
"<2> expected but was\n" \
|
76
|
+
"<1>.",
|
77
|
+
"Failure:\n" \
|
78
|
+
"test_bug_1234(TestMetadata::TestStack)\n" \
|
79
|
+
" bug: 1234\n" \
|
80
|
+
"#{__FILE__}:#{assert_stack_size_line}:in `test_bug_1234'\n" \
|
81
|
+
"#{__FILE__}:#{first_arg_end_line}:in `#{method_name}':\n" \
|
82
|
+
"<0> expected but was\n" \
|
83
|
+
"<11>."],
|
84
|
+
[],
|
85
|
+
["test_peek", "test_bug_1234"])
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_not_show_metadata
|
89
|
+
assert_line = search_line('assert_equal(1, @stack.size')
|
90
|
+
first_arg_end_line = search_line("\"<12>.\"],")
|
91
|
+
method_name = "test_not_show_metadata"
|
92
|
+
assert_result(["Failure:\n" \
|
93
|
+
"test_no_metadata(TestMetadata::TestStack)\n" \
|
94
|
+
"#{__FILE__}:#{assert_line}:in `test_no_metadata'\n" \
|
95
|
+
"#{__FILE__}:#{first_arg_end_line}:in `#{method_name}':\n" \
|
96
|
+
"<1> expected but was\n" \
|
97
|
+
"<12>."],
|
98
|
+
[],
|
99
|
+
["test_no_metadata"])
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def search_line(pattern)
|
104
|
+
if pattern.is_a?(String)
|
105
|
+
pattern = /#{Regexp.escape(pattern)}/
|
106
|
+
end
|
107
|
+
File.open(__FILE__) do |file|
|
108
|
+
while line = file.gets
|
109
|
+
return file.lineno if pattern =~ line
|
110
|
+
end
|
111
|
+
end
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
|
115
|
+
def assert_result(failure_results, error_results, names)
|
116
|
+
tests = names.collect {|name| TestStack.new(name)}
|
117
|
+
result = Test::Unit::TestResult.new
|
118
|
+
mark = /\A#{Regexp.escape(__FILE__)}:#{__LINE__ + 1}/
|
119
|
+
tests.each {|test| test.run(result) {}}
|
120
|
+
failures = result.instance_variable_get("@failures")
|
121
|
+
errors = result.instance_variable_get("@errors")
|
122
|
+
failures.each {|f| f.location.reject! {|l| mark =~ l}}
|
123
|
+
assert_equal([failure_results, error_results],
|
124
|
+
[failures.collect {|failure| failure.long_display},
|
125
|
+
errors.collect {|error| error.long_display}])
|
126
|
+
end
|
127
|
+
end
|