! Added Minitest::TestTask.
[git-p4: depot-paths = "//src/minitest/dev/": change = 13430]
This commit is contained in:
parent
2d64718cae
commit
73692f9202
|
@ -17,6 +17,7 @@ lib/minitest/pride.rb
|
||||||
lib/minitest/pride_plugin.rb
|
lib/minitest/pride_plugin.rb
|
||||||
lib/minitest/spec.rb
|
lib/minitest/spec.rb
|
||||||
lib/minitest/test.rb
|
lib/minitest/test.rb
|
||||||
|
lib/minitest/test_task.rb
|
||||||
lib/minitest/unit.rb
|
lib/minitest/unit.rb
|
||||||
test/minitest/metametameta.rb
|
test/minitest/metametameta.rb
|
||||||
test/minitest/test_minitest_assertions.rb
|
test/minitest/test_minitest_assertions.rb
|
||||||
|
@ -25,3 +26,4 @@ test/minitest/test_minitest_mock.rb
|
||||||
test/minitest/test_minitest_reporter.rb
|
test/minitest/test_minitest_reporter.rb
|
||||||
test/minitest/test_minitest_spec.rb
|
test/minitest/test_minitest_spec.rb
|
||||||
test/minitest/test_minitest_test.rb
|
test/minitest/test_minitest_test.rb
|
||||||
|
test/minitest/test_minitest_test_task.rb
|
||||||
|
|
39
README.rdoc
39
README.rdoc
|
@ -70,6 +70,7 @@ extract-method refactorings still apply.
|
||||||
* minitest/mock - a simple and clean mock/stub system.
|
* minitest/mock - a simple and clean mock/stub system.
|
||||||
* minitest/benchmark - an awesome way to assert your algorithm's performance.
|
* minitest/benchmark - an awesome way to assert your algorithm's performance.
|
||||||
* minitest/pride - show your pride in testing!
|
* minitest/pride - show your pride in testing!
|
||||||
|
* minitest/test_task - a full-featured and clean rake task generator.
|
||||||
* Incredibly small and fast runner, but no bells and whistles.
|
* 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.
|
* Written by squishy human beings. Software can never be perfect. We will all eventually die.
|
||||||
|
|
||||||
|
@ -264,9 +265,8 @@ new non-existing method:
|
||||||
|
|
||||||
=== Running Your Tests
|
=== Running Your Tests
|
||||||
|
|
||||||
Ideally, you'll use a rake task to run your tests, either piecemeal or
|
Ideally, you'll use a rake task to run your tests (see below), either
|
||||||
all at once. Both rake and rails ship with rake tasks for running your
|
piecemeal or all at once. BUT! You don't have to:
|
||||||
tests. BUT! You don't have to:
|
|
||||||
|
|
||||||
% ruby -Ilib:test test/minitest/test_minitest_test.rb
|
% ruby -Ilib:test test/minitest/test_minitest_test.rb
|
||||||
Run options: --seed 37685
|
Run options: --seed 37685
|
||||||
|
@ -294,18 +294,45 @@ provided via plugins. To see them, simply run with +--help+:
|
||||||
-p, --pride Pride. Show your testing pride!
|
-p, --pride Pride. Show your testing pride!
|
||||||
-a, --autotest Connect to autotest server.
|
-a, --autotest Connect to autotest server.
|
||||||
|
|
||||||
|
=== Rake Tasks
|
||||||
|
|
||||||
You can set up a rake task to run all your tests by adding this to your Rakefile:
|
You can set up a rake task to run all your tests by adding this to your Rakefile:
|
||||||
|
|
||||||
require "rake/testtask"
|
require "minitest/test_task"
|
||||||
|
|
||||||
Rake::TestTask.new(:test) do |t|
|
Minitest::TestTask.create # named test, sensible defaults
|
||||||
|
|
||||||
|
# or more explicitly:
|
||||||
|
|
||||||
|
Minitest::TestTask.create(:test) do |t|
|
||||||
t.libs << "test"
|
t.libs << "test"
|
||||||
t.libs << "lib"
|
t.libs << "lib"
|
||||||
t.test_files = FileList["test/**/test_*.rb"]
|
t.warning = false
|
||||||
|
t.test_globs = ["test/**/*_test.rb"]
|
||||||
end
|
end
|
||||||
|
|
||||||
task :default => :test
|
task :default => :test
|
||||||
|
|
||||||
|
Each of these will generate 4 tasks:
|
||||||
|
|
||||||
|
rake test :: Run the test suite.
|
||||||
|
rake test:cmd :: Print out the test command.
|
||||||
|
rake test:isolated :: Show which test files fail when run separately.
|
||||||
|
rake test:slow :: Show bottom 25 tests sorted by time.
|
||||||
|
|
||||||
|
=== Rake Task Variables
|
||||||
|
|
||||||
|
There are a bunch of variables you can supply to rake to modify the run.
|
||||||
|
|
||||||
|
MT_LIB_EXTRAS :: Extra libs to dynamically override/inject for custom runs.
|
||||||
|
N :: -n: Tests to run (string or /regexp/).
|
||||||
|
X :: -x: Tests to exclude (string or /regexp/).
|
||||||
|
A :: Any extra arguments. Honors shell quoting.
|
||||||
|
MT_CPU :: How many threads to use for parallel test runs
|
||||||
|
SEED :: -s --seed Sets random seed.
|
||||||
|
TESTOPTS :: Deprecated, same as A
|
||||||
|
FILTER :: Deprecated, same as A
|
||||||
|
|
||||||
== Writing Extensions
|
== Writing Extensions
|
||||||
|
|
||||||
To define a plugin, add a file named minitest/XXX_plugin.rb to your
|
To define a plugin, add a file named minitest/XXX_plugin.rb to your
|
||||||
|
|
|
@ -0,0 +1,305 @@
|
||||||
|
require "shellwords"
|
||||||
|
require "rbconfig"
|
||||||
|
require "rake/tasklib"
|
||||||
|
|
||||||
|
module Minitest # :nodoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# Minitest::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.
|
||||||
|
|
||||||
|
class TestTask < Rake::TaskLib
|
||||||
|
WINDOWS = RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ # :nodoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# Create several test-oriented tasks under +name+. Takes an
|
||||||
|
# optional block to customize variables.
|
||||||
|
|
||||||
|
def self.create name = :test, &block
|
||||||
|
task = new name
|
||||||
|
task.instance_eval(&block) if block
|
||||||
|
task.process_env
|
||||||
|
task.define
|
||||||
|
task
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# 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
|
||||||
|
|
||||||
|
attr_accessor :extra_args
|
||||||
|
|
||||||
|
##
|
||||||
|
# The code to load the framework. Defaults to requiring
|
||||||
|
# minitest/autorun...
|
||||||
|
#
|
||||||
|
# Why do I have this as an option?
|
||||||
|
|
||||||
|
attr_accessor :framework
|
||||||
|
|
||||||
|
##
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
attr_accessor :libs
|
||||||
|
|
||||||
|
##
|
||||||
|
# The name of the task and base name for the other tasks generated.
|
||||||
|
|
||||||
|
attr_accessor :name
|
||||||
|
|
||||||
|
##
|
||||||
|
# File globs to find test files. Defaults to something sensible to
|
||||||
|
# find test files under the test directory.
|
||||||
|
|
||||||
|
attr_accessor :test_globs
|
||||||
|
|
||||||
|
##
|
||||||
|
# Turn on ruby warnings (-w flag). Defaults to true.
|
||||||
|
|
||||||
|
attr_accessor :warning
|
||||||
|
|
||||||
|
##
|
||||||
|
# Optional: Additional ruby to run before the test framework is loaded.
|
||||||
|
|
||||||
|
attr_accessor :test_prelude
|
||||||
|
|
||||||
|
##
|
||||||
|
# Print out commands as they run. Defaults to Rake's +trace+ (-t
|
||||||
|
# flag) option.
|
||||||
|
|
||||||
|
attr_accessor :verbose
|
||||||
|
|
||||||
|
##
|
||||||
|
# Use TestTask.create instead.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
##
|
||||||
|
# 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+.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def define # :nodoc:
|
||||||
|
default_tasks = []
|
||||||
|
|
||||||
|
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} TESTOPTS=-v",
|
||||||
|
"egrep '#test_.* s = .'",
|
||||||
|
"sort -n -k2 -t=",
|
||||||
|
"tail -25"].join " | "
|
||||||
|
end
|
||||||
|
|
||||||
|
default_tasks << name
|
||||||
|
|
||||||
|
desc "Run the default task(s)."
|
||||||
|
task :default => default_tasks
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Generate the test command-line.
|
||||||
|
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Work < Queue
|
||||||
|
def initialize jobs = []
|
||||||
|
super()
|
||||||
|
|
||||||
|
jobs.each do |job|
|
||||||
|
self << job
|
||||||
|
end
|
||||||
|
|
||||||
|
close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Integer
|
||||||
|
def threads_do(jobs) # :nodoc:
|
||||||
|
require "thread"
|
||||||
|
q = Work.new jobs
|
||||||
|
|
||||||
|
self.times.map {
|
||||||
|
Thread.new do
|
||||||
|
while job = q.pop # go until quit value
|
||||||
|
yield job
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}.each(&:join)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,46 @@
|
||||||
|
require "minitest/autorun"
|
||||||
|
require "hoe"
|
||||||
|
|
||||||
|
require "minitest/test_task"
|
||||||
|
|
||||||
|
Hoe.load_plugins # make sure Hoe::Test is loaded
|
||||||
|
|
||||||
|
class TestHoeTest < Minitest::Test
|
||||||
|
PATH = "test/minitest/test_minitest_test_task.rb"
|
||||||
|
|
||||||
|
mt_path = %w[lib test .].join File::PATH_SEPARATOR
|
||||||
|
|
||||||
|
MT_EXPECTED = %W[-I#{mt_path} -w
|
||||||
|
-e '%srequire "#{PATH}"'
|
||||||
|
--].join(" ") + " "
|
||||||
|
|
||||||
|
def test_make_test_cmd_for_minitest
|
||||||
|
skip "Using TESTOPTS... skipping" if ENV["TESTOPTS"]
|
||||||
|
|
||||||
|
require "minitest/test_task"
|
||||||
|
|
||||||
|
framework = %(require "minitest/autorun"; )
|
||||||
|
|
||||||
|
@tester = Minitest::TestTask.create :test do |t|
|
||||||
|
t.test_globs = [PATH]
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal MT_EXPECTED % [framework].join("; "), @tester.make_test_cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_make_test_cmd_for_minitest_prelude
|
||||||
|
skip "Using TESTOPTS... skipping" if ENV["TESTOPTS"]
|
||||||
|
|
||||||
|
require "minitest/test_task"
|
||||||
|
|
||||||
|
prelude = %(require "other/file")
|
||||||
|
framework = %(require "minitest/autorun"; )
|
||||||
|
|
||||||
|
@tester = Minitest::TestTask.create :test do |t|
|
||||||
|
t.test_prelude = prelude
|
||||||
|
t.test_globs = [PATH]
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal MT_EXPECTED % [prelude, framework].join("; "), @tester.make_test_cmd
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue