spec 5.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +34 -0
  3. data/.gitignore +3 -0
  4. data/History.txt +911 -0
  5. data/Manifest.txt +26 -0
  6. data/README.txt +497 -0
  7. data/Rakefile +214 -0
  8. data/design_rationale.rb +52 -0
  9. data/lib/hoe/minitest.rb +26 -0
  10. data/lib/minitest/assertions.rb +649 -0
  11. data/lib/minitest/autorun.rb +12 -0
  12. data/lib/minitest/benchmark.rb +423 -0
  13. data/lib/minitest/expectations.rb +268 -0
  14. data/lib/minitest/hell.rb +11 -0
  15. data/lib/minitest/mock.rb +220 -0
  16. data/lib/minitest/parallel_each.rb +120 -0
  17. data/lib/minitest/pride.rb +4 -0
  18. data/lib/minitest/pride_plugin.rb +143 -0
  19. data/lib/minitest/spec.rb +292 -0
  20. data/lib/minitest/test.rb +272 -0
  21. data/lib/minitest/unit.rb +45 -0
  22. data/lib/minitest.rb +839 -0
  23. data/lib/spec.rb +3 -0
  24. data/readme.md +7 -0
  25. data/release_notes.md +49 -0
  26. data/spec.gemspec +36 -0
  27. data/test/manual/appium.rb +14 -0
  28. data/test/manual/appium_after_last.rb +24 -0
  29. data/test/manual/appium_before_first.rb +23 -0
  30. data/test/manual/assert.rb +61 -0
  31. data/test/manual/before_first_0.rb +27 -0
  32. data/test/manual/before_first_1.rb +29 -0
  33. data/test/manual/debug.rb +37 -0
  34. data/test/manual/do_end.rb +31 -0
  35. data/test/manual/raise.rb +61 -0
  36. data/test/manual/run2.rb +74 -0
  37. data/test/manual/run3.rb +91 -0
  38. data/test/manual/setup.rb +13 -0
  39. data/test/manual/simple.rb +19 -0
  40. data/test/manual/simple2.rb +20 -0
  41. data/test/manual/t.rb +11 -0
  42. data/test/manual/trace.rb +19 -0
  43. data/test/manual/trace2.rb +15 -0
  44. data/test/minitest/metametameta.rb +78 -0
  45. data/test/minitest/test_helper.rb +20 -0
  46. data/test/minitest/test_minitest_benchmark.rb +131 -0
  47. data/test/minitest/test_minitest_mock.rb +490 -0
  48. data/test/minitest/test_minitest_reporter.rb +270 -0
  49. data/test/minitest/test_minitest_spec.rb +794 -0
  50. data/test/minitest/test_minitest_unit.rb +1846 -0
  51. metadata +147 -0
