minitest 5.11.3 → 5.25.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/minitest/test.rb CHANGED
@@ -18,6 +18,10 @@ module Minitest
18
18
 
19
19
  PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, SystemExit] # :nodoc:
20
20
 
21
+ SETUP_METHODS = %w[ before_setup setup after_setup ] # :nodoc:
22
+
23
+ TEARDOWN_METHODS = %w[ before_teardown teardown after_teardown ] # :nodoc:
24
+
21
25
  # :stopdoc:
22
26
  class << self; attr_accessor :io_lock; end
23
27
  self.io_lock = Mutex.new
@@ -48,9 +52,10 @@ module Minitest
48
52
  end
49
53
 
50
54
  ##
51
- # Call this at the top of your tests when you want to run your
52
- # tests in parallel. In doing so, you're admitting that you rule
53
- # and your tests are awesome.
55
+ # Call this at the top of your tests (inside the +Minitest::Test+
56
+ # subclass or +describe+ block) when you want to run your tests in
57
+ # parallel. In doing so, you're admitting that you rule and your
58
+ # tests are awesome.
54
59
 
55
60
  def self.parallelize_me!
56
61
  include Minitest::Parallel::Test
@@ -67,8 +72,8 @@ module Minitest
67
72
 
68
73
  case self.test_order
69
74
  when :random, :parallel then
70
- max = methods.size
71
- methods.sort.sort_by { rand max }
75
+ srand Minitest.seed
76
+ methods.sort.shuffle
72
77
  when :alpha, :sorted then
73
78
  methods.sort
74
79
  else
@@ -76,32 +81,22 @@ module Minitest
76
81
  end
77
82
  end
78
83
 
79
- ##
80
- # Defines the order to run tests (:random by default). Override
81
- # this or use a convenience method to change it for your tests.
82
-
83
- def self.test_order
84
- :random
85
- end
86
-
87
- TEARDOWN_METHODS = %w[ before_teardown teardown after_teardown ] # :nodoc:
88
-
89
84
  ##
90
85
  # Runs a single test with setup/teardown hooks.
91
86
 
92
87
  def run
93
- with_info_handler do
94
- time_it do
95
- capture_exceptions do
96
- before_setup; setup; after_setup
97
-
98
- self.send self.name
88
+ time_it do
89
+ capture_exceptions do
90
+ SETUP_METHODS.each do |hook|
91
+ self.send hook
99
92
  end
100
93
 
101
- TEARDOWN_METHODS.each do |hook|
102
- capture_exceptions do
103
- self.send hook
104
- end
94
+ self.send self.name
95
+ end
96
+
97
+ TEARDOWN_METHODS.each do |hook|
98
+ capture_exceptions do
99
+ self.send hook
105
100
  end
106
101
  end
107
102
  end
@@ -145,7 +140,7 @@ module Minitest
145
140
  # end
146
141
  # end
147
142
  #
148
- # class MiniTest::Test
143
+ # class Minitest::Test
149
144
  # include MyMinitestPlugin
150
145
  # end
151
146
 
@@ -198,17 +193,39 @@ module Minitest
198
193
  rescue Assertion => e
199
194
  self.failures << e
200
195
  rescue Exception => e
201
- self.failures << UnexpectedError.new(e)
196
+ self.failures << UnexpectedError.new(sanitize_exception e)
197
+ end
198
+
199
+ def sanitize_exception e # :nodoc:
200
+ Marshal.dump e
201
+ e # good: use as-is
202
+ rescue
203
+ neuter_exception e
202
204
  end
203
205
 
204
- def with_info_handler &block # :nodoc:
205
- t0 = Minitest.clock_time
206
+ def neuter_exception e # :nodoc:
207
+ bt = e.backtrace
208
+ msg = e.message.dup
206
209
 
207
- handler = lambda do
208
- warn "\nCurrent: %s#%s %.2fs" % [self.class, self.name, Minitest.clock_time - t0]
210
+ new_exception e.class, msg, bt # e.class can be a problem...
211
+ rescue
212
+ msg.prepend "Neutered Exception #{e.class}: "
213
+
214
+ new_exception RuntimeError, msg, bt, true # but if this raises, we die
215
+ end
216
+
217
+ def new_exception klass, msg, bt, kill = false # :nodoc:
218
+ ne = klass.new msg
219
+ ne.set_backtrace bt
220
+
221
+ if kill then
222
+ ne.instance_variables.each do |v|
223
+ ne.remove_instance_variable v
224
+ end
209
225
  end
