module Minitest
def self.__run reporter, options
def self.__run reporter, options suites = Runnable.runnables.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.after_run &block
def self.after_run &block @@after_run << block end
def self.autorun
def self.autorun Warning[:deprecated] = true if Object.const_defined?(:Warning) && Warning.respond_to?(:[]=) 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
def self.cattr_accessor name # :nodoc:
def self.cattr_accessor name # :nodoc: (class << self; self; end).attr_accessor name end
def self.clock_time
def self.clock_time Process.clock_gettime Process::CLOCK_MONOTONIC end
def self.clock_time
def self.clock_time Time.now end
def self.empty_run! options # :nodoc:
def self.empty_run! options # :nodoc: filter = options[:filter] 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
def self.filter_backtrace bt # :nodoc:
def self.filter_backtrace bt # :nodoc: result = backtrace_filter.filter bt result = bt.dup if result.empty? result end
def self.init_plugins options # :nodoc:
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
def self.load *names
def self.load *names names.each do |name| require "minitest/#{name}_plugin" self.extensions << name.to_s end end
def self.load_plugins # :nodoc:
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
def self.plugin_pride_init options # :nodoc:
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
def self.plugin_pride_options opts, _options # :nodoc:
def self.plugin_pride_options opts, _options # :nodoc: opts.on "-p", "--pride", "Pride. Show your testing pride!" do PrideIO.pride! end end
def self.process_args args = [] # :nodoc:
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 opts.on "--no-plugins", "Bypass minitest plugin auto-loading (or set $MT_NO_PLUGINS)." 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 "-q", "--quiet", "Quiet. Show no progress 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 "-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 opts.on "-S", "--skip CODES", String, "Skip reporting of certain types of results (eg E)." do |s| options[:skip] = s.chars.to_a end ruby27plus = ::Warning.respond_to? :[]= opts.on "-W[error]", String, "Turn Ruby warnings into errors" do |s| options[:Werror] = true case s when "error", "all", nil then require "minitest/error_on_warning" $VERBOSE = true ::Warning[:deprecated] = true if ruby27plus else ::Warning[s.to_sym] = true if ruby27plus # 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
def self.register_plugin name_or_mod
def self.register_plugin name_or_mod self.extensions << name_or_mod nil end
def self.run args = []
def self.run args = [] self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"] 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 reporter, options rescue Interrupt warn "Interrupted. Exiting..." end self.parallel_executor.shutdown # might have been removed/replaced during init_plugins: summary = reporter.reporters.grep(SummaryReporter).first reporter.report return empty_run! options if summary && summary.count == 0 reporter.passed? end
def self.run_one_method klass, method_name # :nodoc:
def self.run_one_method klass, method_name # :nodoc: result = klass.new(method_name).run raise "#{klass}#run _must_ return a Result" unless Result === result result end