test-unit 3.1.5 → 3.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +5 -5
  2. data/BSDL +24 -0
  3. data/COPYING +41 -41
  4. data/README.md +24 -17
  5. data/Rakefile +21 -24
  6. data/doc/text/getting-started.md +246 -0
  7. data/doc/text/news.md +797 -56
  8. data/lib/test/unit/assertion-failed-error.rb +35 -0
  9. data/lib/test/unit/assertions.rb +542 -220
  10. data/lib/test/unit/attribute.rb +78 -4
  11. data/lib/test/unit/auto-runner-loader.rb +17 -0
  12. data/lib/test/unit/autorunner.rb +175 -78
  13. data/lib/test/unit/code-snippet-fetcher.rb +7 -7
  14. data/lib/test/unit/collector/descendant.rb +1 -0
  15. data/lib/test/unit/collector/dir.rb +4 -2
  16. data/lib/test/unit/collector/load.rb +25 -15
  17. data/lib/test/unit/collector/objectspace.rb +1 -0
  18. data/lib/test/unit/collector.rb +31 -0
  19. data/lib/test/unit/color-scheme.rb +29 -2
  20. data/lib/test/unit/data-sets.rb +127 -0
  21. data/lib/test/unit/data.rb +121 -12
  22. data/lib/test/unit/diff.rb +10 -11
  23. data/lib/test/unit/fixture.rb +77 -27
  24. data/lib/test/unit/notification.rb +9 -7
  25. data/lib/test/unit/omission.rb +34 -31
  26. data/lib/test/unit/pending.rb +12 -11
  27. data/lib/test/unit/priority.rb +7 -5
  28. data/lib/test/unit/runner/console.rb +20 -1
  29. data/lib/test/unit/test-suite-creator.rb +30 -9
  30. data/lib/test/unit/testcase.rb +349 -196
  31. data/lib/test/unit/testresult.rb +7 -0
  32. data/lib/test/unit/testsuite.rb +1 -1
  33. data/lib/test/unit/ui/console/testrunner.rb +171 -60
  34. data/lib/test/unit/ui/emacs/testrunner.rb +5 -5
  35. data/lib/test/unit/ui/testrunnermediator.rb +9 -7
  36. data/lib/test/unit/util/backtracefilter.rb +17 -5
  37. data/lib/test/unit/util/memory-usage.rb +47 -0
  38. data/lib/test/unit/util/observable.rb +2 -2
  39. data/lib/test/unit/util/output.rb +5 -4
  40. data/lib/test/unit/util/procwrapper.rb +4 -4
  41. data/lib/test/unit/version.rb +1 -1
  42. data/lib/test/unit/warning.rb +3 -0
  43. data/lib/test/unit.rb +177 -161
  44. data/lib/test-unit.rb +2 -17
  45. metadata +20 -94
  46. data/GPL +0 -339
  47. data/LGPL +0 -502
  48. data/test/collector/test-descendant.rb +0 -178
  49. data/test/collector/test-load.rb +0 -442
  50. data/test/collector/test_dir.rb +0 -406
  51. data/test/collector/test_objectspace.rb +0 -100
  52. data/test/fixtures/header-label.csv +0 -3
  53. data/test/fixtures/header-label.tsv +0 -3
  54. data/test/fixtures/header.csv +0 -3
  55. data/test/fixtures/header.tsv +0 -3
  56. data/test/fixtures/no-header.csv +0 -2
  57. data/test/fixtures/no-header.tsv +0 -2
  58. data/test/fixtures/plus.csv +0 -3
  59. data/test/run-test.rb +0 -22
  60. data/test/test-assertions.rb +0 -2157
  61. data/test/test-attribute-matcher.rb +0 -38
  62. data/test/test-attribute.rb +0 -123
  63. data/test/test-code-snippet.rb +0 -37
  64. data/test/test-color-scheme.rb +0 -82
  65. data/test/test-color.rb +0 -47
  66. data/test/test-data.rb +0 -281
  67. data/test/test-diff.rb +0 -518
  68. data/test/test-emacs-runner.rb +0 -60
  69. data/test/test-error.rb +0 -26
  70. data/test/test-failure.rb +0 -33
  71. data/test/test-fault-location-detector.rb +0 -163
  72. data/test/test-fixture.rb +0 -659
  73. data/test/test-notification.rb +0 -33
  74. data/test/test-omission.rb +0 -81
  75. data/test/test-pending.rb +0 -70
  76. data/test/test-priority.rb +0 -173
  77. data/test/test-test-case.rb +0 -1171
  78. data/test/test-test-result.rb +0 -113
  79. data/test/test-test-suite-creator.rb +0 -97
  80. data/test/test-test-suite.rb +0 -150
  81. data/test/testunit-test-util.rb +0 -31
  82. data/test/ui/test_testrunmediator.rb +0 -20
  83. data/test/util/test-method-owner-finder.rb +0 -38
  84. data/test/util/test-output.rb +0 -11
  85. data/test/util/test_backtracefilter.rb +0 -41
  86. data/test/util/test_observable.rb +0 -102
  87. data/test/util/test_procwrapper.rb +0 -36
