minitest 4.7.5 → 5.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.
data.tar.gz.sig CHANGED
Binary file
data/.autotest CHANGED
@@ -4,7 +4,7 @@ require 'autotest/restart'
4
4
  require 'autotest/rcov' if ENV['RCOV']
5
5
 
6
6
  Autotest.add_hook :initialize do |at|
7
- at.testlib = 'minitest/unit'
7
+ at.testlib = 'minitest/autorun'
8
8
 
9
9
  at.extra_class_map["MiniTest::Spec"] = "test/test_minitest_spec.rb"
10
10
  at.extra_class_map["TestMeta"] = "test/test_minitest_spec.rb"
@@ -18,4 +18,3 @@ end
18
18
 
19
19
  # require 'autotest/rcov'
20
20
  # Autotest::RCov.command = 'rcov_info'
21
-
@@ -1,24 +1,75 @@
1
- === 4.7.5 / 2013-06-21
2
-
3
- * 2 bug fixes:
4
-
5
- * Fix Spec#describe_stack to be thread local.
6
- * Fix multithreaded test failures by defining Time local to mock test namespace
7
-
8
- === 4.7.4 / 2013-05-01
9
-
10
- This is probably the last release of the 4.x series. It will be merged
11
- to ruby and will be put into maintenance mode there.
12
-
13
- I'm not set in stone on this, but at this point further development of
14
- minitest (5+) will be gem-only. It is just too hard to work w/in
15
- ruby-core w/ test-unit compatibility holding minitest development
16
- back.
17
-
18
- * 2 minor enhancements:
19
-
20
- * Added count/size to ParallelEach to fix use w/in stdlib's test/unit. :( (btaitelb)
21
- * Allow disabling of info_signal handler in runner. (erikh)
1
+ === 5.0.0 / 2013-05-10
2
+
3
+ Oh god... here we go...
4
+
5
+ Minitest 5:
6
+
7
+ Deaths in the family:
8
+
9
+ * MiniTest.runner is dead. No more manager objects.
10
+ * MiniTest::Unit#record is dead. Use a Reporter instance instead.
11
+ * MiniTest::Unit._run_* is dead. Runnable things are responsible for their own runs.
12
+ * MiniTest::Unit.output is dead. No more centralized IO.
13
+
14
+ Major (oft incompatible) changes:
15
+
16
+ * Renamed MiniTest to Minitest. Your pinkies will thank me. (aliased to MiniTest)
17
+ * Removed MiniTest::Unit entirely. No more manager objects.
18
+ * Added Minitest::Runnable. Everything minitest can run subclasses this.
19
+ * Renamed MiniTest::Unit::TestCase to Minitest::Test (subclassing Runnable).
20
+ * Added Minitest::Benchmark.
21
+ * Your benchmarks need to move to their own subclass.
22
+ * Benchmarks using the spec DSL have to have "Bench" somewhere in their describe.
23
+ * MiniTest::Unit.after_tests moved to Minitest.after_tests
24
+ * MiniTest::Unit.autorun is now Minitest.autorun. Just require minitest/autorun pls.
25
+ * Removed ParallelEach#grep since it isn't used anywhere.
26
+ * Renamed Runnable#__name__ to Runnable#name (but uses @NAME internally).
27
+ * Runnable#run needs to return self. Allows for swapping of results as needed.
28
+
29
+ Minor moves:
30
+
31
+ * Moved Assertions module to minitest/assertions.rb
32
+ * Moved Expectations module to minitest/expectations.rb
33
+ * Moved Test to minitest/test.rb
34
+ * Moved everything else in minitest/unit.rb to minitest.rb
35
+ * minitest/unit.rb is now just a small (user-test only) compatibility layer.
36
+ * Moved most of minitest/pride into minitest/pride_plugin.
37
+ * minitest/pride now just activates pride.
38
+ * Moved ParallelEach under Minitest.
39
+
40
+ Additions:
41
+
42
+ * Added a plugin system that can extend command-line options.
43
+ * Added Minitest.extensions.
44
+ * Added Minitest.reporter (only available during startup).
45
+ * Added Minitest.run(args). This is the very top of any Minitest run.
46
+ * Added Minitest::Reporter. Everything minitest can report goes through here.
47
+ * Minitest.reporter is a composite so you can add your own.
48
+ * Added Minitest::CompositeReporter. Much easier to extend with your own reporters.
49
+ * Added UnexpectedError, an Assertion subclass, to wrap up errors.
50
+ * Minitest::Test#run is now freakin' beautiful. 47 -> 17 loc
51
+
52
+ Other:
53
+
54
+ * Removed Object.infect_with_assertions (it was already dead code).
55
+ * Runnables are responsible for knowing their result_code (eg "." or "F").
56
+ * Minitest.autorun now returns boolean, not exit code.
57
+ * Added FAQ entry for extending via modules. (phiggins)
58
+ * Implement Runnable#dup to cleanse state back to test results. Helps with serialization. pair:tenderlove
59
+ * Moved ParallelEach under Minitest.
60
+ * Runnable#run needs to return self. Allows for swapping of results as needed.
61
+ * Minitest.init_plugins passes down options.
62
+ * Minitest.load_plugins only loads once.
63
+ * Fixed minitest/pride to work with rake test loader again. (tmiller)
64
+ * Added count/size to ParallelEach to fix use w/in stdlib's test/unit. :( (btaitelb)
65
+
66
+ Voodoo:
67
+
68
+ * Removed mutex from minitest.rb (phiggins)
69
+ * Removed mutex from test.rb (phiggins)
70
+ * Removed Minitest::Reporter.synchronize (phiggins)
71
+ * Removed Minitest::Test.synchronize (phiggins)
72
+ * Upon loading minitest/parallel_each, record, capture_io and capture_subprocess_io are doped with synchronization code. (phiggins)
22
73
 