210
226
 
211
- self.class.on_signal ::Minitest.info_signal, handler, &block
227
+ Marshal.dump ne # can raise TypeError
228
+ ne
212
229
  end
213
230
 
214
231
  include LifecycleHooks
@@ -217,4 +234,4 @@ module Minitest
217
234
  end # Test
218
235
  end
219
236
 
220
- require "minitest/unit" unless defined?(MiniTest) # compatibility layer only
237
+ require "minitest/unit" if ENV["MT_COMPAT"] # compatibility layer only
@@ -0,0 +1,307 @@
1
+ require "shellwords"
2
+ require "rbconfig"
3
+
4
+ begin
5
+ require "rake/tasklib"
6
+ rescue LoadError => e
7
+ warn e.message
8
+ return
9
+ end
10
+
11
+ module Minitest # :nodoc:
12
+
13
+ ##
14
+ # Minitest::TestTask is a rake helper that generates several rake
15
+ # tasks under the main test task's name-space.
16
+ #
17
+ # task <name> :: the main test task
18
+ # task <name>:cmd :: prints the command to use
19
+ # task <name>:deps :: runs each test file by itself to find dependency errors
20
+ # task <name>:slow :: runs the tests and reports the slowest 25 tests.
21
+ #
22
+ # Examples:
23
+ #
24
+ # Minitest::TestTask.create
25
+ #
26
+ # The most basic and default setup.
27
+ #
28
+ # Minitest::TestTask.create :my_tests
29
+ #
30
+ # The most basic/default setup, but with a custom name
31
+ #
32
+ # Minitest::TestTask.create :unit do |t|
33
+ # t.test_globs = ["test/unit/**/*_test.rb"]
34
+ # t.warning = false
35
+ # end
36
+ #
37
+ # Customize the name and only run unit tests.
38
+ #
39
+ # NOTE: To hook this task up to the default, make it a dependency:
40
+ #
41
+ # task default: :unit
42
+
43
+ class TestTask < Rake::TaskLib
44
+ WINDOWS = RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ # :nodoc:
45
+
46
+ ##
47
+ # Create several test-oriented tasks under +name+. Takes an
48
+ # optional block to customize variables.
49
+
50
+ def self.create name = :test, &block
51
+ task = new name
52
+ task.instance_eval(&block) if block
53
+ task.process_env
54
+ task.define
55
+ task
56
+ end
57
+
58
+ ##
59
+ # Extra arguments to pass to the tests. Defaults empty but gets
60
+ # populated by a number of enviroment variables:
61
+ #
62
+ # N (-n flag) :: a string or regexp of tests to run.
63
+ # X (-e flag) :: a string or regexp of tests to exclude.
64
+ # A (arg) :: quick way to inject an arbitrary argument (eg A=--help).
65
+ #
66
+ # See #process_env
67
+
68
+ attr_accessor :extra_args
69
+
70
+ ##
71
+ # The code to load the framework. Defaults to requiring
72
+ # minitest/autorun...
73
+ #
74
+ # Why do I have this as an option?
75
+
76
+ attr_accessor :framework
77
+
78
+ ##
79
+ # Extra library directories to include. Defaults to %w[lib test
80
+ # .]. Also uses $MT_LIB_EXTRAS allowing you to dynamically
81
+ # override/inject directories for custom runs.
82
+
83
+ attr_accessor :libs
84
+
85
+ ##
86
+ # The name of the task and base name for the other tasks generated.
87
+
88
+ attr_accessor :name
89
+
90
+ ##
91
+ # File globs to find test files. Defaults to something sensible to
92
+ # find test files under the test directory.
93
+
94
+ attr_accessor :test_globs
95
+
96
+ ##
97
+ # Turn on ruby warnings (-w flag). Defaults to true.
98
+
99
+ attr_accessor :warning
100
+
101
+ ##
102
+ # Optional: Additional ruby to run before the test framework is loaded.
103
+
104
+ attr_accessor :test_prelude
105
+
106
+ ##
107
+ # Print out commands as they run. Defaults to Rake's +trace+ (-t
108
+ # flag) option.
109
+
110
+ attr_accessor :verbose
111
+
112
+ ##
113
+ # Use TestTask.create instead.
114
+
115
+ def initialize name = :test # :nodoc:
116
+ self.extra_args = []
117
+ self.framework = %(require "minitest/autorun")
118
+ self.libs = %w[lib test .]
119
+ self.name = name
120
+ self.test_globs = ["test/**/test_*.rb",
121
+ "test/**/*_test.rb"]
122
+ self.test_prelude = nil
123
+ self.verbose = Rake.application.options.trace || Rake.verbose == true
124
+ self.warning = true
125
+ end
126
+
127
+ ##
128
+ # Extract variables from the environment and convert them to
129
+ # command line arguments. See #extra_args.
130
+ #
131
+ # Environment Variables:
132
+ #
133
+ # MT_LIB_EXTRAS :: Extra libs to dynamically override/inject for custom runs.
134
+ # N :: Tests to run (string or /regexp/).
135
+ # X :: Tests to exclude (string or /regexp/).
136
+ # A :: Any extra arguments. Honors shell quoting.
137
+ #
138
+ # Deprecated:
139
+ #
140
+ # TESTOPTS :: For argument passing, use +A+.
141
+ # N :: For parallel testing, use +MT_CPU+.
142
+ # FILTER :: Same as +TESTOPTS+.
143
+
144
+ def process_env
145
+ warn "TESTOPTS is deprecated in Minitest::TestTask. Use A instead" if
146
+ ENV["TESTOPTS"]
147
+ warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if
148
+ ENV["FILTER"]
149
+ warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if
150
+ ENV["N"] && ENV["N"].to_i > 0
151
+
152
+ lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR
153
+ self.libs[0, 0] = lib_extras
154
+
155
+ extra_args << "-n" << ENV["N"] if ENV["N"]
156
+ extra_args << "-e" << ENV["X"] if ENV["X"]
157
+ extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"]
158
+ extra_args.concat Shellwords.split(ENV["FILTER"]) if ENV["FILTER"]
159
+ extra_args.concat Shellwords.split(ENV["A"]) if ENV["A"]
160
+
161
+ ENV.delete "N" if ENV["N"]
162
+
163
+ # TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"]
164
+ # TODO? ENV["RUBY_FLAGS"]
165
+
166
+ extra_args.compact!
167
+ end
168
+
169
+ def define # :nodoc:
170
+ desc "Run the test suite. Use N, X, A, and TESTOPTS to add flags/args."
171
+ task name do
172
+ ruby make_test_cmd, verbose: verbose
173
+ end
174
+
175
+ desc "Print out the test command. Good for profiling and other tools."
176
+ task "#{name}:cmd" do
177
+ puts "ruby #{make_test_cmd}"
178
+ end
179
+
180
+ desc "Show which test files fail when run in isolation."
181
+ task "#{name}:isolated" do
182
+ tests = Dir[*self.test_globs].uniq
183
+
184
+ # 3 seems to be the magic number... (tho not by that much)
185
+ bad, good, n = {}, [], (ENV.delete("K") || 3).to_i
186
+ file = ENV.delete "F"
187
+ times = {}
188
+
189
+ tt0 = Time.now
190
+
191
+ n.threads_do tests.sort do |path|
192
+ t0 = Time.now
193
+ output = `#{Gem.ruby} #{make_test_cmd path} 2>&1`
194
+ t1 = Time.now - t0
195
+
196
+ times[path] = t1
197
+
198
+ if $?.success?
199
+ $stderr.print "."
200
+ good << path
201
+ else
202
+ $stderr.print "x"
203
+ bad[path] = output
204
+ end
205
+ end
206
+
207
+ puts "done"
208
+ puts "Ran in %.2f seconds" % [ Time.now - tt0 ]
209
+
210
+ if file then
211
+ require "json"
212
+ File.open file, "w" do |io|
213
+ io.puts JSON.pretty_generate times
214
+ end
215
+ end
216
+
217
+ unless good.empty?
218
+ puts
219
+ puts "# Good tests:"
220
+ puts
221
+ good.sort.each do |path|
222
+ puts "%.2fs: %s" % [times[path], path]
223
+ end
224
+ end
225
+
226
+ unless bad.empty?
227
+ puts
228
+ puts "# Bad tests:"
229
+ puts
230
+ bad.keys.sort.each do |path|
231
+ puts "%.2fs: %s" % [times[path], path]
232
+ end
233
+ puts
234
+ puts "# Bad Test Output:"
235
+ puts
236
+ bad.sort.each do |path, output|
237
+ puts
238
+ puts "# #{path}:"
239
+ puts output
240
+ end
241
+ exit 1
242
+ end
243
+ end
244
+
245
+ task "#{name}:deps" => "#{name}:isolated" # now just an alias
246
+
247
+ desc "Run the test suite and report the slowest 25 tests."
248
+ task "#{name}:slow" do
249
+ sh ["rake #{name} A=-v",
250
+ "egrep '#test_.* s = .'",
251
+ "sort -n -k2 -t=",
252
+ "tail -25"].join " | "
253
+ end
254
+ end
255
+
256
+ ##
257
+ # Generate the test command-line.
258
+
259
+ def make_test_cmd globs = test_globs
260
+ tests = []
261
+ tests.concat Dir[*globs].sort.shuffle # TODO: SEED -> srand first?
262
+ tests.map! { |f| %(require "#{f}") }
263
+
264
+ runner = []
265
+ runner << test_prelude if test_prelude
266
+ runner << framework
267
+ runner.concat tests
268
+ runner = runner.join "; "
269
+
270
+ args = []
271
+ args << "-I#{libs.join File::PATH_SEPARATOR}" unless libs.empty?
272
+ args << "-w" if warning
273
+ args << "-e"
274
+ args << "'#{runner}'"
275
+ args << "--"
276
+ args << extra_args.map(&:shellescape)
277
+
278
+ args.join " "
279
+ end
280
+ end
281
+ end
282
+
283
+ class Work < Queue # :nodoc:
284
+ def initialize jobs = [] # :nodoc:
285
+ super()
286
+
287
+ jobs.each do |job|
288
+ self << job
289
+ end
290
+
291
+ close
292
+ end
293
+ end
294
+
295
+ class Integer # :nodoc:
296
+ def threads_do jobs # :nodoc:
297
+ q = Work.new jobs
298
+
299
+ Array.new(self) {
300
+ Thread.new do
301
+ while job = q.pop # go until quit value
302
+ yield job
303
+ end
304
+ end
305
+ }.each(&:join)
306
+ end
307
+ end
data/lib/minitest/unit.rb CHANGED
@@ -1,5 +1,3 @@
1
- # :stopdoc:
2
-
3
1
  unless defined?(Minitest) then
