minitest 5.25.5 → 6.0.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -4
  3. data/History.rdoc +116 -0
  4. data/Manifest.txt +13 -4
  5. data/README.rdoc +18 -98
  6. data/Rakefile +7 -2
  7. data/bin/minitest +5 -0
  8. data/design_rationale.rb +21 -19
  9. data/lib/hoe/minitest.rb +2 -1
  10. data/lib/minitest/assertions.rb +37 -74
  11. data/lib/minitest/autorun.rb +3 -4
  12. data/lib/minitest/benchmark.rb +2 -2
  13. data/lib/minitest/bisect.rb +306 -0
  14. data/lib/minitest/complete.rb +56 -0
  15. data/lib/minitest/find_minimal_combination.rb +127 -0
  16. data/lib/minitest/hell.rb +1 -1
  17. data/lib/minitest/manual_plugins.rb +4 -16
  18. data/lib/minitest/parallel.rb +5 -3
  19. data/lib/minitest/path_expander.rb +418 -0
  20. data/lib/minitest/pride.rb +2 -2
  21. data/lib/minitest/pride_plugin.rb +1 -1
  22. data/lib/minitest/server.rb +45 -0
  23. data/lib/minitest/server_plugin.rb +84 -0
  24. data/lib/minitest/spec.rb +11 -37
  25. data/lib/minitest/sprint.rb +104 -0
  26. data/lib/minitest/sprint_plugin.rb +39 -0
  27. data/lib/minitest/test.rb +8 -13
  28. data/lib/minitest/test_task.rb +32 -17
  29. data/lib/minitest.rb +94 -107
  30. data/test/minitest/metametameta.rb +1 -1
  31. data/test/minitest/test_bisect.rb +235 -0
  32. data/test/minitest/test_find_minimal_combination.rb +138 -0
  33. data/test/minitest/test_minitest_assertions.rb +51 -108
  34. data/test/minitest/test_minitest_reporter.rb +6 -5
  35. data/test/minitest/test_minitest_spec.rb +60 -128
  36. data/test/minitest/test_minitest_test.rb +22 -101
  37. data/test/minitest/test_path_expander.rb +229 -0
  38. data/test/minitest/test_server.rb +149 -0
  39. data.tar.gz.sig +0 -0
  40. metadata +54 -21
  41. metadata.gz.sig +0 -0
  42. data/.autotest +0 -34
  43. data/lib/minitest/mock.rb +0 -347
  44. data/lib/minitest/unit.rb +0 -42
  45. data/test/minitest/test_minitest_mock.rb +0 -1218
@@ -0,0 +1,84 @@
1
+ require_relative "../minitest"
2
+
3
+ module Minitest
4
+ @server = false
5
+
6
+ def self.plugin_server_options opts, options # :nodoc:
7
+ opts.on "--server=pid", Integer, "Connect to minitest server w/ pid." do |s|
8
+ @server = s
9
+ end
10
+ end
11
+
12
+ def self.plugin_server_init options
13
+ if @server then
14
+ require_relative "server"
15
+ self.reporter << Minitest::ServerReporter.new(@server)
16
+ end
17
+ end
18
+ end
19
+
20
+ class Minitest::ServerReporter < Minitest::AbstractReporter
21
+ def initialize pid
22
+ uri = Minitest::Server.path(pid)
23
+ @mt_server = DRbObject.new_with_uri uri
24
+ super()
25
+ end
26
+
27
+ def start
28
+ @mt_server.start
29
+ end
30
+
31
+ def record result
32
+ r = result
33
+ c = r.class
34
+
35
+ case r
36
+ when Minitest::Result then
37
+ file, = r.source_location
38
+ cn = r.klass
39
+ else
40
+ # TODO: remove? when is this used?
41
+ file, = r.method(r.name).source_location
42
+ cn = c.name
43
+ end
44
+
45
+ sanitize r.failures
46
+
47
+ @mt_server.result file, cn, r.name, r.failures, r.assertions, r.time
48
+ end
49
+
50
+ def sanitize failures
51
+ failures.map! { |e|
52
+ case e
53
+ when Minitest::UnexpectedError then
54
+ # embedded exception might not be able to be marshaled.
55
+ bt = e.error.backtrace
56
+
57
+ ex = RuntimeError.new(e.error.message)
58
+ e.error = ex
59
+ ex.set_backtrace bt
60
+
61
+ e = Minitest::UnexpectedError.new ex # ugh. some rails plugin. ugh.
62
+
63
+ if ex.instance_variables.include? :@bindings then # web-console is Evil
64
+ ex.instance_variable_set :@bindings, nil
65
+ e.instance_variable_set :@bindings, nil
66
+ end
67
+ when Minitest::Skip then
68
+ # do nothing
69
+ when Minitest::Assertion then
70
+ bt = e.backtrace
71
+ e = e.class.new(e.message)
72
+ e.set_backtrace bt
73
+ else
74
+ warn "Unhandled exception type: #{e.class}\n\n#{e.inspect}"
75
+ end
76
+
77
+ e
78
+ }
79
+ end
80
+
81
+ def report
82
+ @mt_server.report
83
+ end
84
+ end
data/lib/minitest/spec.rb CHANGED
@@ -1,27 +1,15 @@
1
- require "minitest/test"
1
+ require_relative "test"
2
2
 