@@ -24,9 +24,11 @@ module Test
24
24
  attr_reader :teardown
25
25
  def initialize(test_case)
26
26
  @test_case = test_case
27
- @setup = HookPoint.new(:after => :append)
28
- @cleanup = HookPoint.new(:before => :prepend)
29
- @teardown = HookPoint.new(:before => :prepend)
27
+ @setup = HookPoint.new(@test_case, :setup, :after => :append)
28
+ @cleanup = HookPoint.new(@test_case, :cleanup, :before => :prepend)
29
+ @teardown = HookPoint.new(@test_case, :teardown, :before => :prepend)
30
+ @cached_before_callbacks = {}
31
+ @cached_after_callbacks = {}
30
32
  end
31
33
 
32
34
  def [](type)
@@ -41,6 +43,19 @@ module Test
41
43
  end
42
44
 
43
45
  def before_callbacks(type)
46
+ @cached_before_callbacks[type] ||= collect_before_callbacks(type)
47
+ end
48
+
49
+ def after_callbacks(type)
50
+ @cached_after_callbacks[type] ||= collect_after_callbacks(type)
51
+ end
52
+
53
+ private
54
+ def target_test_cases
55
+ @cached_target_test_cases ||= collect_target_test_cases
56
+ end
57
+
58
+ def collect_before_callbacks(type)
44
59
  prepend_callbacks = []
45
60
  append_callbacks = []
46
61
  target_test_cases.each do |ancestor|
@@ -51,7 +66,7 @@ module Test
51
66
  merge_callbacks(prepend_callbacks, append_callbacks)
52
67
  end
53
68
 
54
- def after_callbacks(type)
69
+ def collect_after_callbacks(type)
55
70
  prepend_callbacks = []
56
71
  append_callbacks = []
57
72
  target_test_cases.each do |ancestor|
@@ -62,11 +77,6 @@ module Test
62
77
  merge_callbacks(prepend_callbacks, append_callbacks)
63
78
  end
64
79
 
65
- private
66
- def target_test_cases
67
- @cached_target_test_cases ||= collect_target_test_cases
68
- end
69
-
70
80
  def collect_target_test_cases
71
81
  ancestors = @test_case.ancestors
72
82
  base_index = ancestors.index(::Test::Unit::Fixture)
@@ -89,8 +99,11 @@ module Test
89
99
  end
90
100
 
91
101
  class HookPoint
92
- def initialize(default_options)
102
+ def initialize(test_case, type, default_options)
103
+ @test_case = test_case
104
+ @type = type
93
105
  @default_options = default_options
106
+ @callbacks = {}
94
107
  @before_prepend_callbacks = []
95
108
  @before_append_callbacks = []
96
109
  @after_prepend_callbacks = []
@@ -112,11 +125,32 @@ module Test
112
125
  end
113
126
  before_how = options[:before]
114
127
  after_how = options[:after]
115
- add_callback(method_name_or_callback, before_how, after_how)
128
+ if method_name_or_callback.respond_to?(:call)
129
+ callback = method_name_or_callback
130
+ method_name = callback_method_name(callback)
131
+ @test_case.attribute(:source_location,
132
+ callback.source_location,
133
+ method_name)
134
+ # For Ruby 2.6 or earlier. callback may be GC-ed. If
135
+ # callback is GC-ed, callback_method_name may be
136
+ # duplicated because callback_method_name uses callback.object_id.
137
+ # See also: https://github.com/test-unit/test-unit/issues/179
138
+ @callbacks[callback] = true
139
+ @test_case.__send__(:define_method, method_name, &callback)
140
+ else
141
+ method_name = method_name_or_callback
142
+ end
143
+ add_callback(method_name, before_how, after_how)
116
144
  end
117
145
 
118
146
  def unregister(method_name_or_callback)
119
- @unregistered_callbacks << method_name_or_callback
147
+ if method_name_or_callback.respond_to?(:call)
148
+ callback = method_name_or_callback
149
+ method_name = callback_method_name(callback)
150
+ else
151
+ method_name = method_name_or_callback
152
+ end
153
+ @unregistered_callbacks << method_name
120
154
  end
121
155
 
122
156
  def before_prepend_callbacks
@@ -145,6 +179,10 @@ module Test
145
179
  [:prepend, :append].include?(options[key])
146
180
  end
147
181
 
182
+ def callback_method_name(callback)
183
+ "#{@type}_#{callback.object_id}"
184
+ end
185
+
148
186
  def add_callback(method_name_or_callback, before_how, after_how)
149
187
  case before_how
150
188
  when :prepend
@@ -208,38 +246,50 @@ module Test
208
246
  end
209
247
 
210
248
  private
211
- def run_fixture(type, options={})
212
- [
249
+ def run_fixture(type, options={}, &block)
250
+ fixtures = [
213
251
  self.class.fixture.before_callbacks(type),
214
252
  type,
215
253
  self.class.fixture.after_callbacks(type),
216
- ].flatten.each do |method_name_or_callback|
217
- run_fixture_callback(method_name_or_callback, options)
254
+ ].flatten
255
+ if block
256
+ runner = create_fixtures_runner(fixtures, options, &block)
257
+ runner.call
258
+ else
259
+ fixtures.each do |method_name|
260
+ run_fixture_callback(method_name, options)
261
+ end
218
262
  end
219
263
  end
220
264
 
221
- def run_fixture_callback(method_name_or_callback, options)
222
- if method_name_or_callback.respond_to?(:call)
223
- callback = lambda do
224
- instance_eval(&method_name_or_callback)
225
- end
265
+ def create_fixtures_runner(fixtures, options, &block)
266
+ if fixtures.empty?
267
+ block
226
268
  else
227
- return unless respond_to?(method_name_or_callback, true)
228
- callback = lambda do
229
- __send__(method_name_or_callback)
269
+ last_fixture = fixtures.pop
270
+ create_fixtures_runner(fixtures, options) do
271
+ block_is_called = false
272
+ run_fixture_callback(last_fixture, options) do
273
+ block_is_called = true
274
+ block.call
275
+ end
276
+ block.call unless block_is_called
230
277
  end
231
278
  end
279
+ end
232
280
 
281
+ def run_fixture_callback(method_name, options, &block)
282
+ return unless respond_to?(method_name, true)
233
283
  begin
234
- callback.call
284
+ __send__(method_name, &block)
235
285
  rescue Exception
236
286
  raise unless options[:handle_exception]
237
287
  raise unless handle_exception($!)
238
288
  end
239
289
  end
240
290
 
241
- def run_setup
242
- run_fixture(:setup)
291
+ def run_setup(&block)
292
+ run_fixture(:setup, &block)
243
293
  end
244
294
 
245
295
  def run_cleanup
@@ -65,15 +65,17 @@ module Test
65
65
  # Notify some information.
66
66
  #
67
67
  # Example:
68
- # def test_notification
69
- # notify("I'm here!")
70
- # # Reached here
71
- # notify("Special!") if special_case?
72
- # # Reached here too
73
- # end
68
+ #
69
+ # def test_notification
70
+ # notify("I'm here!")
71
+ # # Reached here
72
+ # notify("Special!") if special_case?
73
+ # # Reached here too
74
+ # end
74
75
  #
75
76
  # options:
76
- # :backtrace override backtrace.
77
+ #
78
+ # :backtrace override backtrace.
77
79
  def notify(message, options={}, &block)
78
80
  backtrace = filter_backtrace(options[:backtrace] || caller)