23
74
  === 4.7.3 / 2013-04-20
24
75
 
@@ -5,16 +5,22 @@ README.txt
5
5
  Rakefile
6
6
  design_rationale.rb
7
7
  lib/hoe/minitest.rb
8
+ lib/minitest.rb
9
+ lib/minitest/assertions.rb
8
10
  lib/minitest/autorun.rb
9
11
  lib/minitest/benchmark.rb
12
+ lib/minitest/expectations.rb
10
13
  lib/minitest/hell.rb
11
14
  lib/minitest/mock.rb
12
15
  lib/minitest/parallel_each.rb
13
16
  lib/minitest/pride.rb
17
+ lib/minitest/pride_plugin.rb
14
18
  lib/minitest/spec.rb
19
+ lib/minitest/test.rb
15
20
  lib/minitest/unit.rb
16
21
  test/minitest/metametameta.rb
17
22
  test/minitest/test_minitest_benchmark.rb
18
23
  test/minitest/test_minitest_mock.rb
24
+ test/minitest/test_minitest_reporter.rb
19
25
  test/minitest/test_minitest_spec.rb
20
26
  test/minitest/test_minitest_unit.rb
data/README.txt CHANGED
@@ -90,9 +90,9 @@ Given that you'd like to test the following class:
90
90
 
91
91
  === Unit tests
92
92
 
93
- require 'minitest/autorun'
93
+ require "minitest/autorun"
94
94
 
95
- class TestMeme < MiniTest::Unit::TestCase
95
+ class TestMeme < Minitest::Test
96
96
  def setup
97
97
  @meme = Meme.new
98
98
  end
@@ -112,7 +112,7 @@ Given that you'd like to test the following class:
112
112
 
113
113
  === Specs
114
114
 
115
- require 'minitest/autorun'
115
+ require "minitest/autorun"
116
116
 
117
117
  describe Meme do
118
118
  before do
@@ -138,13 +138,12 @@ https://github.com/zenspider/minitest-matchers
138
138
 
139
139
  === Benchmarks
140
140
 
141
- Add benchmarks to your regular unit tests. If the unit tests fail, the
142
- benchmarks won't run.
141
+ Add benchmarks to your tests.
143
142
 
144
143
  # optionally run benchmarks, good for CI-only work!
145
- require 'minitest/benchmark' if ENV["BENCH"]
144
+ require "minitest/benchmark" if ENV["BENCH"]
146
145
 
147
- class TestMeme < MiniTest::Unit::TestCase
146
+ class TestMeme < Minitest::Benchmark
148
147
  # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000]
149
148
  def bench_my_algorithm
