require “optparse” require “thread” require “mutex_m” require “minitest/parallel” require “stringio”

## # = minitest/{test,spec,mock,benchmark} #

# home

github.com/seattlerb/minitest

# bugs

github.com/seattlerb/minitest/issues

# rdoc

docs.seattlerb.org/minitest

# vim

github.com/sunaku/vim-ruby-minitest

# emacs

github.com/arthurnn/minitest-emacs

# # == DESCRIPTION: # # minitest provides a complete suite of testing facilities supporting # TDD, BDD, mocking, and benchmarking. # # “I had a class with Jim Weirich on testing last week and we were # allowed to choose our testing frameworks. Kirk Haines and I were # paired up and we cracked open the code for a few test # frameworks… # # I MUST say that minitest is very readable / understandable # compared to the 'other two' options we looked at. Nicely done and # thank you for helping us keep our mental sanity.” # # – Wayne E. Seguin # # minitest/test is a small and incredibly fast unit testing framework. # It provides a rich set of assertions to make your tests clean and # readable. # # minitest/spec is a functionally complete spec engine. It hooks onto # minitest/test and seamlessly bridges test assertions over to spec # expectations. # # minitest/benchmark is an awesome way to assert the performance of your # algorithms in a repeatable manner. Now you can assert that your newb # co-worker doesn't replace your linear algorithm with an exponential # one! # # minitest/mock by Steven Baker, is a beautifully tiny mock (and stub) # object framework. # # minitest/pride shows pride in testing and adds coloring to your test # output. I guess it is an example of how to write IO pipes too. :P # # minitest/test is meant to have a clean implementation for language # implementors that need a minimal set of methods to bootstrap a working # test suite. For example, there is no magic involved for test-case # discovery. # # “Again, I can't praise enough the idea of a testing/specing # framework that I can actually read in full in one sitting!” # # – Piotr Szotkowski # # Comparing to rspec: # # rspec is a testing DSL. minitest is ruby. # # – Adam Hawkins, “Bow Before MiniTest” # # minitest doesn't reinvent anything that ruby already provides, like: # classes, modules, inheritance, methods. This means you only have to # learn ruby to use minitest and all of your regular OO practices like # extract-method refactorings still apply. # # == FEATURES/PROBLEMS: # # * minitest/autorun - the easy and explicit way to run all your tests. # * minitest/test - a very fast, simple, and clean test system. # * minitest/spec - a very fast, simple, and clean spec system. # * minitest/mock - a simple and clean mock/stub system. # * minitest/benchmark - an awesome way to assert your algorithm's performance. # * minitest/pride - show your pride in testing! # * Incredibly small and fast runner, but no bells and whistles. # * Written by squishy human beings. Software can never be perfect. We will all eventually die. # # == RATIONALE: # # See design_rationale.rb to see how specs and tests work in minitest. # # == SYNOPSIS: # # Given that you'd like to test the following class: # # class Meme # def i_can_has_cheezburger? # “OHAI!” # end # # def will_it_blend? # “YES!” # end # end # # === Unit tests # # Define your tests as methods beginning with test_. # # require “minitest/autorun” # # class TestMeme < Minitest::Test # def setup # @meme = Meme.new # end # # def test_that_kitty_can_eat # assert_equal “OHAI!”, @meme.i_can_has_cheezburger? # end # # def test_that_it_will_not_blend # refute_match /^no/i, @meme.will_it_blend? # end # # def test_that_will_be_skipped # skip “test this later” # end # end # # === Specs # # require “minitest/autorun” # # describe Meme do # before do # @meme = Meme.new # end # # describe “when asked about cheeseburgers” do # it “must respond positively” do # @meme.i_can_has_cheezburger?.must_equal “OHAI!” # end # end # # describe “when asked about blending possibilities” do # it “won't say no” do # @meme.will_it_blend?.wont_match /^no/i # end # end # end # # For matchers support check out: # # github.com/wojtekmach/minitest-matchers # github.com/rmm5t/minitest-matchers_vaccine # # === Benchmarks # # Add benchmarks to your tests. # # # optionally run benchmarks, good for CI-only work! # require “minitest/benchmark” if ENV # # class TestMeme < Minitest::Benchmark # # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000] # def bench_my_algorithm # assert_performance_linear 0.9999 do |n| # n is a range value # @obj.my_algorithm(n) # end # end # end # # Or add them to your specs. If you make benchmarks optional, you'll # need to wrap your benchmarks in a conditional since the methods won't # be defined. In minitest 5, the describe name needs to match # /Bench(mark)?$/. # # describe “Meme Benchmark” do # if ENV then # bench_performance_linear “my_algorithm”, 0.9999 do |n| # 100.times do # @obj.my_algorithm(n) # end # end # end # end # # outputs something like: # # # Running benchmarks: # # TestBlah 100 1000 10000 # bench_my_algorithm 0.006167 0.079279 0.786993 # bench_other_algorithm 0.061679 0.792797 7.869932 # # Output is tab-delimited to make it easy to paste into a spreadsheet. # # === Mocks # # Mocks and stubs defined using terminology by Fowler & Meszaros at # www.martinfowler.com/bliki/TestDouble.html: # # “Mocks are pre-programmed with expectations which form a specification # of the calls they are expected to receive. They can throw an exception # if they receive a call they don't expect and are checked during # verification to ensure they got all the calls they were expecting.” # # class MemeAsker # def initialize(meme) # @meme = meme # end # # def ask(question) # method = question.tr(“ ”, “_”) + “?” # @meme.__send__(method) # end # end # # require “minitest/autorun” # # describe MemeAsker, :ask do # describe “when passed an unpunctuated question” do # it “should invoke the appropriate predicate method on the meme” do # @meme = Minitest::Mock.new # @meme_asker = MemeAsker.new @meme # @meme.expect :will_it_blend?, :return_value # # @meme_asker.ask “will it blend” # # @meme.verify # end # end # end # # **Multi-threading and Mocks** # # Minitest mocks do not support multi-threading if it works, fine, if it doesn't # you can use regular ruby patterns and facilities like local variables. Here's # an example of asserting that code inside a thread is run: # # def test_called_inside_thread # called = false # pr = Proc.new { called = true } # thread = Thread.new(&pr) # thread.join # assert called, “proc not called” # end # # === Stubs # # Mocks and stubs are defined using terminology by Fowler & Meszaros at # www.martinfowler.com/bliki/TestDouble.html: # # “Stubs provide canned answers to calls made during the test”. # # Minitest's stub method overrides a single method for the duration of # the block. # # def test_stale_eh # obj_under_test = Something.new # # refute obj_under_test.stale? # # Time.stub :now, Time.at(0) do # stub goes away once the block is done # assert obj_under_test.stale? # end # end # # A note on stubbing: In order to stub a method, the method must # actually exist prior to stubbing. Use a singleton method to create a # new non-existing method: # # def obj_under_test.fake_method # … # end # # === Running Your Tests # # Ideally, you'll use a rake task to run your tests, either piecemeal or # all at once. Both rake and rails ship with rake tasks for running your # tests. BUT! You don't have to: # # % ruby -Ilib:test test/minitest/test_minitest_test.rb # Run options: –seed 37685 # # # Running: # # .….….….….….….….….….….….….….….….….….. (etc) # # Finished in 0.107130s, 1446.8403 runs/s, 2959.0217 assertions/s. # # 155 runs, 317 assertions, 0 failures, 0 errors, 0 skips # # There are runtime options available, both from minitest itself, and also # provided via plugins. To see them, simply run with --help: # # % ruby -Ilib:test test/minitest/test_minitest_test.rb –help # minitest options: # -h, –help Display this help. # -s, –seed SEED Sets random seed. Also via env. Eg: SEED=n rake # -v, –verbose Verbose. Show progress processing files. # -n, –name PATTERN Filter run on /regexp/ or string. # -e, –exclude PATTERN Exclude /regexp/ or string from run. # # Known extensions: pride, autotest # -p, –pride Pride. Show your testing pride! # -a, –autotest Connect to autotest server. # # == Writing Extensions # # To define a plugin, add a file named minitest/XXX_plugin.rb to your # project/gem. That file must be discoverable via ruby's LOAD_PATH (via # rubygems or otherwise). Minitest will find and require that file using # Gem.find_files. It will then try to call plugin_XXX_init during # startup. The option processor will also try to call plugin_XXX_options # passing the OptionParser instance and the current options hash. This # lets you register your own command-line options. Here's a totally # bogus example: # # # minitest/bogus_plugin.rb: # # module Minitest # def self.plugin_bogus_options(opts, options) # opts.on “–myci”, “Report results to my CI” do # options = true # options = get_myci_addr # options = get_myci_port # end # end # # def self.plugin_bogus_init(options) # self.reporter << MyCI.new(options) if options # end # end # # === Adding custom reporters # # Minitest uses composite reporter to output test results using multiple # reporter instances. You can add new reporters to the composite during # the init_plugins phase. As we saw in plugin_bogus_init above, you # simply add your reporter instance to the composite via <<. # # AbstractReporter defines the API for reporters. You may subclass it # and override any method you want to achieve your desired behavior. #