3
3
  class Module # :nodoc:
4
4
  def infect_an_assertion meth, new_name, dont_flip = false # :nodoc:
5
5
  block = dont_flip == :block
6
6
  dont_flip = false if block
7
- target_obj = block ? "_{obj.method}" : "_(obj)"
8
7
 
9
8
  # https://eregon.me/blog/2021/02/13/correct-delegation-in-ruby-2-27-3.html
10
9
  # Drop this when we can drop ruby 2.6 (aka after rails 6.1 EOL, ~2024-06)
11
10
  kw_extra = "ruby2_keywords %p" % [new_name] if respond_to? :ruby2_keywords, true
12
11
 
13
- # warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
14
12
  self.class_eval <<-EOM, __FILE__, __LINE__ + 1
15
- def #{new_name} *args
16
- where = Minitest.filter_backtrace(caller).first
17
- where = where.split(/:in /, 2).first # clean up noise
18
- Kernel.warn "DEPRECATED: global use of #{new_name} from #\{where}. Use #{target_obj}.#{new_name} instead. This will fail in Minitest 6."
19
- Minitest::Expectation.new(self, Minitest::Spec.current).#{new_name}(*args)
20
- end
21
- #{kw_extra}
22
- EOM
23
-
24
- Minitest::Expectation.class_eval <<-EOM, __FILE__, __LINE__ + 1
25
13
  def #{new_name} *args
26
14
  raise "Calling ##{new_name} outside of test." unless ctx
27
15
  case
@@ -38,7 +26,11 @@ class Module # :nodoc:
38
26
  end
39
27
  end
40
28
 
41
- Minitest::Expectation = Struct.new :target, :ctx # :nodoc:
29
+ # :stopdoc:
30
+ module Minitest # fucking hell rdoc...
31
+ Expectation = Struct.new :target, :ctx
32
+ end
33
+ # :startdoc:
42
34
 
43
35
  ##
44
36
  # Kernel extensions for minitest
@@ -106,15 +98,6 @@ end
106
98
 
107
99
  class Minitest::Spec < Minitest::Test
108
100
 
109
- def self.current # :nodoc:
110
- Thread.current[:current_spec]
111
- end
112
-
113
- def initialize name # :nodoc:
114
- super
115
- Thread.current[:current_spec] = self
116
- end
117
-
118
101
  ##
119
102
  # Oh look! A Minitest::Spec::DSL module! Eat your heart out DHH.
120
103
 
@@ -285,9 +268,8 @@ class Minitest::Spec < Minitest::Test
285
268
  defined?(@name) ? @name : super
286
269
  end
287
270
 
288
- def to_s # :nodoc:
289
- name # Can't alias due to 1.8.7, not sure why
290
- end
271
+ alias to_s name
272
+ alias inspect name
291
273
 
292
274
  attr_reader :desc # :nodoc:
293
275
  alias specify it
@@ -310,9 +292,6 @@ class Minitest::Spec < Minitest::Test
310
292
  # straight-expectation methods (on Object) because it stores its
311
293
  # test context, bypassing our hacky use of thread-local variables.
312
294
  #
313
- # NOTE: At some point, the methods on Object will be deprecated
314
- # and then removed.
315
- #
316
295
  # It is also aliased to #value and #expect for your aesthetic
317
296
  # pleasure:
318
297
  #
@@ -326,11 +305,6 @@ class Minitest::Spec < Minitest::Test
326
305
 
327
306
  alias value _
328
307
  alias expect _
329
-
330
- def before_setup # :nodoc:
331
- super
332
- Thread.current[:current_spec] = self
333
- end
334
308
  end
335
309
 
336
310
  def self.extended obj # :nodoc:
@@ -343,8 +317,8 @@ class Minitest::Spec < Minitest::Test
343
317
  TYPES = DSL::TYPES # :nodoc:
344
318
  end
345
319
 
346
- require "minitest/expectations"
320
+ require_relative "expectations"
347
321
 
348
- class Object # :nodoc:
349
- include Minitest::Expectations unless ENV["MT_NO_EXPECTATIONS"]
322
+ class Minitest::Expectation
323
+ include Minitest::Expectations
350
324
  end
@@ -0,0 +1,104 @@
1
+ $LOAD_PATH.unshift "test", "lib"
2
+
3
+ require "simplecov" if ENV["MT_COV"] || ARGV.delete("--simplecov")
4
+ require_relative "autorun"
5
+ require_relative "path_expander"
6
+
7
+ ##
8
+ # Runs (Get it? It's fast!) your tests and makes it easier to rerun individual
9
+ # failures.
10
+
11
+ module Minitest
12
+ class Sprint
13
+ # extracted version = "1.5.0"
14
+
15
+ ##
16
+ # Process and run minitest cmdline.
17
+
18
+ def self.run args = ARGV
19
+ if ARGV.delete("--bisect") or ARGV.delete("-b") then
20
+ require_relative "bisect"
21
+
22
+ return Minitest::Bisect.run ARGV
23
+ end
24
+
25
+ Minitest::PathExpander.new(args).process { |f|
26
+ require "./#{f}" if File.file? f
27
+ }
28
+ end
29
+
30
+ ##
31
+ # An extra minitest reporter to output how to rerun failures in
32
+ # various styles.
33
+
34
+ class SprintReporter < AbstractReporter
35
+ ##
36
+ # The style to report, either lines or regexp. Defaults to lines.
37
+ attr_accessor :style
38
+ attr_accessor :results # :nodoc:
39
+
40
+ def initialize style = :regexp # :nodoc:
41
+ self.results = []
42
+ self.style = style
43
+ end
44
+
45
+ def record result # :nodoc:
46
+ results << result unless result.passed? or result.skipped?
47
+ end
48
+
49
+ def report # :nodoc:
50
+ return if results.empty?
51
+
52
+ puts
53
+ puts "Happy Happy Sprint List:"
54
+ puts
55
+ print_list
56
+ puts
57
+ end
58
+
59
+ def print_list # :nodoc:
60
+ case style
61
+ when :regexp
62
+ results.each do |result|
63
+ puts " minitest -n #{result.class_name}##{result.name}"
64
+ end
65
+ when :lines
66
+ files = Hash.new { |h,k| h[k] = [] }
67
+ results.each do |result|
68
+ path, line = result.source_location
69
+ path = path.delete_prefix "#{Dir.pwd}/"
70
+ files[path] << line
71
+ end
72
+
73
+ files.sort.each do |path, lines|
74
+ puts " minitest %s:%s" % [path, lines.sort.join(",")]
75
+ end
76
+ else
77
+ raise "unsupported style: %p" % [style]
78
+ end
79
+ end
80
+ end
81
+
82
+ ##
83
+ # An extra minitest reporter to output how to rerun failures using
84
+ # rake.
85
+
86
+ class RakeReporter < SprintReporter
87
+ ##
88
+ # The name of the rake task to rerun. Defaults to nil.
89
+
90
+ attr_accessor :name
91
+
92
+ def initialize name = nil # :nodoc:
93
+ super()
94
+ self.name = name
95
+ end
96
+
97
+ def print_list # :nodoc:
98
+ results.each do |result|
99
+ puts [" rake", name, "N=#{result.class_name}##{result.name}"].compact.join(" ")
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,39 @@
1
+ require_relative "../minitest"
2
+
3
+ # :stopdoc:
4
+ class OptionParser # unofficial embedded gem "makeoptparseworkwell"
5
+ def hidden(...) = define(...).tap { |sw| def sw.summarize(*) = nil }
6
+ def deprecate(from, to) = hidden(from) { abort "#{from} is deprecated. Use #{to}." }
7
+ def topdict(name) = name.length > 1 ? top.long : top.short
8
+ def alias(from, to) = (dict = topdict(from) and dict[to] = dict[from])
9
+ end unless OptionParser.method_defined? :hidden
10
+ # :startdoc:
11
+
12
+ module Minitest # :nodoc:
13
+ def self.plugin_sprint_options opts, options # :nodoc:
14
+ opts.on "--rake [TASK]", "Report how to re-run failures with rake." do |task|
15
+ options[:sprint] = :rake
16
+ options[:rake_task] = task
17
+ end
18
+
19
+ opts.deprecate "--binstub", "--rerun"
20
+
21
+ sprint_styles = %w[rake lines names binstub]
22
+
23
+ opts.on "-r", "--rerun [STYLE]", sprint_styles, "Report how to re-run failures using STYLE (names, lines)." do |style|
24
+ options[:sprint] = (style || :lines).to_sym
25
+ end
26
+ end
27
+
28
+ def self.plugin_sprint_init options
29
+ require_relative "sprint"
30
+ case options[:sprint]
31
+ when :rake then
32
+ self.reporter << Minitest::Sprint::RakeReporter.new(options[:rake_task])
33
+ when :binstub, :names then
34
+ self.reporter << Minitest::Sprint::SprintReporter.new
35
+ when :lines then
36
+ self.reporter << Minitest::Sprint::SprintReporter.new(:lines)
37
+ end
38
+ end
39
+ end
data/lib/minitest/test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "minitest" unless defined? Minitest::Runnable
1
+ require_relative "../minitest" unless defined? Minitest::Runnable
2
2
 
3
3
  module Minitest
4
4
  ##
@@ -8,14 +8,10 @@ module Minitest
8
8
  # See Minitest::Assertions
9
9
 
10
10
  class Test < Runnable
11
- require "minitest/assertions"
11
+ require_relative "assertions"
12
12
  include Minitest::Reportable
13
13
  include Minitest::Assertions
14
14
 
15
- def class_name # :nodoc:
16
- self.class.name # for Minitest::Reportable
17
- end
18
-
19
15
  PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, SystemExit] # :nodoc:
20
16
 
21
17
  SETUP_METHODS = %w[ before_setup setup after_setup ] # :nodoc:
@@ -34,8 +30,8 @@ module Minitest
34
30
 
35
31
  def self.i_suck_and_my_tests_are_order_dependent!
36
32
  class << self
37
- undef_method :test_order if method_defined? :test_order
38
- define_method :test_order do :alpha end
33
+ undef_method :run_order if method_defined? :run_order
34
+ define_method :run_order do :alpha end
39
35
  end
40
36
  end
41
37
 
@@ -58,26 +54,27 @@ module Minitest
58
54
  # tests are awesome.
59
55
 
60
56
  def self.parallelize_me!
57
+ return unless Minitest.parallel_executor
61
58
  include Minitest::Parallel::Test
62
59
  extend Minitest::Parallel::Test::ClassMethods
63
60
  end
64
61
 
65
62
  ##
66
63
  # Returns all instance methods starting with "test_". Based on
67
- # #test_order, the methods are either sorted, randomized
64
+ # #run_order, the methods are either sorted, randomized
68
65
  # (default), or run in parallel.
69
66
 
70
67
  def self.runnable_methods
71
68
  methods = methods_matching(/^test_/)
72
69
 
73
- case self.test_order
70
+ case self.run_order
74
71
  when :random, :parallel then
75
72
  srand Minitest.seed
76
73
  methods.sort.shuffle
77
74
  when :alpha, :sorted then
