test-unit 1.2.3 → 2.0.0

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