150
149
  assert_performance_linear 0.9999 do |n| # n is a range value
@@ -155,9 +154,10 @@ benchmarks won't run.
155
154
 
156
155
  Or add them to your specs. If you make benchmarks optional, you'll
157
156
  need to wrap your benchmarks in a conditional since the methods won't
158
- be defined.
157
+ be defined. In minitest 5, the describe name needs to match
158
+ /Bench(mark)?$/.
159
159
 
160
- describe Meme do
160
+ describe "Meme Benchmark" do
161
161
  if ENV["BENCH"] then
162
162
  bench_performance_linear "my_algorithm", 0.9999 do |n|
163
163
  100.times do
@@ -190,7 +190,7 @@ Output is tab-delimited to make it easy to paste into a spreadsheet.
190
190
  end
191
191
  end
192
192
 
193
- require 'minitest/autorun'
193
+ require "minitest/autorun"
194
194
 
195
195
  describe MemeAsker do
196
196
  before do
@@ -229,57 +229,30 @@ new non-existing method:
229
229
  ...
230
230
  end
231
231
 
232
- === Customizable Test Runner Types:
233
-
234
- MiniTest::Unit.runner=(runner) provides an easy way of creating custom
235
- test runners for specialized needs. Justin Weiss provides the
236
- following real-world example to create an alternative to regular
237
- fixture loading:
232
+ == Writing Extensions
238
233
 
239
- class MiniTestWithHooks::Unit < MiniTest::Unit
240
- def before_suites
241
- end
234
+ To define a plugin, add a file named minitest/XXX_plugin.rb to your
235
+ project/gem. Minitest will find and require that file using
236
+ Gem.find_files. It will then try to call plugin_XXX_init during
237
+ startup. The option processor will also try to call plugin_XXX_options
238
+ passing the OptionParser instance and the current options hash. This
239
+ lets you register your own command-line options. Here's a totally
240
+ bogus example:
242
241
 
243
- def after_suites
244
- end
242
+ # minitest/bogus_plugin.rb:
245
243
 
246
- def _run_suites(suites, type)
247
- begin
248
- before_suites
249
- super(suites, type)
250
- ensure
251
- after_suites
244
+ module Minitest
245
+ def self.plugin_bogus_options(opts, options)
246
+ opts.on "--myci", "Report results to my CI" do
247
+ options[:myci] = true
248
+ end
252
249
  end
253
- end
254
250
 
255
- def _run_suite(suite, type)
256
- begin
257
- suite.before_suite
258
- super(suite, type)
259
- ensure
260
- suite.after_suite
251
+ def self.plugin_bogus_init
252
+ ARGV << "-p" # all pride, all the time
253
+ self.reporter << MyCI.new if options[:myci]
261
254
  end
262
255
  end
263
- end
264
-
265
- module MiniTestWithTransactions
266
- class Unit < MiniTestWithHooks::Unit
267
- include TestSetupHelper
268
-
269
- def before_suites
270
- super
271
- setup_nested_transactions
272
- # load any data we want available for all tests
273
- end
274
-
275
- def after_suites
276
- teardown_nested_transactions
277
- super
278
- end
279
- end
280
- end
281
-
282
- MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new
283
256
 
284
257
  == FAQ
285
258
 
@@ -329,11 +302,35 @@ or you can extend the Worker class (within the test file!), like:
329
302
  include ::MiniTest::Expectations
330
303
  end
331
304
 
305
+ === How to share code across test classes?
306
+
307
+ Use a module. That's exactly what they're for:
308
+
309
+ module UsefulStuff
310
+ def useful_method
311
+ # ...
312
+ end
313
+ end
314
+
315
+ describe Blah do
316
+ include UsefulStuff
317
+
318
+ def test_whatever
319
+ # useful_method available here
320
+ end
321
+ end
322
+
323
+ Remember, `describe` simply creates test classes. It's just ruby at
324
+ the end of the day and all your normal Good Ruby Rules (tm) apply. If
325
+ you want to extend your test using setup/teardown via a module, just
326
+ make sure you ALWAYS call super. before/after automatically call super
327
+ for you, so make sure you don't do it twice.
328
+
332
329
  == Known Extensions:
333
330
 