# start

Called when the run has started.

# record

Called for each result, passed or otherwise.

# report

Called at the end of the run.

# passed?

Called to see if you detected any problems.

# # Using our example above, here is how we might implement MyCI: # # # minitest/bogus_plugin.rb # # module Minitest # class MyCI < AbstractReporter # attr_accessor :results, :addr, :port # # def initialize options # self.results = [] # self.addr = options # self.port = options # end # # def record result # self.results << result # end # # def report # CI.connect(addr, port).send_results self.results # end # end # # # code from above… # end # # == FAQ # # === How to test SimpleDelegates? # # The following implementation and test: # # class Worker < SimpleDelegator # def work # end # end # # describe Worker do # before do # @worker = Worker.new(Object.new) # end # # it “must respond to work” do # @worker.must_respond_to :work # end # end # # outputs a failure: # # 1) Failure: # Worker#test_0001_must respond to work [bug11.rb:16]: # Expected #<Object:0x007f9e7184f0a0> (Object) to respond to work. # # Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject. # Expectations are put on Object (one level down) so the Worker # (SimpleDelegate) hits method_missing and delegates down to the # Object.new instance. That object doesn't respond to work so the test # fails. # # You can bypass SimpleDelegate#method_missing by extending the worker # with Minitest::Expectations. You can either do that in your setup at # the instance level, like: # # before do # @worker = Worker.new(Object.new) # @worker.extend Minitest::Expectations # end # # or you can extend the Worker class (within the test file!), like: # # class Worker # include ::Minitest::Expectations # end # # === How to share code across test classes? # # Use a module. That's exactly what they're for: # # module UsefulStuff # def useful_method # # … # end # end # # describe Blah do # include UsefulStuff # # def test_whatever # # useful_method available here # end # end # # Remember, describe simply creates test classes. It's just ruby at # the end of the day and all your normal Good Ruby Rules (tm) apply. If # you want to extend your test using setup/teardown via a module, just # make sure you ALWAYS call super. before/after automatically call super # for you, so make sure you don't do it twice. # # === Why am I seeing uninitialized constant MiniTest::Test (NameError)? # # Are you running the test with Bundler (e.g. via bundle exec )? If so, # in order to require minitest, you must first add the gem 'minitest' # to your Gemfile and run bundle. Once it's installed, you should be # able to require minitest and run your tests. # # == Prominent Projects using Minitest: # # * arel # * journey # * mime-types # * nokogiri # * rails (active_support et al) # * rake # * rdoc # * …and of course, everything from seattle.rb… # # == Known Extensions: #

# capybara_minitest_spec

Bridge between Capybara RSpec matchers and

# Minitest::Spec expectations (e.g. # page.must_have_content("Title")).

# color_pound_spec_reporter

Test names print Ruby Object types in color with

# your Minitest Spec style tests.

# minispec-metadata

Metadata for describe/it blocks & CLI tag filter.

# E.g. it "requires JS driver", js: true do & # ruby test.rb --tag js runs tests tagged :js.

# minitest-around

Around block for minitest. An alternative to

# setup/teardown dance.

# minitest-assert_errors

Adds Minitest assertions to test for errors raised

# or not raised by Minitest itself.

# minitest-autotest

autotest is a continuous testing facility meant to

# be used during development.

# minitest-bacon

minitest-bacon extends minitest with bacon-like

# functionality.

# minitest-bang

Adds support for RSpec-style let! to immediately

# invoke let statements before each test.

# minitest-bisect

Helps you isolate and debug random test failures.

# minitest-blink1_reporter

Display test results with a Blink1.

# minitest-capistrano

Assertions and expectations for testing

# Capistrano recipes.

# minitest-capybara

Capybara matchers support for minitest unit and

# spec.

# minitest-chef-handler

Run Minitest suites as Chef report handlers

# minitest-ci

CI reporter plugin for Minitest.

# minitest-context

Defines contexts for code reuse in Minitest

# specs that share common expectations.

# minitest-debugger

Wraps assert so failed assertions drop into

# the ruby debugger.

# minitest-display

Patches Minitest to allow for an easily

# configurable output.

# minitest-documentation

Minimal documentation format inspired by rspec's.

# minitest-doc_reporter

Detailed output inspired by rspec's documentation

# format.

# minitest-emoji

Print out emoji for your test passes, fails, and

# skips.

# minitest-english

Semantically symmetric aliases for assertions and

# expectations.

# minitest-excludes

Clean API for excluding certain tests you

# don't want to run under certain conditions.

# minitest-fail-fast

Reimplements RSpec's “fail fast” feature

# minitest-filecontent

Support unit tests with expectation results in files.

# Differing results will be stored again in files.

# minitest-filesystem

Adds assertion and expectation to help testing

# filesystem contents.

# minitest-firemock

Makes your Minitest mocks more resilient.

# minitest-focus

Focus on one test at a time.

# minitest-gcstats

A minitest plugin that adds a report of the top

# tests by number of objects allocated.

# minitest-great_expectations

Generally useful additions to minitest's

# assertions and expectations.

# minitest-growl

Test notifier for minitest via growl.

# minitest-happy

GLOBALLY ACTIVATE MINITEST PRIDE! RAWR!

# minitest-have_tag

Adds Minitest assertions to test for the existence of

# HTML tags, including contents, within a provided string.

# minitest-hooks

Around and before_all/after_all/around_all hooks

# minitest-hyper

Pretty, single-page HTML reports for your Minitest runs

# minitest-implicit-subject

Implicit declaration of the test subject.

# minitest-instrument

Instrument ActiveSupport::Notifications when

# test method is executed.

# minitest-instrument-db

Store information about speed of test execution

# provided by minitest-instrument in database.

# minitest-junit

JUnit-style XML reporter for minitest.

# minitest-libnotify

Test notifier for minitest via libnotify.

# minitest-line

Run test at line number.

# minitest-logger

Define assert_log and enable minitest to test log messages.

# Supports Logger and Log4r::Logger.

# minitest-macruby

Provides extensions to minitest for macruby UI

# testing.

# minitest-matchers

Adds support for RSpec-style matchers to

# minitest.

# minitest-matchers_vaccine

Adds assertions that adhere to the matcher spec,

# but without any expectation infections.

# minitest-metadata

Annotate tests with metadata (key-value).

# minitest-mongoid

Mongoid assertion matchers for Minitest.

# minitest-must_not

Provides must_not as an alias for wont in

# Minitest.

# minitest-optional_retry

Automatically retry failed test to help with flakiness.

# minitest-osx

Reporter for the Mac OS X notification center.

# minitest-parallel_fork

Fork-based parallelization

# minitest-parallel-db

Run tests in parallel with a single database.

# minitest-power_assert

PowerAssert for Minitest.

# minitest-predicates

Adds support for .predicate? methods.

# minitest-profile

List the 10 slowest tests in your suite.

# minitest-rails

Minitest integration for Rails 3.x.

# minitest-rails-capybara

Capybara integration for Minitest::Rails.

# minitest-reporters

Create customizable Minitest output formats.

# minitest-rg

Colored red/green output for Minitest.

# minitest-rspec_mocks

Use RSpec Mocks with Minitest.

# minitest-server

minitest-server provides a client/server setup

# with your minitest process, allowing your test # run to send its results directly to a handler.

# minitest-sequel

Minitest assertions to speed-up development and

# testing of Ruby Sequel database setups.

# minitest-shared_description

Support for shared specs and shared spec

# subclasses

# minitest-should_syntax

RSpec-style x.should == y assertions for

# Minitest.

# minitest-shouldify