78
75
  methods.sort
79
76
  else
80
- raise "Unknown test_order: #{self.test_order.inspect}"
77
+ raise "Unknown_order: %p" % [self.run_order]
81
78
  end
82
79
  end
83
80
 
@@ -233,5 +230,3 @@ module Minitest
233
230
  extend Guard
234
231
  end # Test
235
232
  end
236
-
237
- require "minitest/unit" if ENV["MT_COMPAT"] # compatibility layer only
@@ -44,8 +44,16 @@ module Minitest # :nodoc:
44
44
  WINDOWS = RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ # :nodoc:
45
45
 
46
46
  ##
47
- # Create several test-oriented tasks under +name+. Takes an
48
- # optional block to customize variables.
47
+ # Create several test-oriented tasks under +name+ (default:
48
+ # "test"). Takes an optional block to customize variables.
49
+ # Examples:
50
+ #
51
+ # Minitest::TestTask.create # named "test", all defaults
52
+ #
53
+ # Minitest::TestTask.create do |t|
54
+ # t.warning = false # my tests are noisy
55
+ # t.framework = %(require_relative "./test/helper.rb")
56
+ # end
49
57
 
50
58
  def self.create name = :test, &block
51
59
  task = new name
@@ -69,9 +77,18 @@ module Minitest # :nodoc:
69
77
 
70
78
  ##
71
79
  # The code to load the framework. Defaults to requiring
72
- # minitest/autorun...
80
+ # minitest/autorun.
81
+ #
82
+ # If you have a test helper file that requires minitest/autorun
83
+ # and anything else your project standardizes on, then you'll
84
+ # probably want to change this to:
73
85
  #
74
- # Why do I have this as an option?
86
+ # Minitest::TestTask.create do |t|
87
+ # t.framework = %(require_relative "./test/helper.rb")
88
+ # end
89
+ #
90
+ # or something similar. NOTE: if you do this, then helper must
91
+ # require "minitest/autorun" at the top to start the tests.
75
92
 
76
93
  attr_accessor :framework
77
94
 
@@ -100,6 +117,11 @@ module Minitest # :nodoc:
100
117
 
101
118
  ##
102
119
  # Optional: Additional ruby to run before the test framework is loaded.
120
+ # Example:
121
+ #
122
+ # Minitest::TestTask.create "test:cov" do |t|
123
+ # t.test_prelude = %(require "simplecov")
124
+ # end
103
125
 
104
126
  attr_accessor :test_prelude
105
127
 
@@ -146,20 +168,18 @@ module Minitest # :nodoc:
146
168
  ENV["TESTOPTS"]
147
169
  warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if
148
170
  ENV["FILTER"]
149
- warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if
150
- ENV["N"] && ENV["N"].to_i > 0
151
171
 
152
172
  lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR
153
173
  self.libs[0, 0] = lib_extras
154
174
 
155
- extra_args << "-n" << ENV["N"] if ENV["N"]
156
- extra_args << "-e" << ENV["X"] if ENV["X"]
175
+ extra_args << "-i" << ENV["N"] if ENV["N"]
176
+ extra_args << "-i" << ENV["I"] if ENV["I"]
177
+ extra_args << "-x" << ENV["X"] if ENV["X"]
178
+ extra_args << "-x" << ENV["E"] if ENV["E"]
157
179
  extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"]
158
180
  extra_args.concat Shellwords.split(ENV["FILTER"]) if ENV["FILTER"]
159
181
  extra_args.concat Shellwords.split(ENV["A"]) if ENV["A"]
160
182
 
161
- ENV.delete "N" if ENV["N"]
162
-
163
183
  # TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"]
164
184
  # TODO? ENV["RUBY_FLAGS"]
165
185
 
@@ -281,13 +301,8 @@ module Minitest # :nodoc:
281
301
  end
282
302
 
283
303
  class Work < Queue # :nodoc:
284
- def initialize jobs = [] # :nodoc:
285
- super()
286
-
287
- jobs.each do |job|
288
- self << job
289
- end
290
-
304
+ def initialize jobs # :nodoc:
305
+ super
291
306
  close
292
307
  end
293
308
  end