123456789_123456789_123456789_123456789_123456789_

Module: Minitest

Overview

The top-level namespace for Minitest. Also the location of the main runtime. See .run for more information.

Constant Summary

Class Method Summary

Instance Method Summary

ErrorOnWarning - Included

Class Method Details

.after_run(&block)

A simple hook allowing you to run a block of code after everything is done running. Eg:

Minitest.after_run { p $debugging_info }
[ GitHub ]

  
# File 'lib/minitest.rb', line 95

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

.autorun

Registers Minitest to run at process exit

[ GitHub ]

  
# File 'lib/minitest.rb', line 69

def self.autorun
  Warning[:deprecated] = true

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

    exit_code = nil

    pid = Process.pid
    at_exit {
      next if !Minitest.allow_fork && Process.pid != pid
      @@after_run.reverse_each(&:call)
      exit exit_code || false
    }

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

.cattr_accessor(name)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest.rb', line 19

def self.cattr_accessor name # :nodoc:
  (class << self; self; end).attr_accessor name
end

.clock_time

This method is for internal use only.

See additional method definition at line 1203.

[ GitHub ]

  
# File 'lib/minitest.rb', line 1207

def self.clock_time
  Process.clock_gettime Process::CLOCK_MONOTONIC
end

.empty_run!(options)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest.rb', line 326

def self.empty_run! options # :nodoc:
  filter = options[:include]
  return true unless filter # no filter, but nothing ran == success

  warn "Nothing ran for filter: %s" % [filter]

  require "did_you_mean" # soft dependency, punt if it doesn't load

  ms = Runnable.runnables.flat_map(&:runnable_methods)
  cs = DidYouMean::SpellChecker.new(dictionary: ms).correct filter

  warn DidYouMean::Formatter.message_for cs unless cs.empty?
rescue LoadError
  # do nothing
end

.filter_backtrace(bt)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest.rb', line 359

def self.filter_backtrace bt # :nodoc:
  result = backtrace_filter.filter bt
  result = bt.dup if result.empty?
  result
end

.init_plugins(options)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest.rb', line 134

def self.init_plugins options # :nodoc:
  self.extensions.each do |mod_or_meth|
    case mod_or_meth
    when Symbol, String then
      name = mod_or_meth
      msg = "plugin_#{name}_init"
      next unless self.respond_to? msg
      send msg, options
    when Module then
      recv = mod_or_meth
      next unless recv.respond_to? :minitest_plugin_init
      recv.minitest_plugin_init options
    else
      raise ArgumentError, "plugin is %p, but it must be a symbol, string or module" % [mod_or_meth]
    end
  end
end

.load(*names)

Manually load plugins by name.

[ GitHub ]

  
# File 'lib/minitest.rb', line 102

def self.load *names
  names.each do |name|
    require "minitest/#{name}_plugin"

    self.extensions << name.to_s
  end
end

.load_plugins

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest.rb', line 118

def self.load_plugins # :nodoc:
  return unless defined? Gem

  seen = {}

  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

.plugin_pride_init(options)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest/pride_plugin.rb', line 10

def self.plugin_pride_init options # :nodoc:
  return unless PrideIO.pride?

  klass = ENV["TERM"] =~ /^xterm|-(?:256color|direct)$/ ? PrideLOL : PrideIO
  io    = klass.new options[:io]

  self.reporter.reporters.grep(Minitest::Reporter).each do |rep|
    rep.io = io if rep.io.tty?
  end
end

.plugin_pride_options(opts, _options)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest/pride_plugin.rb', line 4

def self.plugin_pride_options opts, _options # :nodoc:
  opts.on "-p", "--pride", "Pride. Show your testing pride!" do
    PrideIO.pride!
  end
end

.plugin_server_init(options)

[ GitHub ]

  
# File 'lib/minitest/server_plugin.rb', line 12

def self.plugin_server_init options
  if @server then
    require_relative "server"
    self.reporter << Minitest::ServerReporter.new(@server)
  end
end

.plugin_server_options(opts, options)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest/server_plugin.rb', line 6

def self.plugin_server_options opts, options # :nodoc:
  opts.on "--server=pid", Integer, "Connect to minitest server w/ pid." do |s|
    @server = s
  end
end

.plugin_sprint_init(options)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest/sprint_plugin.rb', line 28

def self.plugin_sprint_init options
  require_relative "sprint"
  case options[:sprint]
  when :rake then
    self.reporter << Minitest::Sprint::RakeReporter.new(options[:rake_task])
  when :binstub, :names then
    self.reporter << Minitest::Sprint::SprintReporter.new
  when :lines then
    self.reporter << Minitest::Sprint::SprintReporter.new(:lines)
  end
end

.plugin_sprint_options(opts, options)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest/sprint_plugin.rb', line 13

def self.plugin_sprint_options opts, options # :nodoc:
  opts.on "--rake [TASK]", "Report how to re-run failures with rake." do |task|
    options[:sprint] = :rake
    options[:rake_task] = task
  end

  opts.deprecate "--binstub", "--rerun"

  sprint_styles = %w[rake lines names binstub]

  opts.on "-r", "--rerun [STYLE]", sprint_styles, "Report how to re-run failures using STYLE (names, lines)." do |style|
    options[:sprint] = (style || :lines).to_sym
  end