79
81
  notification = Notification.new(name, backtrace, message,
@@ -65,17 +65,18 @@ module Test
65
65
  # Omit the test or part of the test.
66
66
  #
67
67
  # Example:
68
- # def test_omission
69
- # omit
70
- # # Not reached here
71
- # end
72
68
  #
73
- # def test_omission_with_here
74
- # omit do
75
- # # Not ran here
69
+ # def test_omission
70
+ # omit
71
+ # # Not reached here
72
+ # end
73
+ #
74
+ # def test_omission_with_here
75
+ # omit do
76
+ # # Not ran here
77
+ # end
78
+ # # Reached here
76
79
  # end
77
- # # Reached here
78
- # end
79
80
  def omit(message=nil, &block)
80
81
  message ||= "omitted."
81
82
  if block_given?
@@ -91,20 +92,21 @@ module Test
91
92
  # true.
92
93
  #
93
94
  # Example:
94
- # def test_omission
95
- # omit_if("".empty?)
96
- # # Not reached here
97
- # end
98
95
  #
99
- # def test_omission_with_here
100
- # omit_if(true) do
101
- # # Not ran here
96
+ # def test_omission
97
+ # omit_if("".empty?)
98
+ # # Not reached here
102
99
  # end
103
- # omit_if(false) do
104
- # # Reached here
100
+ #
101
+ # def test_omission_with_here
102
+ # omit_if(true) do
103
+ # # Not ran here
104
+ # end
105
+ # omit_if(false) do
106
+ # # Reached here
107
+ # end
108
+ # # Reached here too
105
109
  # end
106
- # # Reached here too
107
- # end
108
110
  def omit_if(condition, *args, &block)
109
111
  if condition
110
112
  omit(*args, &block)
@@ -117,20 +119,21 @@ module Test
117
119
  # not true.
118
120
  #
119
121
  # Example:
120
- # def test_omission
121
- # omit_unless("string".empty?)
122
- # # Not reached here
123
- # end
124
122
  #
125
- # def test_omission_with_here
126
- # omit_unless(true) do
127
- # # Reached here
123
+ # def test_omission
124
+ # omit_unless("string".empty?)
125
+ # # Not reached here
128
126
  # end
129
- # omit_unless(false) do
130
- # # Not ran here
127
+ #
128
+ # def test_omission_with_here
129
+ # omit_unless(true) do
130
+ # # Reached here
131
+ # end
132
+ # omit_unless(false) do
133
+ # # Not ran here
134
+ # end
135
+ # # Reached here too
131
136
  # end
132
- # # Reached here too
133
- # end
134
137
  def omit_unless(condition, *args, &block)
135
138
  if condition
136
139
  block.call if block
@@ -65,19 +65,20 @@ module Test
65
65
  # Marks the test or part of the test is pending.
66
66
  #
67
67
  # Example:
68
- # def test_pending
69
- # pend
70
- # # Not reached here
71
- # end
72
68
  #
73
- # def test_pending_with_here
74
- # pend do
75
- # # Ran here
76
- # # Fails if the block doesn't raise any error.
77
- # # Because it means the block is passed unexpectedly.
69
+ # def test_pending
70
+ # pend
71
+ # # Not reached here
72
+ # end
73
+ #
74
+ # def test_pending_with_here
75
+ # pend do
76
+ # # Ran here
77
+ # # Fails if the block doesn't raise any error.
78
+ # # Because it means the block is passed unexpectedly.
79
+ # end
80
+ # # Reached here
78
81
  # end
79
- # # Reached here
80
- # end
81
82
  def pend(message=nil, &block)
82
83
  message ||= "pended."
83
84
  if block_given?
@@ -1,5 +1,3 @@
1
- require "fileutils"
2
-
3
1
  module Test
4
2
  module Unit
5
3
  module Priority
@@ -148,15 +146,19 @@ module Test
148
146
  end
149
147
 
150
148
  def escape_class_name(class_name)
151
- class_name.gsub(/(?:[: \\\/])/, "_")
149
+ escape_name(class_name)
152
150
  end
153
151
 
154
152
  def escaped_method_name
155
- @test.method_name.to_s.gsub(/(?:[: ]|[!?=]$)/) do |matched|
153
+ escape_name(@test.method_name.to_s)
154
+ end
155
+
156
+ def escape_name(name)
157
+ name.gsub(/(?:[: \/!?=])/) do |matched|
156
158
  case matched
157
159
  when ":"
158
160
  "_colon_"
159
- when " "
161
+ when " ", "/"
160
162
  "_"
161
163
  when "!"
162
164
  ".destructive"
@@ -1,3 +1,5 @@
1
+ # Copyright (C) 2008-2023 Sutou Kouhei <kou@clear-code.com>
2
+
1
3
  module Test
2
4
  module Unit
3
5
  AutoRunner.register_runner(:console) do |auto_runner|
@@ -16,7 +18,7 @@ module Test
16
18
  ["verbose", UI::Console::OutputLevel::VERBOSE],
17
19
  ]
