123456789_123456789_123456789_123456789_123456789_

Class: Minitest::TestTask

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Rake::TaskLib
Instance Chain:
self, Rake::TaskLib
Inherits: Rake::TaskLib
  • ::Object
Defined in: lib/minitest/test_task.rb

Overview

TestTask is a rake helper that generates several rake tasks under the main test task’s name-space.

task <name>      :: the main test task
task <name>:cmd  :: prints the command to use
task <name>:deps :: runs each test file by itself to find dependency errors
task <name>:slow :: runs the tests and reports the slowest 25 tests.

Examples:

Minitest::TestTask.create

The most basic and default setup.

Minitest::TestTask.create :my_tests

The most basic/default setup, but with a custom name

Minitest::TestTask.create :unit do |t|
  t.test_globs = ["test/unit/**/*_test.rb"]
  t.warning = false
end

Customize the name and only run unit tests.

NOTE: To hook this task up to the default, make it a dependency:

task default: :unit

Constant Summary

Class Method Summary

Instance Attribute Summary

  • #extra_args rw

    Extra arguments to pass to the tests.

  • #framework rw

    The code to load the framework.

  • #libs rw

    Extra library directories to include.

  • #name rw

    The name of the task and base name for the other tasks generated.

  • #test_globs rw

    File globs to find test files.

  • #test_prelude rw

    Optional: Additional ruby to run before the test framework is loaded.

  • #verbose rw

    Print out commands as they run.

  • #warning rw

    Turn on ruby warnings (-w flag).

Instance Method Summary

Constructor Details

.new(name = :test) ⇒ TestTask

This method is for internal use only.

Use .create instead.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 109

def initialize name = :test # :nodoc:
  self.extra_args   = []
  self.framework    = %(require "minitest/autorun")
  self.libs         = %w[lib test .]
  self.name         = name
  self.test_globs   = ["test/**/test_*.rb",
                       "test/**/*_test.rb"]
  self.test_prelude = nil
  self.verbose      = Rake.application.options.trace
  self.warning      = true
end

Class Method Details

.create(name = :test, &block)

Create several test-oriented tasks under #name. Takes an optional block to customize variables.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 44

def self.create name = :test, &block
  task = new name
  task.instance_eval(&block) if block
  task.process_env
  task.define
  task
end

Instance Attribute Details

#extra_args (rw)

Extra arguments to pass to the tests. Defaults empty but gets populated by a number of enviroment variables:

N (-n flag)

a string or regexp of tests to run.

X (-e flag)

a string or regexp of tests to exclude.

A (arg)

quick way to inject an arbitrary argument (eg A=–help).

See #process_env

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 62

attr_accessor :extra_args

#framework (rw)

The code to load the framework. Defaults to requiring minitest/autorun…

Why do I have this as an option?

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 70

attr_accessor :framework

#libs (rw)

Extra library directories to include. Defaults to %w[lib test .]. Also uses $MT_LIB_EXTRAS allowing you to dynamically override/inject directories for custom runs.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 77

attr_accessor :libs

#name (rw)

The name of the task and base name for the other tasks generated.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 82

attr_accessor :name

#test_globs (rw)

File globs to find test files. Defaults to something sensible to find test files under the test directory.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 88

attr_accessor :test_globs

#test_prelude (rw)

Optional: Additional ruby to run before the test framework is loaded.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 98

attr_accessor :test_prelude

#verbose (rw)

Print out commands as they run. Defaults to Rake’s trace (-t flag) option.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 104

attr_accessor :verbose

#warning (rw)

Turn on ruby warnings (-w flag). Defaults to true.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 93

attr_accessor :warning

Instance Method Details

#define

