test-unit 1.2.3 → 2.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.
Files changed (60) hide show
  1. data/History.txt +27 -0
  2. data/Manifest.txt +30 -8
  3. data/README.txt +9 -4
  4. data/Rakefile +16 -1
  5. data/bin/testrb +0 -0
  6. data/lib/test/unit/assertions.rb +148 -48
  7. data/lib/test/unit/attribute.rb +125 -0
  8. data/lib/test/unit/autorunner.rb +101 -71
  9. data/lib/test/unit/collector/descendant.rb +23 -0
  10. data/lib/test/unit/collector/dir.rb +1 -1
  11. data/lib/test/unit/collector/load.rb +135 -0
  12. data/lib/test/unit/color.rb +61 -0
  13. data/lib/test/unit/diff.rb +524 -0
  14. data/lib/test/unit/error.rb +70 -2
  15. data/lib/test/unit/exceptionhandler.rb +39 -0
  16. data/lib/test/unit/failure.rb +63 -4
  17. data/lib/test/unit/fixture.rb +185 -0
  18. data/lib/test/unit/notification.rb +125 -0
  19. data/lib/test/unit/omission.rb +143 -0
  20. data/lib/test/unit/pending.rb +146 -0
  21. data/lib/test/unit/priority.rb +146 -0
  22. data/lib/test/unit/runner/console.rb +46 -0
  23. data/lib/test/unit/runner/emacs.rb +8 -0
  24. data/lib/test/unit/testcase.rb +193 -76
  25. data/lib/test/unit/testresult.rb +37 -28
  26. data/lib/test/unit/testsuite.rb +35 -1
  27. data/lib/test/unit/ui/console/outputlevel.rb +14 -0
  28. data/lib/test/unit/ui/console/testrunner.rb +96 -28
  29. data/lib/test/unit/ui/emacs/testrunner.rb +49 -0
  30. data/lib/test/unit/ui/testrunner.rb +20 -0
  31. data/lib/test/unit/ui/testrunnermediator.rb +28 -19
  32. data/lib/test/unit/ui/testrunnerutilities.rb +2 -7
  33. data/lib/test/unit/util/backtracefilter.rb +2 -1
  34. data/lib/test/unit/version.rb +1 -1
  35. data/test/collector/test_descendant.rb +135 -0
  36. data/test/collector/test_load.rb +333 -0
  37. data/test/run-test.rb +13 -0
  38. data/test/test_assertions.rb +221 -56
  39. data/test/test_attribute.rb +86 -0
  40. data/test/test_color.rb +37 -0
  41. data/test/test_diff.rb +477 -0
  42. data/test/test_emacs_runner.rb +60 -0
  43. data/test/test_fixture.rb +275 -0
  44. data/test/test_notification.rb +33 -0
  45. data/test/test_omission.rb +81 -0
  46. data/test/test_pending.rb +70 -0
  47. data/test/test_priority.rb +89 -0
  48. data/test/test_testcase.rb +160 -5
  49. data/test/test_testresult.rb +61 -52
  50. data/test/testunit_test_util.rb +14 -0
  51. data/test/ui/test_testrunmediator.rb +20 -0
  52. metadata +53 -23
  53. data/lib/test/unit/ui/fox/testrunner.rb +0 -268
  54. data/lib/test/unit/ui/gtk/testrunner.rb +0 -416
  55. data/lib/test/unit/ui/gtk2/testrunner.rb +0 -465
  56. data/lib/test/unit/ui/tk/testrunner.rb +0 -260
  57. data/test/runit/test_assert.rb +0 -402
  58. data/test/runit/test_testcase.rb +0 -91
  59. data/test/runit/test_testresult.rb +0 -144
  60. data/test/runit/test_testsuite.rb +0 -49
@@ -1,10 +1,27 @@
1
1
  require 'test/unit'
2
- require 'test/unit/ui/testrunnerutilities'
3
2
  require 'optparse'
