test-unit 3.2.0 → 3.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +5 -5
  2. data/COPYING +4 -1
  3. data/README.md +11 -11
  4. data/Rakefile +10 -1
  5. data/doc/text/getting-started.md +246 -0
  6. data/doc/text/news.md +372 -1
  7. data/lib/test/unit.rb +171 -157
  8. data/lib/test/unit/assertions.rb +187 -149
  9. data/lib/test/unit/attribute.rb +71 -2
  10. data/lib/test/unit/autorunner.rb +65 -32
  11. data/lib/test/unit/code-snippet-fetcher.rb +7 -7
  12. data/lib/test/unit/collector/load.rb +8 -13
  13. data/lib/test/unit/data-sets.rb +116 -0
  14. data/lib/test/unit/data.rb +121 -12
  15. data/lib/test/unit/diff.rb +11 -11
  16. data/lib/test/unit/fixture.rb +3 -0
  17. data/lib/test/unit/notification.rb +9 -7
  18. data/lib/test/unit/omission.rb +34 -31
  19. data/lib/test/unit/pending.rb +12 -11
  20. data/lib/test/unit/priority.rb +7 -3
  21. data/lib/test/unit/runner/console.rb +25 -0
  22. data/lib/test/unit/test-suite-creator.rb +22 -8
  23. data/lib/test/unit/testcase.rb +270 -182
  24. data/lib/test/unit/ui/console/testrunner.rb +90 -35
  25. data/lib/test/unit/ui/emacs/testrunner.rb +5 -5
  26. data/lib/test/unit/util/observable.rb +2 -2
  27. data/lib/test/unit/util/output.rb +5 -4
  28. data/lib/test/unit/util/procwrapper.rb +4 -4
  29. data/lib/test/unit/version.rb +1 -1
  30. data/test/collector/test-descendant.rb +4 -0
  31. data/test/collector/test-load.rb +35 -2
  32. data/test/collector/test_dir.rb +5 -4
  33. data/test/collector/test_objectspace.rb +7 -5
  34. data/test/test-assertions.rb +128 -101
  35. data/test/test-code-snippet.rb +42 -0
  36. data/test/test-data.rb +195 -79
  37. data/test/test-priority.rb +19 -8
  38. data/test/test-test-case.rb +111 -3
  39. data/test/test-test-suite.rb +1 -0
  40. data/test/testunit-test-util.rb +2 -0
  41. metadata +38 -37
@@ -1,3 +1,5 @@
1
+ require "test/unit/data-sets"
2
+
1
3
  module Test
2
4
  module Unit
3
5
  module Data
@@ -12,9 +14,12 @@ module Test
12
14
  #
13
15
  # Define test data in the test code.
14
16
  #
15
- # @overload data(label, data)
17
+ # @overload data(label, data, options={})
16
18
  # @param [String] label specify test case name.
17
19
  # @param data specify test data.
20
+ # @param [Hash] options specify options.
21
+ # @option options [Boolean] :keep whether or not to use
22
+ # this data in the following test methods
18
23
  #
19
24
  # @example data(label, data)
20
25
  # data("empty string", [true, ""])
@@ -24,9 +29,39 @@ module Test
24
29
  # assert_equal(expected, target.empty?)
25
30
  # end
26
31
  #
27
- # @overload data(data_set)
32
+ # @overload data(variable, patterns, options={})
33
+ # @param [Symbol] variable specify test pattern variable name.
34
+ # @param [Array] patterns specify test patterns for the variable.
35
+ # @param [Hash] options specify options.
36
+ # @option options [Boolean] :keep whether or not to use
37
+ # this data in the following test methods
38
+ # @option options [Object] :group the test pattern group.
39
+ # Test matrix is generated for each test pattern group separately.
40
+ #
41
+ # @example data(variable, patterns)
42
+ # data(:x, [1, 2, 3])
43
+ # data(:y, ["a", "b"])
44
+ # def test_patterns(data)
45
+ # # 3 * 2 times executed
46
+ # # 3: the number of patterns of :x
47
+ # # 2: the number of patterns of :y
48
+ # p data
49
+ # # => {:x => 1, :y => "a"}
50
+ # # => {:x => 1, :y => "b"}
51
+ # # => {:x => 2, :y => "a"}
52
+ # # => {:x => 2, :y => "b"}
53
+ # # => {:x => 3, :y => "a"}
54
+ # # => {:x => 3, :y => "b"}
55
+ # end
56
+ #
57
+ # Generates test matrix from variable and patterns pairs.
58
+ #
59
+ # @overload data(data_set, options={})
28
60
  # @param [Hash] data_set specify test data as a Hash that
29
61
  # key is test label and value is test data.
62
+ # @param [Hash] options specify options.
63
+ # @option options [Boolean] :keep whether or not to use
64
+ # this data in the following test methods
30
65
  #
31
66
  # @example data(data_set)
32
67
  # data("empty string" => [true, ""],
@@ -36,9 +71,12 @@ module Test
36
71
  # assert_equal(expected, target.empty?)
37
72
  # end
38
73
  #
39
- # @overload data(&block)
40
- # @yieldreturn [Hash] return test data set as a Hash that
41
- # key is test label and value is test data.
74
+ # @overload data(options={}, &block)
75
+ # @param [Hash] options specify options.
76
+ # @option options [Boolean] :keep whether or not to use
77
+ # this data in the following test methods
78
+ # @yieldreturn [Hash<String, Object>] return test data set
79
+ # as a Hash that key is test label and value is test data.
42
80
  #
43
81
  # @example data(&block)
44
82
  # data do
@@ -52,22 +90,93 @@ module Test
52
90
  # assert_equal(expected, target.empty?)
53
91
  # end
54
92
  #
93
+ # @overload data(options={}, &block)
94
+ # @param [Hash] options specify options.
95
+ # @option options [Boolean] :keep whether or not to use
96
+ # this data in the following test methods
97
+ # @yieldreturn [Array<Symbol, Array>] return test data set
98
+ # as an Array of variable and patterns.
99
+ #
100
+ # @example data(&block)
101
+ # data do
102
+ # patterns = 3.times.to_a
103
+ # [:x, patterns]
104
+ # end
105
+ # data do
106
+ # patterns = []
107
+ # character = "a"
108
+ # 2.times.each do
109
+ # patterns << character
110
+ # character = character.succ
111
+ # end
112
+ # [:y, patterns]
113
+ # end
114
+ # def test_patterns(data)
115
+ # # 3 * 2 times executed
116
+ # # 3: the number of patterns of :x
117
+ # # 2: the number of patterns of :y
118
+ # p data
119
+ # # => {:x => 0, :y => "a"}
120
+ # # => {:x => 0, :y => "b"}
121
+ # # => {:x => 1, :y => "a"}
122
+ # # => {:x => 1, :y => "b"}
123
+ # # => {:x => 2, :y => "a"}
124
+ # # => {:x => 2, :y => "b"}
125
+ # end
126
+ #
127
+ # Generates test matrix from variable and patterns pairs.
128
+ #
55
129
  def data(*arguments, &block)
130
+ options = nil
56
131
  n_arguments = arguments.size
57
132
  case n_arguments
58
133
  when 0
59
134
  raise ArgumentError, "no block is given" unless block_given?
60
135
  data_set = block
61
136
  when 1
62
- data_set = arguments[0]
137
+ if block_given?
138
+ data_set = block
139
+ options = arguments[1]
140
+ else
141
+ data_set = arguments[0]
142
+ end
63
143
  when 2
64
- data_set = {arguments[0] => arguments[1]}
144
+ case arguments[0]
145
+ when String
146
+ data_set = {arguments[0] => arguments[1]}
147
+ when Hash
148
+ data_set = arguments[0]
149
+ options = arguments[1]
150
+ else
151
+ variable = arguments[0]
152
+ patterns = arguments[1]
153
+ data_set = [variable, patterns]
154
+ end
155
+ when 3
156
+ case arguments[0]
157
+ when String
158
+ data_set = {arguments[0] => arguments[1]}
159
+ options = arguments[2]
160
+ else
161
+ variable = arguments[0]
162
+ patterns = arguments[1]
163
+ data_set = [variable, patterns]
164
+ options = arguments[2]
165
+ end
65
166
  else
66
- message = "wrong number arguments(#{n_arguments} for 1..2)"
167
+ message = "wrong number arguments(#{n_arguments} for 0..3)"
67
168
  raise ArgumentError, message
68
169
  end
69
- current_data = current_attribute(:data)[:value] || []
70
- attribute(:data, current_data + [data_set])
170
+ options ||= {}
171
+ data_sets = current_attribute(:data)[:value] || DataSets.new
172
+ data_sets.add(data_set, options)
173
+ if options[:keep]
174
+ keep_hook = lambda do |attr|
175
+ attr.merge(value: attr[:value].keep)
176
+ end
177
+ options = options.merge(keep_hook: keep_hook)
178
+ end
179
+ attribute(:data, data_sets, options)
71
180
  end
72
181
 
73
182
  # This method provides Data-Driven-Test functionality.
@@ -78,7 +187,7 @@ module Test
78
187
  #
79
188
  # @param [String] file_name full path to test data file.
80
189
  # File format is automatically detected from filename extension.
81
- # @raise [ArgumentError] if +file_name+ is not supported file format.
190
+ # @raise [ArgumentError] if `file_name` is not supported file format.
82
191
  # @see Loader#load
83
192
  #
84
193
  # @example Load data from CSV file
@@ -102,7 +211,7 @@ module Test
102
211
  #
103
212
  # @param [String] file_name full path to test data file.
104
213
  # File format is automatically detected from filename extension.
105
- # @raise [ArgumentError] if +file_name+ is not supported file format.
214
+ # @raise [ArgumentError] if `file_name` is not supported file format.
106
215
  # @see #load_csv
107
216
  # @see #load_tsv
108
217
  # @api private
@@ -3,9 +3,9 @@
3
3
  # Copyright (c) 2001-2008 Python Software Foundation; All Rights Reserved
4
4
  # Copyright (c) 2008-2011 Kouhei Sutou; All Rights Reserved
5
5
  #
6
- # It is free software, and is distributed under the Ruby
7
- # license and/or the PSF license. See the COPYING file and
8
- # PSFL file.
6
+ # It is free software, and is distributed under the Ruby license, the
7
+ # PSF license and/or LGPLv2.1 or later. See the COPYING file, the PSFL
8
+ # file and the LGPL file.
9
9
 
10
10
  module Test
11
11
  module Unit
@@ -269,7 +269,7 @@ module Test
269
269
 
270
270
  private
271
271
  def tag(mark, contents)
272
- contents.collect {|content| "#{mark}#{content}"}
272
+ contents.collect {|content| mark + content}
273
273
  end
274
274
  end
275
275
 
@@ -450,7 +450,7 @@ module Test
450
450
 
451
451
  def tag(mark, contents)
452
452
  contents.each do |content|
453
- @result << "#{mark}#{content}"
453
+ @result << (mark + content)
454
454
  end
455
455
  end
456
456
 
@@ -577,15 +577,15 @@ module Test
577
577
  to_width = compute_width(to_line, to_start, to_end)
578
578
  case tag
579
579
  when :replace
580
- from_tags << "^" * from_width
581
- to_tags << "^" * to_width
580
+ from_tags += "^" * from_width
581
+ to_tags += "^" * to_width
582
582
  when :delete
583
- from_tags << "-" * from_width
583
+ from_tags += "-" * from_width
584
584
  when :insert
585
- to_tags << "+" * to_width
585
+ to_tags += "+" * to_width
586
586
  when :equal
587
- from_tags << " " * from_width
588
- to_tags << " " * to_width
587
+ from_tags += " " * from_width
588
+ to_tags += " " * to_width
589
589
  else
590
590
  raise "unknown tag: #{tag}"
591
591
  end
@@ -127,6 +127,9 @@ module Test
127
127
  if method_name_or_callback.respond_to?(:call)
128
128
  callback = method_name_or_callback
129
129
  method_name = callback_method_name(callback)
130
+ @test_case.attribute(:source_location,
131
+ callback.source_location,
132
+ method_name)
130
133
  @test_case.__send__(:define_method, method_name, &callback)
131
134
  else
132
135
  method_name = method_name_or_callback
@@ -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?
@@ -148,15 +148,19 @@ module Test
148
148
  end
149
149
 
150
150
  def escape_class_name(class_name)
151
- class_name.gsub(/(?:[: \\\/])/, "_")
151
+ escape_name(class_name)
152
152
  end
153
153
 
154
154
  def escaped_method_name
155
- @test.method_name.to_s.gsub(/(?:[: ]|[!?=]$)/) do |matched|
155
+ escape_name(@test.method_name.to_s)
156
+ end
157
+
158
+ def escape_name(name)
159
+ name.gsub(/(?:[: \/!?=])/) do |matched|
156
160
  case matched
157
161
  when ":"
158
162
  "_colon_"
159
- when " "
163
+ when " ", "/"
160
164
  "_"
161
165
  when "!"
162
166
  ".destructive"
@@ -1,3 +1,22 @@
1
+ # Copyright (C) 2008-2017 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # License: Ruby OR LGPL-2.1+
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ # 02110-1301 USA
19
+
1
20
  module Test
2
21
  module Unit
3
22
  AutoRunner.register_runner(:console) do |auto_runner|
@@ -54,6 +73,12 @@ module Test
54
73
  "(default is yes)") do |boolean|
55
74
  auto_runner.runner_options[:show_detail_immediately] = boolean
56
75
  end
76
+
77
+ opts.on("--[no-]reverse-output",
78
+ "Shows fault details in reverse.",
79
+ "(default is yes for tty output, no otherwise)") do |boolean|
80
+ auto_runner.runner_options[:reverse_output] = boolean
81
+ end
57
82
  end
58
83
  end
59
84
  end