minitest 4.7.5 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
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