4
3
 
5
4
  module Test
6
5
  module Unit
7
6
  class AutoRunner
7
+ RUNNERS = {}
8
+ COLLECTORS = {}
9
+ ADDITIONAL_OPTIONS = []
10
+
11
+ class << self
12
+ def register_runner(id, runner_builder=Proc.new)
13
+ RUNNERS[id] = runner_builder
14
+ end
15
+
16
+ def register_collector(id, collector_builder=Proc.new)
17
+ COLLECTORS[id] = collector_builder
18
+ end
19
+
20
+ def setup_option(option_builder=Proc.new)
21
+ ADDITIONAL_OPTIONS << option_builder
22
+ end
23
+ end
24
+
8
25
  def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
9
26
  r = new(force_standalone || standalone?, &block)
10
27
  r.base = default_dir
@@ -20,69 +37,57 @@ module Test
20
37
  true
21
38
  end
22
39
 
23
- RUNNERS = {
24
- :console => proc do |r|
25
- require 'test/unit/ui/console/testrunner'
26
- Test::Unit::UI::Console::TestRunner
27
- end,
28
- :gtk => proc do |r|
29
- require 'test/unit/ui/gtk/testrunner'
30
- Test::Unit::UI::GTK::TestRunner
31
- end,
32
- :gtk2 => proc do |r|
33
- require 'test/unit/ui/gtk2/testrunner'
34
- Test::Unit::UI::GTK2::TestRunner
35
- end,
36
- :fox => proc do |r|
37
- require 'test/unit/ui/fox/testrunner'
38
- Test::Unit::UI::Fox::TestRunner
39
- end,
40
- :tk => proc do |r|
41
- require 'test/unit/ui/tk/testrunner'
42
- Test::Unit::UI::Tk::TestRunner
43
- end,
44
- }
45
-
46
- OUTPUT_LEVELS = [
47
- [:silent, UI::SILENT],
48
- [:progress, UI::PROGRESS_ONLY],
49
- [:normal, UI::NORMAL],
50
- [:verbose, UI::VERBOSE],
51
- ]
52
-
53
- COLLECTORS = {
54
- :objectspace => proc do |r|
55
- require 'test/unit/collector/objectspace'
56
- c = Collector::ObjectSpace.new
57
- c.filter = r.filters
58
- c.collect($0.sub(/\.rb\Z/, ''))
59
- end,
60
- :dir => proc do |r|
61
- require 'test/unit/collector/dir'
62
- c = Collector::Dir.new
63
- c.filter = r.filters
64
- c.pattern.concat(r.pattern) if(r.pattern)
65
- c.exclude.concat(r.exclude) if(r.exclude)
66
- c.base = r.base
67
- $:.push(r.base) if r.base
68
- c.collect(*(r.to_run.empty? ? ['.'] : r.to_run))
69
- end,
70
- }
71
-
72
- attr_reader :suite
73
- attr_accessor :output_level, :filters, :to_run, :pattern, :exclude, :base, :workdir
40
+ register_collector(:descendant) do |auto_runner|
41
+ require 'test/unit/collector/descendant'
42
+ collector = Collector::Descendant.new
43
+ collector.filter = auto_runner.filters
44
+ collector.collect($0.sub(/\.rb\Z/, ''))
45
+ end
46
+
47
+ register_collector(:load) do |auto_runner|
48
+ require 'test/unit/collector/load'
49
+ collector = Collector::Load.new
50
+ collector.patterns.concat(auto_runner.pattern) if auto_runner.pattern
51
+ collector.excludes.concat(auto_runner.exclude) if auto_runner.exclude
52
+ collector.base = auto_runner.base
53
+ collector.filter = auto_runner.filters
54
+ collector.collect(*auto_runner.to_run)
55
+ end
56
+
57
+ # deprecated
58
+ register_collector(:object_space) do |auto_runner|
59
+ require 'test/unit/collector/objectspace'
60
+ c = Collector::ObjectSpace.new
61
+ c.filter = auto_runner.filters
62
+ c.collect($0.sub(/\.rb\Z/, ''))
63
+ end
64
+
65
+ # deprecated
66
+ register_collector(:dir) do |auto_runner|
67
+ require 'test/unit/collector/dir'
68
+ c = Collector::Dir.new
69
+ c.filter = auto_runner.filters
70
+ c.pattern.concat(auto_runner.pattern) if auto_runner.pattern
71
+ c.exclude.concat(auto_runner.exclude) if auto_runner.exclude
72
+ c.base = auto_runner.base
73
+ $:.push(auto_runner.base) if auto_runner.base
74
+ c.collect(*(auto_runner.to_run.empty? ? ['.'] : auto_runner.to_run))
75
+ end
76
+
77
+ attr_reader :suite, :runner_options
78
+ attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
74
79
  attr_writer :runner, :collector