334
- capybara_minitest_spec :: Bridge between Capybara RSpec matchers and MiniTest::Spec expectations (e.g. page.must_have_content('Title')).
331
+ capybara_minitest_spec :: Bridge between Capybara RSpec matchers and MiniTest::Spec expectations (e.g. page.must_have_content("Title")).
335
332
  minispec-metadata :: Metadata for describe/it blocks
336
- (e.g. `it 'requires JS driver', js: true do`)
333
+ (e.g. `it "requires JS driver", js: true do`)
337
334
  minitest-ansi :: Colorize minitest output with ANSI colors.
338
335
  minitest-around :: Around block for minitest. An alternative to setup/teardown dance.
339
336
  minitest-capistrano :: Assertions and expectations for testing Capistrano recipes
@@ -416,11 +413,11 @@ Authors... Please send me a pull request with a description of your minitest ext
416
413
  sudo gem install minitest
417
414
 
418
415
  On 1.9, you already have it. To get newer candy you can still install
419
- the gem, but you'll need to activate the gem explicitly to use it:
416
+ the gem, and then requiring "minitest/autorun" should automatically
417
+ pull it in. If not, you'll need to do it yourself:
420
418
 
421
- require 'rubygems'
422
- gem 'minitest' # ensures you're using the gem, and not the built in MT
423
- require 'minitest/autorun'
419
+ gem "minitest" # ensures you"re using the gem, and not the built-in MT
420
+ require "minitest/autorun"
424
421
 
425
422
  # ... usual testing stuffs ...
426
423
 
@@ -1,6 +1,6 @@
1
1
  # Specs: # Equivalent Unit Tests:
2
2
  ###############################################################################
3
- describe Thingy do # class TestThingy < MiniTest::Unit::TestCase
3
+ describe Thingy do # class TestThingy < Minitest::Test
4
4
  before do # def setup
5
5
  do_some_setup # super
6
6
  end # do_some_setup
@@ -5,18 +5,22 @@ end
5
5
 
6
6
  module Hoe::Minitest
7
7
  def initialize_minitest
8
+ dir = "../../minitest/dev/lib"
9
+ Hoe.add_include_dirs dir if File.directory? dir
10
+
8
11
  gem "minitest"
9
- require 'minitest/unit'
10
- version = MiniTest::Unit::VERSION.split(/\./).first(2).join(".")
12
+ require "minitest"
13
+ version = Minitest::VERSION.split(/\./).first(2).join(".")
11
14
 
12
- dependency 'minitest', "~> #{version}", :development unless
13
- self.name == "minitest"
15
+ dependency "minitest", "~> #{version}", :development unless
16
+ self.name == "minitest" or ENV["MT_NO_ISOLATE"]
14
17
  end
15
18
 
16
19
  def define_minitest_tasks
17
20
  self.testlib = :minitest
18
21
 
19
22
  # make sure we use the gemmed minitest on 1.9
20
- self.test_prelude = 'gem "minitest"'
23
+ self.test_prelude = 'gem "minitest"' unless
24
+ self.name == "minitest" or ENV["MT_NO_ISOLATE"]
21
25
  end
22
26
  end