end

.process_args(args = [])

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest.rb', line 152

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

  warn "--no-plugins is a no-op" if args.delete "--no-plugins" # TODO: remove me! when?

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

    opts.banner = [
      "Usage: rake test [A=options]        (see Minitest::TestTask for more options)",
      "minitest [paths] [options]   (with minitest-sprint gem)",
      "ruby path/to/test.rb [options]\n\n",
    ].join "\n   or: "

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

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

    opts.on "-v", "--verbose", "Verbose. Print each name as they run." do
      options[:verbose] = true
    end

    opts.on "-q", "--quiet", "Quiet. Show no dots while processing files." do
      options[:quiet] = true
    end

    opts.on "--show-skips", "Show skipped at the end of run." do
      options[:show_skips] = true
    end

    opts.on "-b", "--bisect", "Run minitest in bisect-mode to isolate flaky tests."

    opts.on "-i", "--include PATTERN", "Include /regexp/ or string for run." do |a|
      options[:include] = a
    end

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

    # part of my unofficial embedded gem "makeoptparseworkwell"
    def opts.topdict(name)   = (name.length > 1 ? top.long : top.short)
    def opts.alias(from, to) = (dict = topdict(from) ; dict[to] = dict[from])

    # these will work but won't show up in --help output:
    opts.alias "include", "name"
    opts.alias "i",       "n"
    opts.alias "e",       "x"

    opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s|
      options[:skip] = s.chars.to_a
    end

    opts.on "-W[error]", String, "Turn Ruby warnings into errors" do |s|
      options[:Werror] = true
      case s
      when "error", "all", nil then
        require_relative "minitest/error_on_warning"
        $VERBOSE = true
        ::Warning[:deprecated] = true
      else
        ::Warning[s.to_sym] = true # check validity of category
      end
    end

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

      extensions.each do |mod_or_meth|
        case mod_or_meth
        when Symbol, String then
          meth = mod_or_meth
          msg = "plugin_#{meth}_options"
          send msg, opts, options if respond_to? msg
        when Module
          recv = mod_or_meth
          next unless recv.respond_to? :minitest_plugin_options
          recv.minitest_plugin_options opts, options
        else
          raise ArgumentError, "plugin is %p, but it must be a symbol, string or module" % [mod_or_meth]
        end
      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

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

  options
end

.register_plugin(name_or_mod)

Register a plugin to be used. Does NOT require / load it.

[ GitHub ]

  
# File 'lib/minitest.rb', line 113

def self.register_plugin name_or_mod
  self.extensions << name_or_mod
  nil
end

.run(args = [])

This is the top-level run method. Everything starts from here. It tells each ::Minitest::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.load_plugins] optional, called by user, or require what you want
Minitest.autorun
  Minitest.run(args)
    Minitest.process_args
    Minitest.init_plugins
    Minitest.run_all_suites(reporter, options)
      Runnable.runnables.each |runnable_klass|
        runnable_klass.run_suite(reporter, options)
          filtered_methods = runnable_klass.filter_runnable_methods options
          filtered_methods.each |runnable_method|
            runnable_klass.run(self, runnable_method, reporter)
              runnable_klass.new(runnable_method).run
[ GitHub ]

  
# File 'lib/minitest.rb', line 293

def self.run args = []
  options = process_args args

  Minitest.seed = options[:seed]
  srand Minitest.seed

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

  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_all_suites reporter, options
    finished = true
  rescue Interrupt
    warn "Interrupted. Exiting..."
  end
  self.parallel_executor.shutdown if parallel_executor.respond_to? :shutdown

  # might have been removed/replaced during init_plugins:
  summary = reporter.reporters.grep(SummaryReporter).first

  reporter.report

  return empty_run! options if finished && summary && summary.count == 0
  finished and reporter.passed?
end

.run_all_suites(reporter, options)

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

[ GitHub ]

  
# File 'lib/minitest.rb', line 346

def self.run_all_suites reporter, options
  suites = Runnable.runnables.shuffle
  parallel, serial = suites.partition { |s| s.run_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_suite reporter, options } +
    parallel.map { |suite| suite.run_suite reporter, options }
end

Instance Method Details

#backtrace_filter

Filter object for backtraces.

[ GitHub ]

  
# File 'lib/minitest.rb', line 43

cattr_accessor :backtrace_filter

#extensions

Names of known extension plugins.

[ GitHub ]

  
# File 'lib/minitest.rb', line 55

cattr_accessor :extensions

#info_signal

The signal to use for dumping information to STDERR. Defaults to “INFO”.

[ GitHub ]

  
# File 'lib/minitest.rb', line 60

cattr_accessor :info_signal

#parallel_executor

::Minitest::Parallel test executor

[ GitHub ]

  
# File 'lib/minitest.rb', line 34

cattr_accessor :parallel_executor

#reporter

::Minitest::Reporter object to be used for all runs.

NOTE: This accessor is only available during setup, not during runs.

[ GitHub ]

  
# File 'lib/minitest.rb', line 50

cattr_accessor :reporter

#seed

The random seed used for this run. This is used to srand at the start of the run and between each Runnable.run.

Set via .run after processing args.

[ GitHub ]

  
# File 'lib/minitest.rb', line 29

cattr_accessor :seed