4
2
  # all of this crap is just to avoid circular requires and is only
5
3
  # needed if a user requires "minitest/unit" directly instead of
@@ -10,17 +8,18 @@ unless defined?(Minitest) then
10
8
  warn %(Warning: or add 'gem "minitest"' before 'require "minitest/autorun"')
11
9
  warn "From:\n #{from}"
12
10
 
13
- module Minitest; end
14
- MiniTest = Minitest # prevents minitest.rb from requiring back to us
11
+ module Minitest # :nodoc:
12
+ end
13
+ MiniTest = Minitest # :nodoc: # prevents minitest.rb from requiring back to us
15
14
  require "minitest"
16
15
  end
17
16
 
18
17
  MiniTest = Minitest unless defined?(MiniTest)
19
18
 
20
19
  module Minitest
21
- class Unit
20
+ class Unit # :nodoc:
22
21
  VERSION = Minitest::VERSION
23
- class TestCase < Minitest::Test
22
+ class TestCase < Minitest::Test # :nodoc:
24
23
  def self.inherited klass # :nodoc:
25
24
  from = caller.first
26
25
  warn "MiniTest::Unit::TestCase is now Minitest::Test. From #{from}"
@@ -41,5 +40,3 @@ module Minitest
41
40
  end
42
41
  end
43
42
  end
44
-
45
- # :startdoc: