test-unit 3.1.5 → 3.6.1

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 (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