18
20
  opts.on('-v', '--verbose=[LEVEL]', output_levels,
19
- "Set the output level (default is verbose).",
21
+ "Set the output level (default is normal).",
20
22
  "(#{auto_runner.keyword_display(output_levels)})") do |level|
21
23
  level ||= output_levels.assoc("verbose")[1]
22
24
  auto_runner.runner_options[:output_level] = level
@@ -49,11 +51,28 @@ module Test
49
51
  auto_runner.runner_options[:progress_row_max] = max
50
52
  end
51
53
 
54
+ progress_styles = [
55
+ ["inplace", :inplace],
56
+ ["mark", :mark],
57
+ ["fault-only", :fault_only],
58
+ ]
59
+ opts.on("--progress-style=STYLE", progress_styles,
60
+ "Uses STYLE as progress style",
61
+ "(#{auto_runner.keyword_display(progress_styles)}") do |style|
62
+ auto_runner.runner_options[:progress_style] = style
63
+ end
64
+
52
65
  opts.on("--no-show-detail-immediately",
53
66
  "Shows not passed test details immediately.",
54
67
  "(default is yes)") do |boolean|
55
68
  auto_runner.runner_options[:show_detail_immediately] = boolean
56
69
  end
70
+
71
+ opts.on("--[no-]reverse-output",
72
+ "Shows fault details in reverse.",
73
+ "(default is yes for tty output, no otherwise)") do |boolean|
74
+ auto_runner.runner_options[:reverse_output] = boolean
75
+ end
57
76
  end
58
77
  end
59
78
  end
@@ -5,9 +5,18 @@
5
5
  # * Copyright (c) 2011 Kouhei Sutou <tt><kou@clear-code.com></tt>
6
6
  # License:: Ruby license.
7
7
 
8
+ require "test/unit/data-sets"
9
+
8
10
  module Test
9
11
  module Unit
10
12
  class TestSuiteCreator # :nodoc:
13
+ class << self
14
+ def test_method?(test_case, method_name)
15
+ /\Atest./ =~ method_name.to_s or
16
+ test_case.find_attribute(method_name, :test)
17
+ end
18
+ end
19
+
11
20
  def initialize(test_case)
12
21
  @test_case = test_case
13
22
  end
@@ -15,14 +24,11 @@ module Test
15
24
  def create
16
25
  suite = TestSuite.new(@test_case.name, @test_case)
17
26
  collect_test_names.each do |test_name|
18
- data_sets = @test_case.find_attribute(test_name, :data)
27
+ data_sets = extract_data_sets(test_name)
19
28
  if data_sets
20
- data_sets.each do |data_set|
21
- data_set = data_set.call if data_set.respond_to?(:call)
22
- data_set.each do |label, data|
23
- append_test(suite, test_name) do |test|
24
- test.assign_test_data(label, data)
25
- end
29
+ data_sets.each do |label, data|
30
+ append_test(suite, test_name) do |test|
31
+ test.assign_test_data(label, data)
26
32
  end
27
33
  end
28
34
  else
@@ -34,6 +40,22 @@ module Test
34
40
  end
35
41
 
36
42
  private
43
+ def extract_data_sets(test_name)
44
+ data_sets = @test_case.find_attribute(test_name,
45
+ :data,
46
+ :recursive => false)
47
+ data_method_name = "data_#{test_name}"
48
+ test = @test_case.new(test_name)
49
+ if test.respond_to?(data_method_name)
50
+ data_method = test.method(data_method_name)
51
+ if data_method.arity <= 0
52
+ data_sets ||= DataSets.new
53
+ data_sets << data_method
54
+ end
55
+ end
56
+ data_sets
57
+ end
58
+
37
59
  def append_test(suite, test_name)
38
60
  test = @test_case.new(test_name)
39
61
  yield(test) if block_given?
@@ -47,8 +69,7 @@ module Test
47
69
  methods |= @test_case.public_instance_methods(false)
48
70
  method_names = methods.collect(&:to_s)
49
71
  test_names = method_names.find_all do |method_name|
50
- /\Atest./ =~ method_name or
51
- @test_case.find_attribute(method_name, :test)
72
+ self.class.test_method?(@test_case, method_name)
52
73
  end
53
74
  __send__("sort_test_names_in_#{@test_case.test_order}_order", test_names)
54
75
  end