Adding all manner of shoulds to Minitest (bad

# idea)

# minitest-snail

Print a list of tests that take too long

# minitest-spec-context

Provides rspec-ish context method to

# Minitest::Spec.

# minitest-spec-expect

Expect syntax for Minitest::Spec (e.g.

# expect(sequences).to_include :celery_man).

# minitest-spec-magic

Minitest::Spec extensions for Rails and beyond.

# minitest-spec-rails

Drop in Minitest::Spec superclass for

# ActiveSupport::TestCase.

# minitest-sprint

Runs (Get it? It's fast!) your tests and makes

# it easier to rerun individual failures.

# minitest-stately

Find leaking state between tests

# minitest-stub_any_instance

Stub any instance of a method on the given class

# for the duration of a block.

# minitest-stub-const

Stub constants for the duration of a block.

# minitest-tags

Add tags for minitest.

# minitest-unordered

Adds a new assertion to minitest for checking the

# contents of a collection, ignoring element order.

# minitest-vcr

Automatic cassette managment with Minitest::Spec

# and VCR.

# minitest_owrapper

Get tests results as a TestResult object.

# minitest_should

Shoulda style syntax for minitest test::unit.

# minitest_tu_shim

Bridges between test/unit and minitest.

# mongoid-minitest

Minitest matchers for Mongoid.

# pry-rescue

A pry plugin w/ minitest support. See

# pry-rescue/minitest.rb.

# rspec2minitest

Easily translate any RSpec matchers to Minitest

# assertions and expectations. # # == Unknown Extensions: # # Authors… Please send me a pull request with a description of your minitest extension. # # * assay-minitest # * detroit-minitest # * em-minitest-spec # * flexmock-minitest # * guard-minitest # * guard-minitest-decisiv # * minitest-activemodel # * minitest-ar-assertions # * minitest-capybara-unit # * minitest-colorer # * minitest-deluxe # * minitest-extra-assertions # * minitest-rails-shoulda # * minitest-spec # * minitest-spec-should # * minitest-sugar # * spork-minitest # # == Minitest related goods # # * minitest/pride fabric: www.spoonflower.com/fabric/3928730-again-by-katie_allen # # == REQUIREMENTS: # # * Ruby 1.8.7+. No magic is involved. I hope. # * NOTE: 1.8 and 1.9 will be dropped in minitest 6+. # # == INSTALL: # # sudo gem install minitest # # On 1.9, you already have it. To get newer candy you can still install # the gem, and then requiring “minitest/autorun” should automatically # pull it in. If not, you'll need to do it yourself: # # gem “minitest” # ensures you“re using the gem, and not the built-in MT # require ”minitest/autorun“ # # # … usual testing stuffs … # # DO NOTE: There is a serious problem with the way that ruby 1.9/2.0 # packages their own gems. They install a gem specification file, but # don't install the gem contents in the gem path. This messes up # Gem.find_files and many other things (gem which, gem contents, etc). # # Just install minitest as a gem for real and you'll be happier. # # == LICENSE: # # (The MIT License) # # Copyright © Ryan Davis, seattle.rb # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # 'Software'), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

module Minitest

VERSION = "5.9.1" # :nodoc:
ENCS = "".respond_to? :encoding # :nodoc:

@@installed_at_exit ||= false
@@after_run = []
@extensions = []

mc = (class << self; self; end)

##
# Parallel test executor

mc.send :attr_accessor, :parallel_executor
self.parallel_executor = Parallel::Executor.new((ENV["N"] || 2).to_i)

##
# Filter object for backtraces.

mc.send :attr_accessor, :backtrace_filter

##
# Reporter object to be used for all runs.
#
# NOTE: This accessor is only available during setup, not during runs.

mc.send :attr_accessor, :reporter

##
# Names of known extension plugins.

mc.send :attr_accessor, :extensions

##
# The signal to use for dumping information to STDERR. Defaults to "INFO".

mc.send :attr_accessor, :info_signal
self.info_signal = "INFO"

##
# Registers Minitest to run at process exit

def self.autorun
  at_exit {
    next if $! and not ($!.kind_of? SystemExit and $!.success?)

    exit_code = nil

    at_exit {
      @@after_run.reverse_each(&:call)
      exit exit_code || false
    }

    exit_code = Minitest.run ARGV
  } unless @@installed_at_exit
  @@installed_at_exit = true
end

##
# A simple hook allowing you to run a block of code after everything
# is done running. Eg:
#
#   Minitest.after_run { p $debugging_info }

def self.after_run &block
  @@after_run << block
end

def self.init_plugins options # :nodoc:
  self.extensions.each do |name|
    msg = "plugin_#{name}_init"
    send msg, options if self.respond_to? msg
  end
end

def self.load_plugins # :nodoc:
  return unless self.extensions.empty?

  seen = {}

  require "rubygems" unless defined? Gem

  Gem.find_files("minitest/*_plugin.rb").each do |plugin_path|
    name = File.basename plugin_path, "_plugin.rb"

    next if seen[name]
    seen[name] = true

    require plugin_path
    self.extensions << name
  end
end

##
# This is the top-level run method. Everything starts from here. It
# tells each Runnable sub-class to run, and each of those are
# responsible for doing whatever they do.
#
# The overall structure of a run looks like this:
#
#   Minitest.autorun
#     Minitest.run(args)
#       Minitest.__run(reporter, options)
#         Runnable.runnables.each
#           runnable.run(reporter, options)
#             self.runnable_methods.each
#               self.run_one_method(self, runnable_method, reporter)
#                 Minitest.run_one_method(klass, runnable_method)
#                   klass.new(runnable_method).run

def self.run args = []
  self.load_plugins

  options = process_args args

  reporter = CompositeReporter.new
  reporter << SummaryReporter.new(options[:io], options)
  reporter << ProgressReporter.new(options[:io], options)

  self.reporter = reporter # this makes it available to plugins
  self.init_plugins options
  self.reporter = nil # runnables shouldn't depend on the reporter, ever

  self.parallel_executor.start if parallel_executor.respond_to?(:start)
  reporter.start
  begin
    __run reporter, options
  rescue Interrupt
    warn "Interrupted. Exiting..."
  end
  self.parallel_executor.shutdown
  reporter.report

  reporter.passed?
end

##
# Internal run method. Responsible for telling all Runnable
# sub-classes to run.

def self.__run reporter, options
  suites = Runnable.runnables.reject { |s| s.runnable_methods.empty? }.shuffle
  parallel, serial = suites.partition { |s| s.test_order == :parallel }

  # If we run the parallel tests before the serial tests, the parallel tests
  # could run in parallel with the serial tests. This would be bad because
  # the serial tests won't lock around Reporter#record. Run the serial tests
  # first, so that after they complete, the parallel tests will lock when
  # recording results.
  serial.map { |suite| suite.run reporter, options } +
    parallel.map { |suite| suite.run reporter, options }
end

def self.process_args args = [] # :nodoc:
  options = {
             :io => $stdout,
            }
  orig_args = args.dup

  OptionParser.new do |opts|
    opts.banner  = "minitest options:"
    opts.version = Minitest::VERSION

    opts.on "-h", "--help", "Display this help." do
      puts opts
      exit
    end

    desc = "Sets random seed. Also via env. Eg: SEED=n rake"
    opts.on "-s", "--seed SEED", Integer, desc do |m|
      options[:seed] = m.to_i
    end

    opts.on "-v", "--verbose", "Verbose. Show progress processing files." do
      options[:verbose] = true
    end

    opts.on "-n", "--name PATTERN", "Filter run on /regexp/ or string." do |a|
      options[:filter] = a
    end

    opts.on "-e", "--exclude PATTERN", "Exclude /regexp/ or string from run." do |a|
      options[:exclude] = a
    end

    unless extensions.empty?
      opts.separator ""
      opts.separator "Known extensions: #{extensions.join(", ")}"

      extensions.each do |meth|
        msg = "plugin_#{meth}_options"
        send msg, opts, options if self.respond_to?(msg)
      end
    end

    begin
      opts.parse! args
    rescue OptionParser::InvalidOption => e
      puts
      puts e
      puts
      puts opts
      exit 1
    end

    orig_args -= args
  end

  unless options[:seed] then
    srand
    options[:seed] = (ENV["SEED"] || srand).to_i % 0xFFFF
    orig_args << "--seed" << options[:seed].to_s
  end

  srand options[:seed]

  options[:args] = orig_args.map { |s|
    s =~ /[\s|&<>$()]/ ? s.inspect : s
  }.join " "

  options
end

def self.filter_backtrace bt # :nodoc:
  backtrace_filter.filter bt
end

##
# Represents anything "runnable", like Test, Spec, Benchmark, or
# whatever you can dream up.
#
# Subclasses of this are automatically registered and available in
# Runnable.runnables.

class Runnable
  ##
  # Number of assertions executed in this run.

  attr_accessor :assertions

  ##
  # An assertion raised during the run, if any.

  attr_accessor :failures

  ##
  # Name of the run.

  def name
    @NAME
  end

  ##
  # Set the name of the run.

  def name= o
    @NAME = o
  end

  def self.inherited klass # :nodoc:
    self.runnables << klass
    super
  end

  ##
  # Returns all instance methods matching the pattern +re+.

  def self.methods_matching re
    public_instance_methods(true).grep(re).map(&:to_s)
  end

  def self.reset # :nodoc:
    @@runnables = []
  end

  reset

  ##
  # Responsible for running all runnable methods in a given class,
  # each in its own instance. Each instance is passed to the
  # reporter to record.

  def self.run reporter, options = {}
    filter = options[:filter] || "/./"
    filter = Regexp.new $1 if filter =~ %r%/(.*)/%

    filtered_methods = self.runnable_methods.find_all { |m|
      filter === m || filter === "#{self}##{m}"
    }

    exclude = options[:exclude]
    exclude = Regexp.new $1 if exclude =~ %r%/(.*)/%

    filtered_methods.delete_if { |m|
      exclude === m || exclude === "#{self}##{m}"
    }

    return if filtered_methods.empty?

    with_info_handler reporter do
      filtered_methods.each do |method_name|
        run_one_method self, method_name, reporter
      end
    end
  end

  ##
  # Runs a single method and has the reporter record the result.
  # This was considered internal API but is factored out of run so
  # that subclasses can specialize the running of an individual
  # test. See Minitest::ParallelTest::ClassMethods for an example.

  def self.run_one_method klass, method_name, reporter
    reporter.prerecord klass, method_name
    reporter.record Minitest.run_one_method(klass, method_name)
  end

  def self.with_info_handler reporter, &block # :nodoc:
    handler = lambda do
      unless reporter.passed? then
        warn "Current results:"
        warn ""
        warn reporter.reporters.first
        warn ""
      end
    end

    on_signal ::Minitest.info_signal, handler, &block
  end

  SIGNALS = Signal.list # :nodoc:

  def self.on_signal name, action # :nodoc:
    supported = SIGNALS[name]

    old_trap = trap name do
      old_trap.call if old_trap.respond_to? :call
      action.call
    end if supported

    yield
  ensure
    trap name, old_trap if supported
  end

  ##
  # Each subclass of Runnable is responsible for overriding this
  # method to return all runnable methods. See #methods_matching.

  def self.runnable_methods
    raise NotImplementedError, "subclass responsibility"
  end

  ##
  # Returns all subclasses of Runnable.

  def self.runnables
    @@runnables
  end

  def marshal_dump # :nodoc:
    [self.name, self.failures, self.assertions]
  end

  def marshal_load ary # :nodoc:
    self.name, self.failures, self.assertions = ary
  end

  def failure # :nodoc:
    self.failures.first
  end

  def initialize name # :nodoc:
    self.name       = name
    self.failures   = []
    self.assertions = 0
  end

  ##
  # Runs a single method. Needs to return self.

  def run
    raise NotImplementedError, "subclass responsibility"
  end

  ##
  # Did this run pass?
  #
  # Note: skipped runs are not considered passing, but they don't
  # cause the process to exit non-zero.

  def passed?
    raise NotImplementedError, "subclass responsibility"
  end

  ##
  # Returns a single character string to print based on the result
  # of the run. Eg ".", "F", or "E".

  def result_code
    raise NotImplementedError, "subclass responsibility"
  end

  ##
  # Was this run skipped? See #passed? for more information.

  def skipped?
    raise NotImplementedError, "subclass responsibility"
  end
end

##
# Defines the API for Reporters. Subclass this and override whatever
# you want. Go nuts.

class AbstractReporter
  include Mutex_m

  ##
  # Starts reporting on the run.

  def start
  end

  ##
  # About to start running a test. This allows a reporter to show
  # that it is starting or that we are in the middle of a test run.

  def prerecord klass, name
  end

  ##
  # Record a result and output the Runnable#result_code. Stores the
  # result of the run if the run did not pass.

  def record result
  end

  ##
  # Outputs the summary of the run.

  def report
  end

  ##
  # Did this run pass?

  def passed?
    true
  end
end

class Reporter < AbstractReporter # :nodoc:
  ##
  # The IO used to report.

  attr_accessor :io

  ##
  # Command-line options for this run.

  attr_accessor :options

  def initialize io = $stdout, options = {} # :nodoc:
    super()
    self.io      = io
    self.options = options
  end
end

##
# A very simple reporter that prints the "dots" during the run.
#
# This is added to the top-level CompositeReporter at the start of
# the run. If you want to change the output of minitest via a
# plugin, pull this out of the composite and replace it with your
# own.

class ProgressReporter < Reporter
  def prerecord klass, name
    if options[:verbose] then
      io.print "%s#%s = " % [klass, name]
      io.flush
    end
  end

  def record result # :nodoc:
    io.print "%.2f s = " % [result.time] if options[:verbose]
    io.print result.result_code
    io.puts if options[:verbose]
  end
end

##
# A reporter that gathers statistics about a test run. Does not do
# any IO because meant to be used as a parent class for a reporter
# that does.
#
# If you want to create an entirely different type of output (eg,
# CI, HTML, etc), this is the place to start.

class StatisticsReporter < Reporter

#

attr_accessor :assertions
attr_accessor :count
attr_accessor :results
attr_accessor :start_time
attr_accessor :total_time
attr_accessor :failures
attr_accessor :errors
attr_accessor :skips

#

  def initialize io = $stdout, options = {} # :nodoc:
    super

    self.assertions = 0
    self.count      = 0
    self.results    = []
    self.start_time = nil
    self.total_time = nil
    self.failures   = nil
    self.errors     = nil
    self.skips      = nil
  end

  def passed? # :nodoc:
    results.all?(&:skipped?)
  end

  def start # :nodoc:
    self.start_time = Minitest.clock_time
  end

  def record result # :nodoc:
    self.count += 1
    self.assertions += result.assertions

    results << result if not result.passed? or result.skipped?
  end

  def report # :nodoc:
    aggregate = results.group_by { |r| r.failure.class }
    aggregate.default = [] # dumb. group_by should provide this

    self.total_time = Minitest.clock_time - start_time
    self.failures   = aggregate[Assertion].size
    self.errors     = aggregate[UnexpectedError].size
    self.skips      = aggregate[Skip].size
  end
end

##
# A reporter that prints the header, summary, and failure details at
# the end of the run.
#
# This is added to the top-level CompositeReporter at the start of
# the run. If you want to change the output of minitest via a
# plugin, pull this out of the composite and replace it with your
# own.

class SummaryReporter < StatisticsReporter

#

attr_accessor :sync
attr_accessor :old_sync

#

  def start # :nodoc:
    super

    io.puts "Run options: #{options[:args]}"
    io.puts
    io.puts "# Running:"
    io.puts

    self.sync = io.respond_to? :"sync=" # stupid emacs
    self.old_sync, io.sync = io.sync, true if self.sync
  end

  def report # :nodoc:
    super

    io.sync = self.old_sync

    io.puts unless options[:verbose] # finish the dots
    io.puts
    io.puts statistics
    aggregated_results io
    io.puts summary
  end

  def statistics # :nodoc:
    "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." %
      [total_time, count / total_time, assertions / total_time]
  end

  def aggregated_results io # :nodoc:
    filtered_results = results.dup
    filtered_results.reject!(&:skipped?) unless options[:verbose]

    filtered_results.each_with_index.each { |result, i|
      io.puts "\n%3d) %s" % [i+1, result]
    }
    io.puts
    io
  end

  def to_s
    aggregated_results(StringIO.new(binary_string)).string
  end

  def summary # :nodoc:
    extra = ""

    extra = "\n\nYou have skipped tests. Run with --verbose for details." if
      results.any?(&:skipped?) unless options[:verbose] or ENV["MT_NO_SKIP_MSG"]

    "%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
      [count, assertions, failures, errors, skips, extra]
  end

  private

  if '<3'.respond_to? :b
    def binary_string; ''.b; end
  else
    def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end
  end
end

##
# Dispatch to multiple reporters as one.

class CompositeReporter < AbstractReporter
  ##
  # The list of reporters to dispatch to.

  attr_accessor :reporters

  def initialize *reporters # :nodoc:
    super()
    self.reporters = reporters
  end

  def io # :nodoc:
    reporters.first.io
  end

  ##
  # Add another reporter to the mix.

  def << reporter
    self.reporters << reporter
  end

  def passed? # :nodoc:
    self.reporters.all?(&:passed?)
  end

  def start # :nodoc:
    self.reporters.each(&:start)
  end

  def prerecord klass, name # :nodoc:
    self.reporters.each do |reporter|
      reporter.prerecord klass, name
    end
  end

  def record result # :nodoc:
    self.reporters.each do |reporter|
      reporter.record result
    end
  end

  def report # :nodoc:
    self.reporters.each(&:report)
  end
end

##
# Represents run failures.

class Assertion < Exception
  def error # :nodoc:
    self
  end

  ##
  # Where was this run before an assertion was raised?

  def location
    last_before_assertion = ""
    self.backtrace.reverse_each do |s|
      break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
      last_before_assertion = s
    end
    last_before_assertion.sub(/:in .*$/, "")
  end

  def result_code # :nodoc:
    result_label[0, 1]
  end

  def result_label # :nodoc:
    "Failure"
  end
end

##
# Assertion raised when skipping a run.

class Skip < Assertion
  def result_label # :nodoc:
    "Skipped"
  end
end

##
# Assertion wrapping an unexpected error that was raised during a run.

class UnexpectedError < Assertion
  attr_accessor :exception # :nodoc:

  def initialize exception # :nodoc:
    super "Unexpected exception"
    self.exception = exception
  end

  def backtrace # :nodoc:
    self.exception.backtrace
  end

  def error # :nodoc:
    self.exception
  end

  def message # :nodoc:
    bt = Minitest.filter_backtrace(self.backtrace).join "\n    "
    "#{self.exception.class}: #{self.exception.message}\n    #{bt}"
  end

  def result_label # :nodoc:
    "Error"
  end
end

##
# Provides a simple set of guards that you can use in your tests
# to skip execution if it is not applicable. These methods are
# mixed into Test as both instance and class methods so you
# can use them inside or outside of the test methods.
#
#   def test_something_for_mri
#     skip "bug 1234"  if jruby?
#     # ...
#   end
#
#   if windows? then
#     # ... lots of test methods ...
#   end

module Guard

  ##
  # Is this running on jruby?

  def jruby? platform = RUBY_PLATFORM
    "java" == platform
  end

  ##
  # Is this running on maglev?

  def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
    "maglev" == platform
  end

  ##
  # Is this running on mri?

  def mri? platform = RUBY_DESCRIPTION
    /^ruby/ =~ platform
  end

  ##
  # Is this running on rubinius?

  def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
    "rbx" == platform
  end

  ##
  # Is this running on windows?

  def windows? platform = RUBY_PLATFORM
    /mswin|mingw/ =~ platform
  end
end

class BacktraceFilter # :nodoc:
  def filter bt
    return ["No backtrace"] unless bt

    return bt.dup if $DEBUG

    mt_re = %r%lib/minitest%

    new_bt = bt.take_while { |line| line !~ mt_re }
    new_bt = bt.select     { |line| line !~ mt_re } if new_bt.empty?
    new_bt = bt.dup                                 if new_bt.empty?

    new_bt
  end
end

self.backtrace_filter = BacktraceFilter.new

def self.run_one_method klass, method_name # :nodoc:
  result = klass.new(method_name).run
  raise "#{klass}#run _must_ return self" unless klass === result
  result
end

#

if defined? Process::CLOCK_MONOTONIC # :nodoc:
  def self.clock_time
    Process.clock_gettime Process::CLOCK_MONOTONIC
  end
else
  def self.clock_time
    Time.now
  end
end

# end

require “minitest/test”