This method is for internal use only.
[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 163

def define # :nodoc:
  desc "Run the test suite. Use N, X, A, and TESTOPTS to add flags/args."
  task name do
    ruby make_test_cmd, verbose:verbose
  end

  desc "Print out the test command. Good for profiling and other tools."
  task "#{name}:cmd" do
    puts "ruby #{make_test_cmd}"
  end

  desc "Show which test files fail when run in isolation."
  task "#{name}:isolated" do
    tests = Dir[*self.test_globs].uniq

    # 3 seems to be the magic number... (tho not by that much)
    bad, good, n = {}, [], (ENV.delete("K") || 3).to_i
    file = ENV.delete("F")
    times = {}

    tt0 = Time.now

    n.threads_do tests.sort do |path|
      t0 = Time.now
      output = `#{Gem.ruby} #{make_test_cmd path} 2>&1`
      t1 = Time.now - t0

      times[path] = t1

      if $?.success?
        $stderr.print "."
        good << path
      else
        $stderr.print "x"
        bad[path] = output
      end
    end

    puts "done"
    puts "Ran in %.2f seconds" % [ Time.now - tt0 ]

    if file then
      require "json"
      File.open file, "w" do |io|
        io.puts JSON.pretty_generate times
      end
    end

    unless good.empty?
      puts
      puts "# Good tests:"
      puts
      good.sort.each do |path|
        puts "%.2fs: %s" % [times[path], path]
      end
    end

    unless bad.empty?
      puts
      puts "# Bad tests:"
      puts
      bad.keys.sort.each do |path|
        puts "%.2fs: %s" % [times[path], path]
      end
      puts
      puts "# Bad Test Output:"
      puts
      bad.sort.each do |path, output|
        puts
        puts "# #{path}:"
        puts output
      end
      exit 1
    end
  end

  task "#{name}:deps" => "#{name}:isolated" # now just an alias

  desc "Show bottom 25 tests wrt time."
  task "#{name}:slow" do
    sh ["rake #{name} A=-v",
        "egrep '#test_.* s = .'",
        "sort -n -k2 -t=",
        "tail -25"].join " | "
  end
end

#make_test_cmd(globs = test_globs)

Generate the test command-line.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 253

def make_test_cmd globs = test_globs
  tests = []
  tests.concat Dir[*globs].sort.shuffle # TODO: SEED -> srand first?
  tests.map! { |f| %(require "#{f}") }

  runner = []
  runner << test_prelude if test_prelude
  runner << framework
  runner.concat tests
  runner = runner.join "; "

  args  = []
  args << "-I#{libs.join(File::PATH_SEPARATOR)}" unless libs.empty?
  args << "-w" if warning
  args << '-e'
  args << "'#{runner}'"
  args << '--'
  args << extra_args.map(&:shellescape)

  args.join " "
end

#process_env

Extract variables from the environment and convert them to command line arguments. See #extra_args.

Environment Variables:

MT_LIB_EXTRAS

Extra libs to dynamically override/inject for custom runs.

N

Tests to run (string or /regexp/).

X

Tests to exclude (string or /regexp/).

A

Any extra arguments. Honors shell quoting.

Deprecated:

TESTOPTS

For argument passing, use A.

N

For parallel testing, use MT_CPU.

FILTER

Same as TESTOPTS.

[ GitHub ]

  
# File 'lib/minitest/test_task.rb', line 138

def process_env
  warn "TESTOPTS is deprecated in Minitest::TestTask. Use A instead" if
    ENV["TESTOPTS"]
  warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if
    ENV["FILTER"]
  warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if
    ENV["N"] && ENV["N"].to_i > 0

  lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR
  self.libs[0,0] = lib_extras

  extra_args << "-n" << ENV["N"]                      if ENV["N"]
  extra_args << "-e" << ENV["X"]                      if ENV["X"]
  extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"]
  extra_args.concat Shellwords.split(ENV["FILTER"])   if ENV["FILTER"]
  extra_args.concat Shellwords.split(ENV["A"])        if ENV["A"]

  ENV.delete "N" if ENV["N"]

  # TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"]
  # TODO? ENV["RUBY_FLAGS"]

  extra_args.compact!
end