@@ -0,0 +1,639 @@
1
+ require "optparse"
2
+
3
+ ##
4
+ # :include: README.txt
5
+
6
+ module Minitest
7
+ VERSION = "5.0.0" # :nodoc:
8
+
9
+ @@installed_at_exit ||= false
10
+ @@after_run = []
11
+ @extensions = []
12
+
13
+ mc = (class << self; self; end)
14
+
15
+ ##
16
+ # Filter object for backtraces.
17
+
18
+ mc.send :attr_accessor, :backtrace_filter
19
+
20
+ ##
21
+ # Reporter object to be used for all runs.
22
+ #
23
+ # NOTE: This accessor is only available during setup, not during runs.
24
+
25
+ mc.send :attr_accessor, :reporter
26
+
27
+ ##
28
+ # Names of known extension plugins.
29
+
30
+ mc.send :attr_accessor, :extensions
31
+
32
+ ##
33
+ # Registers Minitest to run at process exit
34
+
35
+ def self.autorun
36
+ at_exit {
37
+ next if $! and not $!.kind_of? SystemExit
38
+
39
+ exit_code = nil
40
+
41
+ at_exit {
42
+ @@after_run.reverse_each(&:call)
43
+ exit exit_code || false
44
+ }
45
+
46
+ exit_code = Minitest.run ARGV
47
+ } unless @@installed_at_exit
48
+ @@installed_at_exit = true
49
+ end
50
+
51
+ ##
52
+ # A simple hook allowing you to run a block of code after everything
53
+ # is done running. Eg:
54
+ #
55
+ # Minitest.after_run { p $debugging_info }
56
+
57
+ def self.after_run &block
58
+ @@after_run << block
59
+ end
60
+
61
+ def self.init_plugins options # :nodoc:
62
+ self.extensions.each do |name|
63
+ msg = "plugin_#{name}_init"
64
+ send msg, options if self.respond_to? msg
65
+ end
66
+ end
67
+
68
+ def self.load_plugins # :nodoc:
69
+ return unless self.extensions.empty?
70
+
71
+ Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
72
+ require plugin_path
73
+ name = File.basename plugin_path, "_plugin.rb"
74
+ self.extensions << name
75
+ end
76
+ end
77
+
78
+ ##
79
+ # This is the top-level run method. Everything starts from here. It
80
+ # tells each Runnable sub-class to run, and each of those are
81
+ # responsible for doing whatever they do.
82
+ #
83
+ # The overall structure of a run looks like this:
84
+ #
85
+ # Minitest.autorun
86
+ # Minitest.run(args)
87
+ # __run(reporter, options)
88
+ # Runnable.runnables.each
89
+ # runnable.run(reporter, options)
90
+ # self.runnable_methods.each
91
+ # self.new.run runnable_method
92
+
93
+ def self.run args = []
94
+ self.load_plugins
95
+
96
+ options = process_args args
97
+
98
+ reporter = CompositeReporter.new
99
+ reporter << Reporter.new(options[:io], options)
100
+
101
+ self.reporter = reporter # this makes it available to plugins
102
+ self.init_plugins options
103
+ self.reporter = nil # runnables shouldn't depend on the reporter, ever
104
+
105
+ reporter.run_and_report do
106
+ __run reporter, options
107
+ end
108
+
109
+ reporter.passed?
110
+ end
111
+
112
+ ##
113
+ # Internal run method. Responsible for telling all Runnable
114
+ # sub-classes to run.
115
+ #
116
+ # NOTE: this method is redefined in parallel_each.rb, which is
117
+ # loaded if a Runnable calls parallelize_me!.
118
+
119
+ def self.__run reporter, options
120
+ Runnable.runnables.each do |runnable|
121
+ runnable.run reporter, options
122
+ end
123
+ end
124
+
125
+ def self.process_args args = [] # :nodoc:
126
+ options = {
127
+ :io => $stdout,
128
+ }
129
+ orig_args = args.dup
130
+
131
+ OptionParser.new do |opts|
132
+ opts.banner = "minitest options:"
133
+ opts.version = Minitest::VERSION
134
+
135
+ opts.on "-h", "--help", "Display this help." do
136
+ puts opts
137
+ exit
138
+ end
139
+
140
+ opts.on "-s", "--seed SEED", Integer, "Sets random seed" do |m|
141
+ options[:seed] = m.to_i
142
+ end
143
+
144
+ opts.on "-v", "--verbose", "Verbose. Show progress processing files." do
145
+ options[:verbose] = true
146
+ end
147
+
148
+ opts.on "-n", "--name PATTERN","Filter run on /pattern/ or string." do |a|
149
+ options[:filter] = a
150
+ end
151
+
152
+ unless extensions.empty?
153
+ opts.separator ""
154
+ opts.separator "Known extensions: #{extensions.join(', ')}"
155
+
156
+ extensions.each do |meth|
157
+ msg = "plugin_#{meth}_options"
158
+ send msg, opts, options if self.respond_to?(msg)
159
+ end
160
+ end
161
+
162
+ begin
163
+ opts.parse! args
164
+ rescue OptionParser::InvalidOption => e
165
+ puts
166
+ puts e
167
+ puts
168
+ puts opts
169
+ exit 1
170
+ end
171
+
172
+ orig_args -= args
173
+ end
174
+
175
+ unless options[:seed] then
176
+ srand
177
+ options[:seed] = srand % 0xFFFF
178
+ orig_args << "--seed" << options[:seed].to_s
179
+ end
180
+
181
+ srand options[:seed]
182
+
183
+ options[:args] = orig_args.map { |s|
184
+ s =~ /[\s|&<>$()]/ ? s.inspect : s
185
+ }.join " "
186
+
187
+ options
188
+ end
189
+
190
+ def self.filter_backtrace bt # :nodoc:
191
+ backtrace_filter.filter bt
192
+ end
193
+
194
+ ##
195
+ # Represents anything "runnable", like Test, Spec, Benchmark, or
196
+ # whatever you can dream up.
197
+ #
198
+ # Subclasses of this are automatically registered and available in
199
+ # Runnable.runnables.
200
+
201
+ class Runnable
202
+ ##
203
+ # Number of assertions executed in this run.
204
+
205
+ attr_accessor :assertions
206
+
207
+ ##
208
+ # An assertion raised during the run, if any.
209
+
210
+ attr_accessor :failures
211
+
212
+ ##
213
+ # Name of the run.
214
+
215
+ def name
216
+ @NAME
217
+ end
218
+
219
+ ##
220
+ # Set the name of the run.
221
+
222
+ def name= o
223
+ @NAME = o
224
+ end
225
+
226
+ def self.inherited klass # :nodoc:
227
+ self.runnables << klass
228
+ super
229
+ end
230
+
231
+ ##
232
+ # Returns all instance methods matching the pattern +re+.
233
+
234
+ def self.methods_matching re
235
+ public_instance_methods(true).grep(re).map(&:to_s)
236
+ end
237
+
238
+ def self.reset # :nodoc:
239
+ @@runnables = []
240
+ end
241
+
242
+ reset
243
+
244
+ ##
245
+ # Responsible for running all runnable methods in a given class,
246
+ # each in its own instance. Each instance is passed to the
247
+ # reporter to record.
248
+
249
+ def self.run reporter, options = {}
250
+ filter = options[:filter] || '/./'
251
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
252
+
253
+ filtered_methods = self.runnable_methods.find_all { |m|
254
+ filter === m || filter === "#{self}##{m}"
255
+ }
256
+
257
+ filtered_methods.each do |method_name|
258
+ result = self.new(method_name).run
259
+ raise "#{self}#run _must_ return self" unless self === result
260
+ reporter.record result
261
+ end
262
+ end
263
+
264
+ ##
265
+ # Each subclass of Runnable is responsible for overriding this
266
+ # method to return all runnable methods. See #methods_matching.
267
+
268
+ def self.runnable_methods
269
+ raise NotImplementedError, "subclass responsibility"
270
+ end
271
+
272
+ ##
273
+ # Returns all subclasses of Runnable.
274
+
275
+ def self.runnables
276
+ @@runnables
277
+ end
278
+
279
+ def dup # :nodoc:
280
+ obj = self.class.new self.name
281
+
282
+ obj.name = self.name
283
+ obj.failures = self.failures.dup
284
+ obj.assertions = self.assertions
285
+
286
+ obj
287
+ end
288
+
289
+ def failure # :nodoc:
290
+ self.failures.first
291
+ end
292
+
293
+ def initialize name # :nodoc:
294
+ self.name = name
295
+ self.failures = []
296
+ self.assertions = 0
297
+ end
298
+
299
+ ##
300
+ # Runs a single method. Needs to return self.
301
+
302
+ def run
303
+ raise NotImplementedError, "subclass responsibility"
304
+ end
305
+
306
+ ##
307
+ # Did this run pass?
308
+ #
309
+ # Note: skipped runs are not considered passing, but they don't
310
+ # cause the process to exit non-zero.
311
+
312
+ def passed?
313
+ raise NotImplementedError, "subclass responsibility"
314
+ end
315
+
316
+ ##
317
+ # Returns a single character string to print based on the result
318
+ # of the run. Eg ".", "F", or "E".
319
+
320
+ def result_code
321
+ raise NotImplementedError, "subclass responsibility"
322
+ end
323
+
324
+ ##
325
+ # Was this run skipped? See #passed? for more information.
326
+
327
+ def skipped?
328
+ raise NotImplementedError, "subclass responsibility"
329
+ end
330
+ end
331
+
332
+ ##
333
+ # Collects and reports the result of all runs.
334
+
335
+ class Reporter
336
+ ##
337
+ # The count of assertions run.
338
+
339
+ attr_accessor :assertions
340
+
341
+ ##
342
+ # The count of runnable methods ran.
343
+
344
+ attr_accessor :count
345
+
346
+ ##
347
+ # The IO used to report.
348
+
349
+ attr_accessor :io
350
+
351
+ ##
352
+ # Command-line options for this run.
353
+
354
+ attr_accessor :options
355
+
356
+ ##
357
+ # The results of all the runs. (Non-passing only to cut down on memory)
358
+
359
+ attr_accessor :results
360
+
361
+ ##
362
+ # The start time of the run.
363
+
364
+ attr_accessor :start_time
365
+
366
+ attr_accessor :sync, :old_sync # :nodoc:
367
+
368
+ def initialize io = $stdout, options = {} # :nodoc:
369
+ self.io = io
370
+ self.options = options
371
+
372
+ self.assertions = 0
373
+ self.count = 0
374
+ self.results = []
375
+ self.start_time = nil
376
+ end
377
+
378
+ ##
379
+ # Did this run pass?
380
+
381
+ def passed?
382
+ results.all?(&:skipped?)
383
+ end
384
+
385
+ ##
386
+ # Top-level method to ensure that start and report are called.
387
+ # Yields to the caller.
388
+
389
+ def run_and_report
390
+ start
391
+
392
+ yield
393
+
394
+ report
395
+ end
396
+
397
+ ##
398
+ # Starts reporting on the run.
399
+
400
+ def start
401
+ self.sync = io.respond_to? :"sync=" # stupid emacs
402
+ self.old_sync, io.sync = io.sync, true if self.sync
403
+
404
+ self.start_time = Time.now
405
+
406
+ io.puts "Run options: #{options[:args]}"
407
+ io.puts
408
+ io.puts "# Running:"
409
+ io.puts
410
+ end
411
+
412
+ ##
413
+ # Record a result and output the Runnable#result_code. Stores the
414
+ # result of the run if the run did not pass.
415
+
416
+ def record result
417
+ self.count += 1
418
+ self.assertions += result.assertions
419
+
420
+ io.print "%s#%s = %.2f s = " % [result.class, result.name, result.time] if
421
+ options[:verbose]
422
+ io.print result.result_code
423
+ io.puts if options[:verbose]
424
+
425
+ results << result if not result.passed? or result.skipped?
426
+ end
427
+
428
+ ##
429
+ # Outputs the summary of the run.
430
+
431
+ def report
432
+ aggregate = results.group_by { |r| r.failure.class }
433
+ aggregate.default = [] # dumb. group_by should provide this
434
+
435
+ f = aggregate[Assertion].size
436
+ e = aggregate[UnexpectedError].size
437
+ s = aggregate[Skip].size
438
+ t = Time.now - start_time
439
+
440
+ io.puts # finish the dots
441
+ io.puts
442
+ io.puts "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." %
443
+ [t, count / t, self.assertions / t]
444
+
445
+ format = "%d runs, %d assertions, %d failures, %d errors, %d skips"
446
+ summary = format % [count, self.assertions, f, e, s]
447
+
448
+ filtered_results = results.dup
449
+ filtered_results.reject!(&:skipped?) unless options[:verbose]
450
+
451
+ filtered_results.each_with_index do |result, i|
452
+ io.puts "\n%3d) %s" % [i+1, result]
453
+ end
454
+
455
+ io.puts
456
+ io.puts summary
457
+
458
+ io.sync = self.old_sync if self.sync
459
+ end
460
+ end
461
+
462
+ ##
463
+ # Dispatch to multiple reporters as one.
464
+
465
+ class CompositeReporter < Reporter
466
+ ##
467
+ # The list of reporters to dispatch to.
468
+
469
+ attr_accessor :reporters
470
+
471
+ def initialize *reporters # :nodoc:
472
+ self.reporters = reporters
473
+ end
474
+
475
+ ##
476
+ # Add another reporter to the mix.
477
+
478
+ def << reporter
479
+ self.reporters << reporter
480
+ end
481
+
482
+ def passed? # :nodoc:
483
+ self.reporters.all?(&:passed?)
484
+ end
485
+
486
+ def start # :nodoc:
487
+ self.reporters.each(&:start)
488
+ end
489
+
490
+ def record result # :nodoc:
491
+ self.reporters.each do |reporter|
492
+ reporter.record result
493
+ end
494
+ end
495
+
496
+ def report # :nodoc:
497
+ self.reporters.each(&:report)
498
+ end
499
+ end
500
+
501
+ ##
502
+ # Represents run failures.
503
+
504
+ class Assertion < Exception
505
+ def error # :nodoc:
506
+ self
507
+ end
508
+
509
+ ##
510
+ # Where was this run before an assertion was raised?
511
+
512
+ def location
513
+ last_before_assertion = ""
514
+ self.backtrace.reverse_each do |s|
515
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
516
+ last_before_assertion = s
517
+ end
518
+ last_before_assertion.sub(/:in .*$/, "")
519
+ end
520
+
521
+ def result_code # :nodoc:
522
+ result_label[0, 1]
523
+ end
524
+
525
+ def result_label # :nodoc:
526
+ "Failure"
527
+ end
528
+ end
529
+
530
+ ##
531
+ # Assertion raised when skipping a run.
532
+
533
+ class Skip < Assertion
534
+ def result_label # :nodoc:
535
+ "Skipped"
536
+ end
537
+ end
538
+
539
+ ##
540
+ # Assertion wrapping an unexpected error that was raised during a run.
541
+
542
+ class UnexpectedError < Assertion
543
+ attr_accessor :exception # :nodoc:
544
+
545
+ def initialize exception # :nodoc:
546
+ super
547
+ self.exception = exception
548
+ end
549
+
550
+ def backtrace # :nodoc:
551
+ self.exception.backtrace
552
+ end
553
+
554
+ def error # :nodoc:
555
+ self.exception
556
+ end
557
+
558
+ def message # :nodoc:
559
+ bt = Minitest::filter_backtrace(self.backtrace).join "\n "
560
+ "#{self.exception.class}: #{self.exception.message}\n #{bt}"
561
+ end
562
+
563
+ def result_label # :nodoc:
564
+ "Error"
565
+ end
566
+ end
567
+
568
+ ##
569
+ # Provides a simple set of guards that you can use in your tests
570
+ # to skip execution if it is not applicable. These methods are
571
+ # mixed into TestCase as both instance and class methods so you
572
+ # can use them inside or outside of the test methods.
573
+ #
574
+ # def test_something_for_mri
575
+ # skip "bug 1234" if jruby?
576
+ # # ...
577
+ # end
578
+ #
579
+ # if windows? then
580
+ # # ... lots of test methods ...
581
+ # end
582
+
583
+ module Guard
584
+
585
+ ##
586
+ # Is this running on jruby?
587
+
588
+ def jruby? platform = RUBY_PLATFORM
589
+ "java" == platform
590
+ end
591
+
592
+ ##
593
+ # Is this running on mri?
594
+
595
+ def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
596
+ "maglev" == platform
597
+ end
598
+
599
+ ##
600
+ # Is this running on mri?
601
+
602
+ def mri? platform = RUBY_DESCRIPTION
603
+ /^ruby/ =~ platform
604
+ end
605
+
606
+ ##
607
+ # Is this running on rubinius?
608
+
609
+ def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
610
+ "rbx" == platform
611
+ end
612
+
613
+ ##
614
+ # Is this running on windows?
615
+
616
+ def windows? platform = RUBY_PLATFORM
617
+ /mswin|mingw/ =~ platform
618
+ end
619
+ end
620
+
621
+ class BacktraceFilter # :nodoc:
622
+ def filter bt
623
+ return ["No backtrace"] unless bt
624
+
625
+ return bt.dup if $DEBUG
626
+
627
+ new_bt = bt.take_while { |line| line !~ /lib\/minitest/ }
628
+ new_bt = bt.select { |line| line !~ /lib\/minitest/ } if new_bt.empty?
629
+ new_bt = bt.dup if new_bt.empty?
630
+
631
+ new_bt
632
+ end
633
+ end
634
+
635
+ self.backtrace_filter = BacktraceFilter.new
636
+ end
637
+
638
+ require "minitest/test"
639
+ require "minitest/unit" unless defined?(MiniTest) # compatibility layer only