75
80
 
76
81
  def initialize(standalone)
77
82
  Unit.run = true
78
83
  @standalone = standalone
79
- @runner = RUNNERS[:console]
80
- @collector = COLLECTORS[(standalone ? :dir : :objectspace)]
84
+ @runner = default_runner
85
+ @collector = default_collector
81
86
  @filters = []
82
87
  @to_run = []
83
- @output_level = UI::NORMAL
88
+ @runner_options = {}
84
89
  @workdir = nil
85
- yield(self) if(block_given?)
90
+ yield(self) if block_given?
86
91
  end
87
92
 
88
93
  def process_args(args = ARGV)
@@ -163,15 +168,25 @@ module Test
163
168
  end
164
169
  end
165
170
 
171
+ priority_filter = Proc.new do |test|
172
+ Priority::Checker.new(test).need_to_run? or nil
173
+ end
174
+ o.on("--[no-]priority-mode",
175
+ "Runs some tests based on their priority.") do |priority_mode|
176
+ if priority_mode
177
+ @filters |= [priority_filter]
178
+ else
179
+ @filters -= [priority_filter]
180
+ end
181
+ end
182
+
166
183
  o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
167
184
  "Appends directory list to $LOAD_PATH.") do |dirs|
168
185
  $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
169
186
  end
170
187
 
171
- o.on('-v', '--verbose=[LEVEL]', OUTPUT_LEVELS,
172
- "Set the output level (default is verbose).",
173
- "(" + keyword_display(OUTPUT_LEVELS) + ")") do |l|
174
- @output_level = l || UI::VERBOSE
188
+ ADDITIONAL_OPTIONS.each do |option_builder|
189
+ option_builder.call(self, o)
175
190
  end
176
191
 
177
192
  o.on('--',
@@ -189,14 +204,11 @@ module Test
189
204
  @runner = RUNNERS[:console]
190
205
  end
191
206
 
192
- o.on_tail('--gtk', 'GTK runner (use --runner).') do
193
- warn("Deprecated option (--gtk).")
194
- @runner = RUNNERS[:gtk]
195
- end
196
-
197
- o.on_tail('--fox', 'Fox runner (use --runner).') do
198
- warn("Deprecated option (--fox).")
199
- @runner = RUNNERS[:fox]
207
+ if RUNNERS[:fox]
208
+ o.on_tail('--fox', 'Fox runner (use --runner).') do
209
+ warn("Deprecated option (--fox).")
210
+ @runner = RUNNERS[:fox]
211
+ end
200
212
  end
201
213
 
202
214
  o.on_tail
@@ -210,11 +222,29 @@ module Test
210
222
  end
211
223
 
212
224
  def run
213
- @suite = @collector[self]
214
- result = @runner[self] or return false
225
+ suite = @collector[self]
226
+ return false if suite.nil?
227
+ runner = @runner[self]
228
+ return false if runner.nil?
215
229
  Dir.chdir(@workdir) if @workdir
216
- result.run(@suite, @output_level).passed?
230
+ runner.run(suite, @runner_options).passed?
231
+ end
232
+
233
+ private
234
+ def default_runner
235
+ if ENV["EMACS"] == "t"
236
+ RUNNERS[:emacs]
237
+ else
238
+ RUNNERS[:console]
239
+ end
240
+ end
241
+
242
+ def default_collector
243
+ COLLECTORS[@standalone ? :load : :descendant]
217
244
  end
218
245
  end
219
246
  end
220
247
  end
248
+
249
+ require 'test/unit/runner/console'
250
+ require 'test/unit/runner/emacs'
@@ -0,0 +1,23 @@
1
+ require 'test/unit/collector'
2
+
3
+ module Test
4
+ module Unit
5
+ module Collector
6
+ class Descendant
7
+ include Collector
8
+
9
+ NAME = 'collected from the subclasses of TestCase'
10
+
11
+ def collect(name=NAME)
12
+ suite = TestSuite.new(name)
13
+ sub_suites = []
14
+ TestCase::DESCENDANTS.each do |descendant_test_case|
15
+ add_suite(sub_suites, descendant_test_case.suite)
16
+ end
17
+ sort(sub_suites).each {|s| suite << s}
18
+ suite
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -60,7 +60,7 @@ module Test
60
60
  next if(e == '.' || e == '..')
61
61
  e_name = dir_name ? @file.join(dir_name, e) : e
62
62
  if @file.directory?(realdir(e_name))
63
- next if /\ACVS\z/ =~ e
63
+ next if /\A(?:CVS|\.svn)\z/ =~ e
64
64
  sub_suite = recursive_collect(e_name, already_gathered)
65
65
  sub_suites << sub_suite unless(sub_suite.empty?)
66
66
  else
@@ -0,0 +1,135 @@
1
+ require 'pathname'
2
+
3
+ require 'test/unit/testsuite'
4
+ require 'test/unit/collector'
5
+
6
+ module Test
7
+ module Unit
8
+ module Collector
9
+ class Load
10
+ include Collector
11
+
12
+ attr_reader :patterns, :excludes, :base
13
+
14
+ def initialize
15
+ super
16
+ @system_excludes = [/~\z/, /\A\.\#/]
17
+ @system_directory_excludes = [/\A(?:CVS|\.svn)\z/]
18
+ @patterns = [/\Atest_.+\.rb\z/m]
19
+ @excludes = []
20
+ @base = nil
21
+ end
22
+
23
+ def base=(base)
24
+ base = Pathname(base) unless base.nil?
25
+ @base = base
26
+ end
27
+
28
+ def collect(*froms)
29
+ add_load_path(@base) do
30
+ froms = ["."] if froms.empty?
31
+ test_suites = froms.collect do |from|
32
+ test_suite = collect_recursive(from, find_test_cases)
33
+ test_suite = nil if test_suite.tests.empty?
34
+ test_suite
35
+ end.compact
36
+
37
+ if test_suites.size > 1
38
+ test_suite = TestSuite.new("[#{froms.join(', ')}]")
39
+ sort(test_suites).each do |sub_test_suite|
40
+ test_suite << sub_test_suite
41
+ end
42
+ test_suite
43
+ else
44
+ test_suites.first
45
+ end
46
+ end
47
+ end
48
+
49
+ def find_test_cases(ignore=[])
50
+ test_cases = []
51
+ TestCase::DESCENDANTS.each do |test_case|
52
+ test_cases << test_case unless ignore.include?(test_case)
53
+ end
54
+ ignore.concat(test_cases)
55
+ test_cases
56
+ end
57
+
58
+ private
59
+ def collect_recursive(name, already_gathered)
60
+ sub_test_suites = []
61
+
62
+ path = resolve_path(name)
63
+ if path.directory?
64
+ directories, files = path.children.partition do |child|
65
+ child.directory?
66
+ end
67
+
68
+ files.each do |child|
69
+ next if excluded_file?(child.basename.to_s)
70
+ collect_file(child, sub_test_suites, already_gathered)
71
+ end
72
+
73
+ directories.each do |child|
74
+ next if excluded_directory?(child.basename.to_s)
75
+ sub_test_suite = collect_recursive(child, already_gathered)
76
+ sub_test_suites << sub_test_suite unless sub_test_suite.empty?
77
+ end
78
+ else
79
+ collect_file(path, sub_test_suites, already_gathered)
80
+ end
81
+
82
+ test_suite = TestSuite.new(path.basename.to_s)
83
+ sort(sub_test_suites).each do |sub_test_suite|
84
+ test_suite << sub_test_suite
85
+ end
86
+ test_suite
87
+ end
88
+
89
+ def collect_file(path, test_suites, already_gathered)
90
+ add_load_path(path.expand_path.dirname) do
91
+ require(path.to_s)
92
+ find_test_cases(already_gathered).each do |test_case|
93
+ add_suite(test_suites, test_case.suite)
94
+ end
95
+ end
96
+ end
97
+
98
+ def resolve_path(path)
99
+ if @base
100
+ @base + path
101
+ else
102
+ Pathname(path)
103
+ end
104
+ end
105
+
106
+ def add_load_path(path)
107
+ $LOAD_PATH.push(path.to_s) if path
108
+ yield
109
+ ensure
110
+ $LOAD_PATH.delete_at($LOAD_PATH.rindex(path.to_s)) if path
111
+ end
112
+
113
+ def excluded_directory?(base)
114
+ @system_directory_excludes.any? {|pattern| pattern =~ base}
115
+ end
116
+
117
+ def excluded_file?(base)
118
+ return true if @system_excludes.any? {|pattern| pattern =~ base}
119
+
120
+ patterns = @patterns || []
121
+ unless patterns.empty?
122
+ return true unless patterns.any? {|pattern| pattern =~ base}
123
+ end
124
+
125
+ excludes = @excludes || []
126
+ unless excludes.empty?
127
+ return true if excludes.any? {|pattern| pattern =~ base}
128
+ end
129
+
130
+ false
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,61 @@
1
+ module Test
2
+ module Unit
3
+ class Color
4
+ NAMES = ["black", "red", "green", "yellow",
5
+ "blue", "magenta", "cyan", "white"]
6
+ def initialize(name, options={})
7
+ @name = name
8
+ @foreground = options[:foreground]
9
+ @foreground = true if @foreground.nil?
10
+ @intensity = options[:intensity]
11
+ @bold = options[:bold]
12
+ @italic = options[:italic]
13
+ @underline = options[:underline]
14
+ end
15
+
16
+ def sequence
17
+ sequence = []
18
+ if @name == "none"
19
+ elsif @name == "reset"
20
+ sequence << "0"
21
+ else
22
+ foreground_parameter = @foreground ? 3 : 4
23
+ foreground_parameter += 6 if @intensity
24
+ sequence << "#{foreground_parameter}#{NAMES.index(@name)}"
25
+ end
26
+ sequence << "1" if @bold
27
+ sequence << "3" if @italic
28
+ sequence << "4" if @underline
29
+ sequence
30
+ end
31
+
32
+ def escape_sequence
33
+ "\e[#{sequence.join(';')}m"
34
+ end
35
+
36
+ def +(other)
37
+ MixColor.new([self, other])
38
+ end
39
+ end
40
+
41
+ class MixColor
42
+ def initialize(colors)
43
+ @colors = colors
44
+ end
45
+
46
+ def sequence
47
+ @colors.inject([]) do |result, color|
48
+ result + color.sequence
49
+ end
50
+ end
51
+
52
+ def escape_sequence
53
+ "\e[#{sequence.join(';')}m"
54
+ end
55
+
56
+ def +(other)
57
+ self.class.new([self, other])
58
+ end
59
+ end
60
+ end
61
+ end