data/lib/minitest.rb ADDED
@@ -0,0 +1,839 @@
1
+ require "optparse"
2
+ require 'chronic_duration'
3
+
4
+ ##
5
+ # :include: README.txt
6
+
7
+ module Minitest
8
+ VERSION = '5.0.14' # :nodoc:
9
+ DATE = '2013-08-07' # :nodoc:
10
+
11
+ @@installed_at_exit ||= false
12
+ @@after_run = []
13
+ @extensions = []
14
+
15
+ mc = (class << self; self; end)
16
+
17
+ ##
18
+ # Filter object for backtraces.
19
+
20
+ mc.send :attr_accessor, :backtrace_filter
21
+
22
+ ##
23
+ # Reporter object to be used for all runs.
24
+ #
25
+ # NOTE: This accessor is only available during setup, not during runs.
26
+
27
+ mc.send :attr_accessor, :reporter
28
+
29
+ ##
30
+ # Names of known extension plugins.
31
+
32
+ mc.send :attr_accessor, :extensions
33
+
34
+ @@trace_set = false
35
+ mc.send :attr_accessor, :trace_set
36
+
37
+ ##
38
+ # Registers Minitest to run at process exit
39
+
40
+ def self.autorun
41
+ at_exit {
42
+ next if $! and not $!.kind_of? SystemExit
43
+
44
+ exit_code = nil
45
+
46
+ at_exit {
47
+ @@after_run.reverse_each(&:call)
48
+ exit exit_code || false
49
+ }
50
+
51
+ exit_code = Minitest.run ARGV
52
+ } unless @@installed_at_exit
53
+ @@installed_at_exit = true
54
+ end
55
+
56
+ ##
57
+ # A simple hook allowing you to run a block of code after everything
58
+ # is done running. Eg:
59
+ #
60
+ # Minitest.after_run { p $debugging_info }
61
+
62
+ def self.after_run &block
63
+ @@after_run << block
64
+ end
65
+
66
+ def self.init_plugins options # :nodoc:
67
+ self.extensions.each do |name|
68
+ msg = "plugin_#{name}_init"
69
+ send msg, options if self.respond_to? msg
70
+ end
71
+ end
72
+
73
+ def self.load_plugins # :nodoc:
74
+ return unless self.extensions.empty?
75
+
76
+ seen = {}
77
+
78
+ Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
79
+ name = File.basename plugin_path, "_plugin.rb"
80
+
81
+ next if seen[name]
82
+ seen[name] = true
83
+
84
+ require plugin_path
85
+ self.extensions << name
86
+ end
87
+ end
88
+
89
+ ##
90
+ # This is the top-level run method. Everything starts from here. It
91
+ # tells each Runnable sub-class to run, and each of those are
92
+ # responsible for doing whatever they do.
93
+ #
94
+ # The overall structure of a run looks like this:
95
+ #
96
+ # Minitest.autorun
97
+ # Minitest.run(args)
98
+ # __run(reporter, options)
99
+ # Runnable.runnables.each
100
+ # runnable.run(reporter, options)
101
+ # self.runnable_methods.each
102
+ # self.new(runnable_method).run
103
+
104
+ def self.run args = []
105
+ self.load_plugins
106
+
107
+ options = process_args args
108
+
109
+ reporter = CompositeReporter.new
110
+ reporter << ProgressReporter.new(options[:io], options)
111
+ reporter << SummaryReporter.new(options[:io], options)
112
+
113
+ self.reporter = reporter # this makes it available to plugins
114
+ self.init_plugins options
115
+ self.reporter = nil # runnables shouldn't depend on the reporter, ever
116
+
117
+ reporter.start
118
+ __run reporter, options
119
+ reporter.report
120
+
121
+ reporter.passed?
122
+ end
123
+
124
+ ##
125
+ # Internal run method. Responsible for telling all Runnable
126
+ # sub-classes to run.
127
+ #
128
+ # NOTE: this method is redefined in parallel_each.rb, which is
129
+ # loaded if a Runnable calls parallelize_me!.
130
+
131
+ def self.__run reporter, options
132
+ Runnable.runnables.each do |runnable|
133
+ runnable.run reporter, options
134
+ end
135
+ end
136
+
137
+ ##
138
+ # Trace file source to :io (default $stdout)
139
+ #
140
+ # spec_opts = {}
141
+ #
142
+ # @param :trace [Array<String>] the files to trace
143
+ # @param :io [IO] io to print to
144
+ def self.trace_specs spec_opts
145
+ # ensure trace is set once
146
+ return if trace_set
147
+ self.trace_set = true
148
+
149
+ targets = []
150
+ files = {}
151
+ last_file = ''
152
+ last_line = -1
153
+
154
+ files_to_trace = spec_opts.fetch(:trace, []);
155
+ io = spec_opts.fetch(:io, $stdout)
156
+ color = spec_opts.fetch(:color, "\e[32m") # ANSI.green default
157
+ # target only existing readable files
158
+ files_to_trace.each { |f| targets.push(f) if File.exists?(f) && File
159
+ .readable?(f) }
160
+ return if targets.empty?
161
+
162
+ set_trace_func(lambda do |event, file, line, id, binding, classname|
163
+ return unless targets.include? file
164
+
165
+ # never repeat a line
166
+ return if file == last_file && line == last_line
167
+
168
+ file_sym = file.intern
169
+ files[file_sym] = IO.readlines(file) if files[file_sym].nil?
170
+ lines = files[file_sym]
171
+
172
+ # arrays are 0 indexed and line numbers start at one.
173
+ io.print color if color # ANSI code
174
+ io.puts lines[ line - 1]
175
+ io.print "\e[0m" if color # ANSI.clear
176
+
177
+ last_file = file
178
+ last_line = line
179
+
180
+ end)
181
+ end
182
+
183
+ ##
184
+ # Run specs. Does not print dots (ProgressReporter)
185
+ #
186
+ # spec_opts
187
+ # @param :io [Array<String>] defaults to $stdout
188
+ # @param :trace [Array<String>] files to trace
189
+
190
+ def self.run_specs spec_opts={}
191
+ options = { :io => spec_opts.fetch(:io, $stdout) }
192
+ reporter = Minitest::CompositeReporter.new
193
+ reporter << Minitest::SummaryReporter.new(options[:io], options)
194
+ reporter.start
195
+
196
+ trace_specs spec_opts
197
+
198
+ begin
199
+ Minitest.__run reporter, options
200
+ reporter.reporters.each { |r| r.report }
201
+ rescue Minitest::Runnable::ExitAfterFirstFail
202
+ # Minitest calls .report on exception
203
+ end
204
+ end
205
+
206
+ def self.process_args args = [] # :nodoc:
207
+ options = { :io => $stdout }
208
+ orig_args = args.dup
209
+
210
+ OptionParser.new do |opts|
211
+ opts.banner = "minitest options:"
212
+ opts.version = Minitest::VERSION
213
+
214
+ opts.on "-h", "--help", "Display this help." do
215
+ puts opts
216
+ exit
217
+ end
218
+
219
+ opts.on "-s", "--seed SEED", Integer, "Sets random seed" do |m|
220
+ options[:seed] = m.to_i
221
+ end
222
+
223
+ opts.on "-v", "--verbose", "Verbose. Show progress processing files." do
224
+ options[:verbose] = true
225
+ end
226
+
227
+ opts.on "-n", "--name PATTERN","Filter run on /pattern/ or string." do |a|
228
+ options[:filter] = a
229
+ end
230
+
231
+ unless extensions.empty?
232
+ opts.separator ""
233
+ opts.separator "Known extensions: #{extensions.join(', ')}"
234
+
235
+ extensions.each do |meth|
236
+ msg = "plugin_#{meth}_options"
237
+ send msg, opts, options if self.respond_to?(msg)
238
+ end
239
+ end
240
+
241
+ begin
242
+ opts.parse! args
243
+ rescue OptionParser::InvalidOption => e
244
+ puts
245
+ puts e
246
+ puts
247
+ puts opts
248
+ exit 1
249
+ end
250
+
251
+ orig_args -= args
252
+ end
253
+
254
+ unless options[:seed] then
255
+ srand
256
+ options[:seed] = srand % 0xFFFF
257
+ orig_args << "--seed" << options[:seed].to_s
258
+ end
259
+
260
+ srand options[:seed]
261
+
262
+ options[:args] = orig_args.map { |s|
263
+ s =~ /[\s|&<>$()]/ ? s.inspect : s
264
+ }.join " "
265
+
266
+ options
267
+ end
268
+
269
+ def self.filter_backtrace bt # :nodoc:
270
+ backtrace_filter.filter bt
271
+ end
272
+
273
+ ##
274
+ # Represents anything "runnable", like Test, Spec, Benchmark, or
275
+ # whatever you can dream up.
276
+ #
277
+ # Subclasses of this are automatically registered and available in
278
+ # Runnable.runnables.
279
+
280
+ class Runnable
281
+ ##
282
+ # Number of assertions executed in this run.
283
+
284
+ attr_accessor :assertions
285
+
286
+ ##
287
+ # An assertion raised during the run, if any.
288
+
289
+ attr_accessor :failures
290
+
291
+ ##
292
+ # Name of the run.
293
+
294
+ def name
295
+ @NAME
296
+ end
297
+
298
+ ##
299
+ # Set the name of the run.
300
+
301
+ def name= o
302
+ @NAME = o
303
+ end
304
+
305
+ def self.inherited klass # :nodoc:
306
+ self.runnables << klass
307
+ super
308
+ end
309
+
310
+ ##
311
+ # Returns all instance methods matching the pattern +re+.
312
+
313
+ def self.methods_matching re
314
+ public_instance_methods(true).grep(re).map(&:to_s)
315
+ end
316
+
317
+ def self.reset # :nodoc:
318
+ @@runnables = []
319
+ end
320
+
321
+ reset
322
+
323
+ class ExitAfterFirstFail < RuntimeError; end
324
+
325
+ def self.check_failures result, reporter
326
+ if !result.failures.empty?
327
+ begin
328
+ reporter.reporters.each { |r| r.report }
329
+ ensure
330
+ raise ExitAfterFirstFail
331
+ end
332
+ end
333
+ end
334
+
335
+ ##
336
+ # Responsible for running all runnable methods in a given class,
337
+ # each in its own instance. Each instance is passed to the
338
+ # reporter to record.
339
+
340
+ def self.run reporter, options = {}
341
+ filter = options[:filter] || '/./'
342
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
343
+
344
+ filtered_methods = self.runnable_methods.find_all { |m|
345
+ filter === m || filter === "#{self}##{m}"
346
+ }
347
+
348
+ begin
349
+ # before_first
350
+ method1 = self.new(filtered_methods.first)
351
+ # run method and capture exceptions.
352
+ method1.capture_exceptions do
353
+ method1.before_first_method
354
+ end
355
+ # save exceptions to reporter and check for failures
356
+ with_info_handler reporter do
357
+ # only record if failures not empty, otherwise
358
+ # the count (runs) are messed up. each call to .record
359
+ # increases count by one.
360
+ if !method1.failures.empty?
361
+ reporter.record method1
362
+ check_failures method1, reporter
363
+ end
364
+
365
+ # run the other methods
366
+ filtered_methods.each do |method_name|
367
+ result = self.new(method_name).run
368
+ raise "#{self}#run _must_ return self" unless self === result
369
+ reporter.record result
370
+ check_failures result, reporter
371
+ end
372
+ end
373
+ ensure # ensure after last runs
374
+ # after_last
375
+ # init method1 again
376
+ method1 = self.new(filtered_methods.first)
377
+ method1.capture_exceptions do
378
+ method1.after_last_method
379
+ end
380
+ with_info_handler reporter do
381
+ if !method1.failures.empty?
382
+ reporter.record method1
383
+ check_failures method1, reporter
384
+ end
385
+ end
386
+ end
387
+ end
388
+
389
+ def before_first_method; end
390
+ def after_last_method; end
391
+
392
+ def self.with_info_handler reporter, &block # :nodoc:
393
+ handler = lambda do
394
+ unless reporter.passed? then
395
+ warn "Current results:"
396
+ warn ""
397
+ warn reporter.reporters.first
398
+ warn ""
399
+ end
400
+ end
401
+
402
+ on_signal "INFO", handler, &block
403
+ end
404
+
405
+ def self.on_signal name, action # :nodoc:
406
+ supported = Signal.list[name]
407
+
408
+ old_trap = trap name do
409
+ old_trap.call if old_trap.respond_to? :call
410
+ action.call
411
+ end if supported
412
+
413
+ yield
414
+ ensure
415
+ trap name, old_trap if supported
416
+ end
417
+
418
+ ##
419
+ # Each subclass of Runnable is responsible for overriding this
420
+ # method to return all runnable methods. See #methods_matching.
421
+
422
+ def self.runnable_methods
423
+ raise NotImplementedError, "subclass responsibility"
424
+ end
425
+
426
+ ##
427
+ # Returns all subclasses of Runnable.
428
+
429
+ def self.runnables
430
+ @@runnables
431
+ end
432
+
433
+ def marshal_dump # :nodoc:
434
+ [self.name, self.failures, self.assertions]
435
+ end
436
+
437
+ def marshal_load ary # :nodoc:
438
+ self.name, self.failures, self.assertions = ary
439
+ end
440
+
441
+ def failure # :nodoc:
442
+ self.failures.first
443
+ end
444
+
445
+ def initialize name # :nodoc:
446
+ self.name = name
447
+ self.failures = []
448
+ self.assertions = 0
449
+ end
450
+
451
+ ##
452
+ # Runs a single method. Needs to return self.
453
+
454
+ def run
455
+ raise NotImplementedError, "subclass responsibility"
456
+ end
457
+
458
+ ##
459
+ # Did this run pass?
460
+ #
461
+ # Note: skipped runs are not considered passing, but they don't
462
+ # cause the process to exit non-zero.
463
+
464
+ def passed?
465
+ raise NotImplementedError, "subclass responsibility"
466
+ end
467
+
468
+ ##
469
+ # Returns a single character string to print based on the result
470
+ # of the run. Eg ".", "F", or "E".
471
+
472
+ def result_code
473
+ raise NotImplementedError, "subclass responsibility"
474
+ end
475
+
476
+ ##
477
+ # Was this run skipped? See #passed? for more information.
478
+
479
+ def skipped?
480
+ raise NotImplementedError, "subclass responsibility"
481
+ end
482
+ end
483
+
484
+ ##
485
+ # Defines the API for Reporters. Subclass this and override whatever
486
+ # you want. Go nuts.
487
+
488
+ class AbstractReporter
489
+ ##
490
+ # Starts reporting on the run.
491
+
492
+ def start
493
+ end
494
+
495
+ ##
496
+ # Record a result and output the Runnable#result_code. Stores the
497
+ # result of the run if the run did not pass.
498
+
499
+ def record result
500
+ end
501
+
502
+ ##
503
+ # Outputs the summary of the run.
504
+
505
+ def report
506
+ end
507
+
508
+ ##
509
+ # Did this run pass?
510
+
511
+ def passed?
512
+ true
513
+ end
514
+ end
515
+
516
+ class Reporter < AbstractReporter # :nodoc:
517
+ ##
518
+ # The IO used to report.
519
+
520
+ attr_accessor :io
521
+
522
+ ##
523
+ # Command-line options for this run.
524
+
525
+ attr_accessor :options
526
+
527
+ def initialize io = $stdout, options = {} # :nodoc:
528
+ self.io = io
529
+ self.options = options
530
+ end
531
+ end
532
+
533
+ ##
534
+ # A very simple reporter that prints the "dots" during the run.
535
+ #
536
+ # This is added to the top-level CompositeReporter at the start of
537
+ # the run. If you want to change the output of minitest via a
538
+ # plugin, pull this out of the composite and replace it with your
539
+ # own.
540
+
541
+ class ProgressReporter < Reporter
542
+ def record result # :nodoc:
543
+ io.print "%s#%s = %.2f s = " % [result.class, result.name, result.time] if
544
+ options[:verbose]
545
+ io.print result.result_code
546
+ io.puts if options[:verbose]
547
+ end
548
+ end
549
+
550
+ ##
551
+ # A reporter that gathers statistics about a test run. Does not do
552
+ # any IO because meant to be used as a parent class for a reporter
553
+ # that does.
554
+ #
555
+ # If you want to create an entirely different type of output (eg,
556
+ # CI, HTML, etc), this is the place to start.
557
+
558
+ class StatisticsReporter < Reporter
559
+ # :stopdoc:
560
+ attr_accessor :assertions
561
+ attr_accessor :count
562
+ attr_accessor :results
563
+ attr_accessor :start_time
564
+ attr_accessor :total_time
565
+ attr_accessor :failures
566
+ attr_accessor :errors
567
+ attr_accessor :skips
568
+ # :startdoc:
569
+
570
+ def initialize io = $stdout, options = {} # :nodoc:
571
+ super
572
+
573
+ self.assertions = 0
574
+ self.count = 0
575
+ self.results = []
576
+ self.start_time = nil
577
+ self.total_time = nil
578
+ self.failures = nil
579
+ self.errors = nil
580
+ self.skips = nil
581
+ end
582
+
583
+ def passed? # :nodoc:
584
+ results.all?(&:skipped?)
585
+ end
586
+
587
+ def start # :nodoc:
588
+ self.start_time = Time.now
589
+ end
590
+
591
+ def record result # :nodoc:
592
+ self.count += 1
593
+ self.assertions += result.assertions
594
+
595
+ results << result if not result.passed? or result.skipped?
596
+ end
597
+
598
+ def report # :nodoc:
599
+ aggregate = results.group_by { |r| r.failure.class }
600
+ aggregate.default = [] # dumb. group_by should provide this
601
+
602
+ self.total_time = Time.now - start_time
603
+ self.failures = aggregate[Assertion].size
604
+ self.errors = aggregate[UnexpectedError].size
605
+ self.skips = aggregate[Skip].size
606
+ end
607
+ end
608
+
609
+ ##
610
+ # A reporter that prints the header, summary, and failure details at
611
+ # the end of the run.
612
+ #
613
+ # This is added to the top-level CompositeReporter at the start of
614
+ # the run. If you want to change the output of minitest via a
615
+ # plugin, pull this out of the composite and replace it with your
616
+ # own.
617
+
618
+ class SummaryReporter < StatisticsReporter
619
+ # :stopdoc:
620
+ attr_accessor :sync
621
+ attr_accessor :old_sync
622
+ # :startdoc:
623
+
624
+ def start # :nodoc:
625
+ super
626
+
627
+ self.sync = io.respond_to? :"sync=" # stupid emacs
628
+ self.old_sync, io.sync = io.sync, true if self.sync
629
+ end
630
+
631
+ def report # :nodoc:
632
+ super
633
+
634
+ io.sync = self.old_sync
635
+
636
+ io.puts # finish the dots
637
+ io.puts
638
+ io.puts statistics
639
+ io.puts aggregated_results
640
+ io.puts summary
641
+ end
642
+
643
+ def statistics # :nodoc:
644
+ "Finished in #{ChronicDuration.output(total_time.round) || '0s'}"
645
+ end
646
+
647
+ def aggregated_results # :nodoc:
648
+ filtered_results = results.dup
649
+ filtered_results.reject!(&:skipped?) unless options[:verbose]
650
+
651
+ filtered_results.each_with_index.map do |result, i|
652
+ "\n%3d) %s" % [i+1, result]
653
+ end.join("\n") + "\n"
654
+ end
655
+
656
+ def summary # :nodoc:
657
+ "%d runs, %d assertions, %d failures, %d errors, %d skips" %
658
+ [count, assertions, failures, errors, skips]
659
+ end
660
+ end
661
+
662
+ ##
663
+ # Dispatch to multiple reporters as one.
664
+
665
+ class CompositeReporter < AbstractReporter
666
+ ##
667
+ # The list of reporters to dispatch to.
668
+
669
+ attr_accessor :reporters
670
+
671
+ def initialize *reporters # :nodoc:
672
+ self.reporters = reporters
673
+ end
674
+
675
+ ##
676
+ # Add another reporter to the mix.
677
+
678
+ def << reporter
679
+ self.reporters << reporter
680
+ end
681
+
682
+ def passed? # :nodoc:
683
+ self.reporters.all?(&:passed?)
684
+ end
685
+
686
+ def start # :nodoc:
687
+ self.reporters.each(&:start)
688
+ end
689
+
690
+ def record result # :nodoc:
691
+ self.reporters.each do |reporter|
692
+ reporter.record result
693
+ end
694
+ end
695
+
696
+ def report # :nodoc:
697
+ self.reporters.each(&:report)
698
+ end
699
+ end
700
+
701
+ ##
702
+ # Represents run failures.
703
+
704
+ class Assertion < Exception
705
+ def error # :nodoc:
706
+ self
707
+ end
708
+
709
+ ##
710
+ # Where was this run before an assertion was raised?
711
+
712
+ def location
713
+ last_before_assertion = ""
714
+ self.backtrace.reverse_each do |s|
715
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
716
+ last_before_assertion = s
717
+ end
718
+ last_before_assertion.sub(/:in .*$/, "")
719
+ end
720
+
721
+ def result_code # :nodoc:
722
+ result_label[0, 1]
723
+ end
724
+
725
+ def result_label # :nodoc:
726
+ "Failure"
727
+ end
728
+ end
729
+
730
+ ##
731
+ # Assertion raised when skipping a run.
732
+
733
+ class Skip < Assertion
734
+ def result_label # :nodoc:
735
+ "Skipped"
736
+ end
737
+ end
738
+
739
+ ##
740
+ # Assertion wrapping an unexpected error that was raised during a run.
741
+
742
+ class UnexpectedError < Assertion
743
+ attr_accessor :exception # :nodoc:
744
+
745
+ def initialize exception # :nodoc:
746
+ super
747
+ self.exception = exception
748
+ end
749
+
750
+ def backtrace # :nodoc:
751
+ self.exception.backtrace
752
+ end
753
+
754
+ def error # :nodoc:
755
+ self.exception
756
+ end
757
+
758
+ def message # :nodoc:
759
+ bt = Minitest::filter_backtrace(self.backtrace).join "\n "
760
+ "#{self.exception.class}: #{self.exception.message}\n #{bt}"
761
+ end
762
+
763
+ def result_label # :nodoc:
764
+ "Error"
765
+ end
766
+ end
767
+
768
+ ##
769
+ # Provides a simple set of guards that you can use in your tests
770
+ # to skip execution if it is not applicable. These methods are
771
+ # mixed into Test as both instance and class methods so you
772
+ # can use them inside or outside of the test methods.
773
+ #
774
+ # def test_something_for_mri
775
+ # skip "bug 1234" if jruby?
776
+ # # ...
777
+ # end
778
+ #
779
+ # if windows? then
780
+ # # ... lots of test methods ...
781
+ # end
782
+
783
+ module Guard
784
+
785
+ ##
786
+ # Is this running on jruby?
787
+
788
+ def jruby? platform = RUBY_PLATFORM
789
+ "java" == platform
790
+ end
791
+
792
+ ##
793
+ # Is this running on maglev?
794
+
795
+ def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
796
+ "maglev" == platform
797
+ end
798
+
799
+ ##
800
+ # Is this running on mri?
801
+
802
+ def mri? platform = RUBY_DESCRIPTION
803
+ /^ruby/ =~ platform
804
+ end
805
+
806
+ ##
807
+ # Is this running on rubinius?
808
+
809
+ def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
810
+ "rbx" == platform
811
+ end
812
+
813
+ ##
814
+ # Is this running on windows?
815
+
816
+ def windows? platform = RUBY_PLATFORM
817
+ /mswin|mingw/ =~ platform
818
+ end
819
+ end
820
+
821
+ class BacktraceFilter # :nodoc:
822
+ def filter bt
823
+ return ["No backtrace"] unless bt
824
+
825
+ return bt.dup if $DEBUG
826
+
827
+ new_bt = bt.take_while { |line| line !~ /lib\/minitest/ }
828
+ new_bt = bt.select { |line| line !~ /lib\/minitest/ } if new_bt.empty?
829
+ new_bt = bt.dup if new_bt.empty?
830
+
831
+ new_bt
832
+ end
833
+ end
834
+
835
+ self.backtrace_filter = BacktraceFilter.new
836
+ end
837
+
838
+ require "minitest/test"
839
+ require "minitest/unit" unless defined?(MiniTest) # compatibility layer only