summaryrefslogtreecommitdiff
path: root/lib/minitest
diff options
context:
space:
mode:
authorryan <ryan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-04 21:46:01 +0000
committerryan <ryan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-04 21:46:01 +0000
commit6af843b9cb99fb844bf866e71e9ee52be126080f (patch)
treeafee639e216cf32357c2d6e76de49f2549c6d5af /lib/minitest
parent95d4b3ba4974fdb9f08900267964949e30b1c821 (diff)
Imported minitest 2.12.1 (r7323)
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35541 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/minitest')
-rw-r--r--lib/minitest/README.txt50
-rw-r--r--lib/minitest/autorun.rb1
-rw-r--r--lib/minitest/benchmark.rb14
-rw-r--r--lib/minitest/mock.rb70
-rw-r--r--lib/minitest/pride.rb32
-rw-r--r--lib/minitest/spec.rb54
-rw-r--r--lib/minitest/unit.rb217
7 files changed, 351 insertions, 87 deletions
diff --git a/lib/minitest/README.txt b/lib/minitest/README.txt
index 25c4dae1a9..8c33c0aa52 100644
--- a/lib/minitest/README.txt
+++ b/lib/minitest/README.txt
@@ -14,7 +14,7 @@ TDD, BDD, mocking, and benchmarking.
paired up and we cracked open the code for a few test
frameworks...
- I MUST say that mintiest is *very* readable / understandable
+ 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."
@@ -44,7 +44,7 @@ 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
+ "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
@@ -117,6 +117,10 @@ Given that you'd like to test the following class:
end
end
+For matchers support check out:
+
+https://github.com/zenspider/minitest-matchers
+
=== Benchmarks
Add benchmarks to your regular unit tests. If the unit tests fail, the
@@ -167,7 +171,7 @@ Output is tab-delimited to make it easy to paste into a spreadsheet.
def ask(question)
method = question.tr(" ","_") + "?"
- @meme.send(method)
+ @meme.__send__(method)
end
end
@@ -242,6 +246,46 @@ fixture loading:
MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new
+== Known Extensions:
+
+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-colorize :: Colorize MiniTest output and show failing tests instantly.
+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-emoji :: Print out emoji for your test passes, fails, and skips.
+minitest-excludes :: Clean API for excluding certain tests you
+ don't want to run under certain conditions.
+minitest-firemock :: Makes your MiniTest mocks more resilient.
+minitest-growl :: Test notifier for minitest via growl.
+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-libnotify :: Test notifier for minitest via libnotify.
+minitest-macruby :: Provides extensions to minitest for macruby UI testing.
+minitest-matchers :: Adds support for RSpec-style matchers to minitest.
+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-predicates :: Adds support for .predicate? methods
+minitest-pry :: A minitest plugin to drop into pry on assertion failure.
+minitest-rails :: MiniTest integration for Rails 3.1.
+minitest-reporters :: Create customizable MiniTest output formats
+minitest-rg :: redgreen minitest
+minitest-spec-magic :: Minitest::Spec extensions for Rails and beyond
+minitest-tags :: add tags for minitest
+minitest-wscolor :: Yet another test colorizer.
+minitest_owrapper :: Get tests results as a TestResult object.
+minitest_should :: Shoulda style syntax for minitest test::unit.
+minitest_tu_shim :: minitest_tu_shim bridges between test/unit and minitest.
+mongoid-minitest :: MiniTest matchers for Mongoid.
+
== REQUIREMENTS:
* Ruby 1.8, maybe even 1.6 or lower. No magic is involved.
diff --git a/lib/minitest/autorun.rb b/lib/minitest/autorun.rb
index 443f2f61d4..cb4a3a0e5d 100644
--- a/lib/minitest/autorun.rb
+++ b/lib/minitest/autorun.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
######################################################################
# This file is imported from the minitest project.
# DO NOT make modifications in this repo. They _will_ be reverted!
diff --git a/lib/minitest/benchmark.rb b/lib/minitest/benchmark.rb
index c6faa50770..02121db340 100644
--- a/lib/minitest/benchmark.rb
+++ b/lib/minitest/benchmark.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
######################################################################
# This file is imported from the minitest project.
# DO NOT make modifications in this repo. They _will_ be reverted!
@@ -7,9 +8,7 @@
require 'minitest/unit'
require 'minitest/spec'
-class MiniTest::Unit
- attr_accessor :runner
-
+class MiniTest::Unit # :nodoc:
def run_benchmarks # :nodoc:
_run_anything :benchmark
end
@@ -318,6 +317,15 @@ class MiniTest::Spec
define_method "bench_#{name.gsub(/\W+/, '_')}", &block
end
+ ##
+ # Specifies the ranges used for benchmarking for that class.
+ #
+ # bench_range do
+ # bench_exp(2, 16, 2)
+ # end
+ #
+ # See Unit::TestCase.bench_range for more details.
+
def self.bench_range &block
return super unless block
diff --git a/lib/minitest/mock.rb b/lib/minitest/mock.rb
index 0d86bfb847..55b0095c0b 100644
--- a/lib/minitest/mock.rb
+++ b/lib/minitest/mock.rb
@@ -1,10 +1,12 @@
+# encoding: utf-8
######################################################################
# This file is imported from the minitest project.
# DO NOT make modifications in this repo. They _will_ be reverted!
# File a patch instead and assign it to Ryan Davis.
######################################################################
-class MockExpectationError < StandardError; end
+class MockExpectationError < StandardError # :nodoc:
+end # omg... worst bug ever. rdoc doesn't allow 1-liners
##
# A simple and clean mock object framework.
@@ -24,8 +26,8 @@ module MiniTest
end
def initialize # :nodoc:
- @expected_calls = {}
- @actual_calls = Hash.new {|h,k| h[k] = [] }
+ @expected_calls = Hash.new { |calls, name| calls[name] = [] }
+ @actual_calls = Hash.new { |calls, name| calls[name] = [] }
end
##
@@ -50,44 +52,70 @@ module MiniTest
# @mock.verify # => raises MockExpectationError
def expect(name, retval, args=[])
- @expected_calls[name] = { :retval => retval, :args => args }
+ raise ArgumentError, "args must be an array" unless Array === args
+ @expected_calls[name] << { :retval => retval, :args => args }
self
end
+ def call name, data
+ case data
+ when Hash then
+ "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}"
+ else
+ data.map { |d| call name, d }.join ", "
+ end
+ end
+
##
# Verify that all methods were called as expected. Raises
# +MockExpectationError+ if the mock object was not called as
# expected.
def verify
- @expected_calls.each_key do |name|
- expected = @expected_calls[name]
- msg1 = "expected #{name}, #{expected.inspect}"
- msg2 = "#{msg1}, got #{@actual_calls[name].inspect}"
-
- raise MockExpectationError, msg2 if
- @actual_calls.has_key? name and
- not @actual_calls[name].include?(expected)
-
- raise MockExpectationError, msg1 unless
- @actual_calls.has_key? name and @actual_calls[name].include?(expected)
+ @expected_calls.each do |name, calls|
+ calls.each do |expected|
+ msg1 = "expected #{call name, expected}"
+ msg2 = "#{msg1}, got [#{call name, @actual_calls[name]}]"
+
+ raise MockExpectationError, msg2 if
+ @actual_calls.has_key? name and
+ not @actual_calls[name].include?(expected)
+
+ raise MockExpectationError, msg1 unless
+ @actual_calls.has_key? name and @actual_calls[name].include?(expected)
+ end
end
true
end
def method_missing(sym, *args) # :nodoc:
- expected = @expected_calls[sym]
-
- unless expected then
+ unless @expected_calls.has_key?(sym) then
raise NoMethodError, "unmocked method %p, expected one of %p" %
[sym, @expected_calls.keys.sort_by(&:to_s)]
end
- expected_args, retval = expected[:args], expected[:retval]
+ index = @actual_calls[sym].length
+ expected_call = @expected_calls[sym][index]
- unless expected_args.size == args.size
+ unless expected_call then
+ raise MockExpectationError, "No more expects available for %p: %p" %
+ [sym, args]
+ end
+
+ expected_args, retval = expected_call[:args], expected_call[:retval]
+
+ if expected_args.size != args.size then
raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
- [sym, expected[:args].size, args.size]
+ [sym, expected_args.size, args.size]
+ end
+
+ fully_matched = expected_args.zip(args).all? { |mod, a|
+ mod === a or mod == a
+ }
+
+ unless fully_matched then
+ raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
+ [sym, args]
end
@actual_calls[sym] << {
diff --git a/lib/minitest/pride.rb b/lib/minitest/pride.rb
index 9cf16fdffa..9de4e37a98 100644
--- a/lib/minitest/pride.rb
+++ b/lib/minitest/pride.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
######################################################################
# This file is imported from the minitest project.
# DO NOT make modifications in this repo. They _will_ be reverted!
@@ -10,12 +11,17 @@ require "minitest/unit"
# Show your testing pride!
class PrideIO
+
+ # Start an escape sequence
ESC = "\e["
+
+ # End the escape sequence
NND = "#{ESC}0m"
+ # The IO we're going to pipe through.
attr_reader :io
- def initialize io
+ def initialize io # :nodoc:
@io = io
# stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm
# also reference http://en.wikipedia.org/wiki/ANSI_escape_code
@@ -25,6 +31,9 @@ class PrideIO
# io.sync = true
end
+ ##
+ # Wrap print to colorize the output.
+
def print o
case o
when "." then
@@ -36,7 +45,7 @@ class PrideIO
end
end
- def puts(*o)
+ def puts(*o) # :nodoc:
o.map! { |s|
s.sub(/Finished tests/) {
@index = 0
@@ -49,6 +58,9 @@ class PrideIO
super
end
+ ##
+ # Color a string.
+
def pride string
string = "*" if string == "."
c = @colors[@index % @size]
@@ -56,15 +68,20 @@ class PrideIO
"#{ESC}#{c}m#{string}#{NND}"
end
- def method_missing msg, *args
+ def method_missing msg, *args # :nodoc:
io.send(msg, *args)
end
end
-class PrideLOL < PrideIO # inspired by lolcat, but massively cleaned up
- PI_3 = Math::PI / 3
+##
+# If you thought the PrideIO was colorful...
+#
+# (Inspired by lolcat, but with clean math)
+
+class PrideLOL < PrideIO
+ PI_3 = Math::PI / 3 # :nodoc:
- def initialize io
+ def initialize io # :nodoc:
# walk red, green, and blue around a circle separated by equal thirds.
#
# To visualize, type this into wolfram-alpha:
@@ -88,6 +105,9 @@ class PrideLOL < PrideIO # inspired by lolcat, but massively cleaned up
super
end
+ ##
+ # Make the string even more colorful. Damnit.
+
def pride string
c = @colors[@index % @size]
@index += 1
diff --git a/lib/minitest/spec.rb b/lib/minitest/spec.rb
index ac28b24c4a..c0c0ae2f02 100644
--- a/lib/minitest/spec.rb
+++ b/lib/minitest/spec.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
######################################################################
# This file is imported from the minitest project.
# DO NOT make modifications in this repo. They _will_ be reverted!
@@ -13,11 +14,14 @@ class Module # :nodoc:
# warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
self.class_eval <<-EOM
def #{new_name} *args
- return MiniTest::Spec.current.#{meth}(*args, &self) if
- Proc === self
- return MiniTest::Spec.current.#{meth}(args.first, self) if
- args.size == 1 unless #{!!dont_flip}
- return MiniTest::Spec.current.#{meth}(self, *args)
+ case
+ when Proc === self then
+ MiniTest::Spec.current.#{meth}(*args, &self)
+ when #{!!dont_flip} then
+ MiniTest::Spec.current.#{meth}(self, *args)
+ else
+ MiniTest::Spec.current.#{meth}(args.first, self, *args[1..-1])
+ end
end
EOM
end
@@ -177,6 +181,12 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
add_teardown_hook {|tc| tc.instance_eval(&block) }
end
+ NAME_RE = if RUBY_VERSION >= "1.9"
+ Regexp.new("[^[[:word:]]]+")
+ else
+ /\W+/u
+ end
+
##
# Define an expectation with name +desc+. Name gets morphed to a
# proper test method name. For some freakish reason, people who
@@ -194,15 +204,22 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
@specs ||= 0
@specs += 1
- name = "test_%04d_%s" % [ @specs, desc.gsub(/\W+/, '_').downcase ]
+ name = "test_%04d_%s" % [ @specs, desc.gsub(NAME_RE, '_').downcase ]
define_method name, &block
self.children.each do |mod|
mod.send :undef_method, name if mod.public_method_defined? name
end
+
+ name
end
+ ##
+ # Essentially, define an accessor for +name+ with +block+.
+ #
+ # Why use let instead of def? I honestly don't know.
+
def self.let name, &block
define_method name do
@_memoized ||= {}
@@ -210,6 +227,10 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
end
end
+ ##
+ # Another lazy man's accessor generator. Made even more lazy by
+ # setting the name for you to +subject+.
+
def self.subject &block
let :subject, &block
end
@@ -232,6 +253,14 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
end
# :stopdoc:
+ def after_setup
+ run_setup_hooks
+ end
+
+ def before_teardown
+ run_teardown_hooks
+ end
+
class << self
attr_reader :desc
alias :specify :it
@@ -240,6 +269,9 @@ class MiniTest::Spec < MiniTest::Unit::TestCase
# :startdoc:
end
+##
+# It's where you hide your "assertions".
+
module MiniTest::Expectations
##
# See MiniTest::Assertions#assert_empty.
@@ -248,7 +280,7 @@ module MiniTest::Expectations
#
# :method: must_be_empty
- infect_an_assertion :assert_empty, :must_be_empty
+ infect_an_assertion :assert_empty, :must_be_empty, :unary
##
# See MiniTest::Assertions#assert_equal
@@ -322,7 +354,7 @@ module MiniTest::Expectations
#
# :method: must_be_nil
- infect_an_assertion :assert_nil, :must_be_nil
+ infect_an_assertion :assert_nil, :must_be_nil, :unary
##
# See MiniTest::Assertions#assert_operator
@@ -408,7 +440,7 @@ module MiniTest::Expectations
#
# :method: wont_be_empty
- infect_an_assertion :refute_empty, :wont_be_empty
+ infect_an_assertion :refute_empty, :wont_be_empty, :unary
##
# See MiniTest::Assertions#refute_equal
@@ -483,7 +515,7 @@ module MiniTest::Expectations
#
# :method: wont_be_nil
- infect_an_assertion :refute_nil, :wont_be_nil
+ infect_an_assertion :refute_nil, :wont_be_nil, :unary
##
# See MiniTest::Assertions#refute_operator
@@ -517,6 +549,6 @@ module MiniTest::Expectations
infect_an_assertion :refute_same, :wont_be_same_as
end
-class Object
+class Object # :nodoc:
include MiniTest::Expectations
end
diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb
index 2c767b68fa..0a0e10816e 100644
--- a/lib/minitest/unit.rb
+++ b/lib/minitest/unit.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
######################################################################
# This file is imported from the minitest project.
# DO NOT make modifications in this repo. They _will_ be reverted!
@@ -61,8 +62,13 @@ module MiniTest
# printed if the assertion fails.
module Assertions
+ UNDEFINED = Object.new # :nodoc:
- WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
+ def UNDEFINED.inspect # :nodoc:
+ "UNDEFINED" # again with the rdoc bugs... :(
+ end
+
+ WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ # :nodoc:
##
# Returns the diff command to use in #diff. Tries to intelligently
@@ -187,6 +193,7 @@ module MiniTest
# Fails unless the block returns a true value.
def assert_block msg = nil
+ warn "NOTE: MiniTest::Unit::TestCase#assert_block is deprecated, use assert. It will be removed on or after 2012-06-01."
msg = message(msg) { "Expected block to return true value" }
assert yield, msg
end
@@ -225,7 +232,7 @@ module MiniTest
def assert_in_delta exp, act, delta = 0.001, msg = nil
n = (exp - act).abs
- msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" }
+ msg = message(msg) { "Expected |#{exp} - #{act}| (#{n}) to be < #{delta}"}
assert delta >= n, msg
end
@@ -234,7 +241,7 @@ module MiniTest
# error less than +epsilon+.
def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
- assert_in_delta a, b, [a, b].min * epsilon, msg
+ assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg
end
##
@@ -270,13 +277,13 @@ module MiniTest
end
##
- # Fails unless +exp+ is <tt>=~</tt> +act+.
+ # Fails unless +matcher+ <tt>=~</tt> +obj+.
- def assert_match exp, act, msg = nil
- msg = message(msg) { "Expected #{mu_pp(exp)} to match #{mu_pp(act)}" }
- assert_respond_to act, :"=~"
- exp = Regexp.new Regexp.escape exp if String === exp and String === act
- assert exp =~ act, msg
+ def assert_match matcher, obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" }
+ assert_respond_to matcher, :"=~"
+ matcher = Regexp.new Regexp.escape matcher if String === matcher
+ assert matcher =~ obj, msg
end
##
@@ -287,9 +294,6 @@ module MiniTest
assert obj.nil?, msg
end
- UNDEFINED = Object.new
- def UNDEFINED.inspect; "UNDEFINED"; end
-
##
# For testing with binary operators.
#
@@ -313,8 +317,8 @@ module MiniTest
yield
end
- x = assert_equal stdout, out, "In stdout" if stdout
y = assert_equal stderr, err, "In stderr" if stderr
+ x = assert_equal stdout, out, "In stdout" if stdout
(!stdout || x) && (!stderr || y)
end
@@ -334,10 +338,11 @@ module MiniTest
end
##
- # Fails unless the block raises one of +exp+
+ # Fails unless the block raises one of +exp+. Returns the
+ # exception matched so you can check the message, attributes, etc.
def assert_raises *exp
- msg = "#{exp.pop}\n" if String === exp.last
+ msg = "#{exp.pop}.\n" if String === exp.last
should_raise = false
begin
@@ -355,7 +360,7 @@ module MiniTest
details = "#{msg}#{mu_pp(exp)} exception expected, not"
assert(exp.any? { |ex|
ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class
- }, proc{exception_details(e, details)})
+ }, exception_details(e, details))
return e
end
@@ -523,14 +528,14 @@ module MiniTest
end
##
- # For comparing Floats. Fails if +exp+ is within +delta+ of +act+
+ # For comparing Floats. Fails if +exp+ is within +delta+ of +act+.
#
# refute_in_delta Math::PI, (22.0 / 7.0)
def refute_in_delta exp, act, delta = 0.001, msg = nil
n = (exp - act).abs
msg = message(msg) {
- "Expected #{exp} - #{act} (#{n}) to not be < #{delta}"
+ "Expected |#{exp} - #{act}| (#{n}) to not be < #{delta}"
}
refute delta > n, msg
end
@@ -544,7 +549,7 @@ module MiniTest
end
##
- # Fails if +collection+ includes +obj+
+ # Fails if +collection+ includes +obj+.
def refute_includes collection, obj, msg = nil
msg = message(msg) {
@@ -555,7 +560,7 @@ module MiniTest
end
##
- # Fails if +obj+ is an instance of +cls+
+ # Fails if +obj+ is an instance of +cls+.
def refute_instance_of cls, obj, msg = nil
msg = message(msg) {
@@ -565,7 +570,7 @@ module MiniTest
end
##
- # Fails if +obj+ is a kind of +cls+
+ # Fails if +obj+ is a kind of +cls+.
def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
@@ -573,13 +578,13 @@ module MiniTest
end
##
- # Fails if +exp+ <tt>=~</tt> +act+
+ # Fails if +matcher+ <tt>=~</tt> +obj+.
- def refute_match exp, act, msg = nil
- msg = message(msg) { "Expected #{mu_pp(exp)} to not match #{mu_pp(act)}" }
- assert_respond_to act, :"=~"
- exp = (/#{Regexp.escape exp}/) if String === exp and String === act
- refute exp =~ act, msg
+ def refute_match matcher, obj, msg = nil
+ msg = message(msg) {"Expected #{mu_pp matcher} to not match #{mu_pp obj}"}
+ assert_respond_to matcher, :"=~"
+ matcher = Regexp.new Regexp.escape matcher if String === matcher
+ refute matcher =~ obj, msg
end
##
@@ -646,8 +651,8 @@ module MiniTest
end
end
- class Unit
- VERSION = "2.8.1" # :nodoc:
+ class Unit # :nodoc:
+ VERSION = "2.12.1" # :nodoc:
attr_accessor :report, :failures, :errors, :skips # :nodoc:
attr_accessor :test_count, :assertion_count # :nodoc:
@@ -655,6 +660,10 @@ module MiniTest
attr_accessor :help # :nodoc:
attr_accessor :verbose # :nodoc:
attr_writer :options # :nodoc:
+ attr_accessor :last_error # :nodoc:
+
+ ##
+ # Lazy accessor for options.
def options
@options ||= {}
@@ -662,6 +671,7 @@ module MiniTest
@@installed_at_exit ||= false
@@out = $stdout
+ @@after_tests = []
##
# A simple hook allowing you to run a block of code after the
@@ -669,8 +679,8 @@ module MiniTest
#
# MiniTest::Unit.after_tests { p $debugging_info }
- def self.after_tests
- at_exit { at_exit { yield } }
+ def self.after_tests &block
+ @@after_tests << block
end
##
@@ -686,7 +696,10 @@ module MiniTest
# to run (at_exit stacks).
exit_code = nil
- at_exit { exit false if exit_code && exit_code != 0 }
+ at_exit {
+ @@after_tests.reverse_each(&:call)
+ exit false if exit_code && exit_code != 0
+ }
exit_code = MiniTest::Unit.new.run ARGV
} unless @@installed_at_exit
@@ -744,6 +757,9 @@ module MiniTest
grep(/^run_/).map { |s| s.to_s }).uniq
end
+ ##
+ # Return the IO for output.
+
def output
self.class.output
end
@@ -756,6 +772,9 @@ module MiniTest
output.print(*a)
end
+ ##
+ # Runner for a given +type+ (eg, test vs bench).
+
def _run_anything type
suites = TestCase.send "#{type}_suites"
return if suites.empty?
@@ -793,10 +812,16 @@ module MiniTest
status
end
+ ##
+ # Runs all the +suites+ for a given +type+.
+
def _run_suites suites, type
suites.map { |suite| _run_suite suite, type }
end
+ ##
+ # Run a single +suite+ for a given +type+.
+
def _run_suite suite, type
header = "#{type}_suite_header"
puts send(header, suite) if respond_to? header
@@ -811,9 +836,12 @@ module MiniTest
print "#{suite}##{method} = " if @verbose
@start_time = Time.now
+ self.last_error = nil
result = inst.run self
time = Time.now - @start_time
+ record suite, method, inst._assertions, time, last_error
+
print "%.2f s = " % time if @verbose
print result
puts if @verbose
@@ -824,6 +852,21 @@ module MiniTest
return assertions.size, assertions.inject(0) { |sum, n| sum + n }
end
+ ##
+ # Record the result of a single run. Makes it very easy to gather
+ # information. Eg:
+ #
+ # class StatisticsRecorder < MiniTest::Unit
+ # def record suite, method, assertions, time, error
+ # # ... record the results somewhere ...
+ # end
+ # end
+ #
+ # MiniTest::Unit.runner = StatisticsRecorder.new
+
+ def record suite, method, assertions, time, error
+ end
+
def location e # :nodoc:
last_before_assertion = ""
e.backtrace.reverse_each do |s|
@@ -838,6 +881,7 @@ module MiniTest
# exception +e+
def puke klass, meth, e
+ self.last_error = e
e = case e
when MiniTest::Skip then
@skips += 1
@@ -859,9 +903,10 @@ module MiniTest
@report = []
@errors = @failures = @skips = 0
@verbose = false
+ self.last_error = nil
end
- def process_args args = []
+ def process_args args = [] # :nodoc:
options = {}
orig_args = args.dup
@@ -882,7 +927,7 @@ module MiniTest
options[:verbose] = true
end
- opts.on '-n', '--name PATTERN', "Filter test names on pattern." do |a|
+ opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |a|
options[:filter] = a
end
@@ -945,12 +990,61 @@ module MiniTest
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 TestCase 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 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
+
+ ##
# Subclass TestCase to create your own tests. Typically you'll want a
# TestCase subclass per implementation class.
#
# See MiniTest::Assertions
class TestCase
+ include Guard
+ extend Guard
+
attr_reader :__name__ # :nodoc:
PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException,
@@ -963,16 +1057,21 @@ module MiniTest
def run runner
trap "INFO" do
+ runner.report.each_with_index do |msg, i|
+ warn "\n%3d) %s" % [i + 1, msg]
+ end
+ warn ''
time = runner.start_time ? Time.now - runner.start_time : 0
- warn "%s#%s %.2fs" % [self.class, self.__name__, time]
+ warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time]
runner.status $stderr
end if SUPPORTS_INFO_SIGNAL
result = ""
begin
@passed = nil
+ self.before_setup
self.setup
- self.run_setup_hooks
+ self.after_setup
self.run_test self.__name__
result = "." unless io?
@passed = true
@@ -982,13 +1081,14 @@ module MiniTest
@passed = false
result = runner.puke self.class, self.__name__, e
ensure
- begin
- self.run_teardown_hooks
- self.teardown
- rescue *PASSTHROUGH_EXCEPTIONS
- raise
- rescue Exception => e
- result = runner.puke self.class, self.__name__, e
+ %w{ before_teardown teardown after_teardown }.each do |hook|
+ begin
+ self.send hook
+ rescue *PASSTHROUGH_EXCEPTIONS
+ raise
+ rescue Exception => e
+ result = runner.puke self.class, self.__name__, e
+ end
end
trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL
end
@@ -1008,11 +1108,17 @@ module MiniTest
@@current
end
+ ##
+ # Return the output IO object
+
def io
@__io__ = true
MiniTest::Unit.output
end
+ ##
+ # Have we hooked up the IO yet?
+
def io?
@__io__
end
@@ -1030,6 +1136,7 @@ module MiniTest
def self.i_suck_and_my_tests_are_order_dependent!
class << self
+ undef_method :test_order if method_defined? :test_order
define_method :test_order do :alpha end
end
end
@@ -1075,10 +1182,32 @@ module MiniTest
def setup; end
##
+ # Runs before every test after setup. Use this to refactor test
+ # initialization.
+
+ def after_setup; end
+
+ ##
+ # Runs before every setup. Use this to refactor test initialization.
+
+ def before_setup; end
+
+ ##
# Runs after every test. Use this to refactor test cleanup.
def teardown; end
+ ##
+ # Runs after every test before teardown. Use this to refactor test
+ # initialization.
+
+ def before_teardown; end
+
+ ##
+ # Runs after every teardown. Use this to refactor test cleanup.
+
+ def after_teardown; end
+
def self.reset_setup_teardown_hooks # :nodoc:
@setup_hooks = []
@teardown_hooks = []
@@ -1189,6 +1318,8 @@ module MiniTest
end # class Unit
end # module MiniTest
+Minitest = MiniTest # because ugh... I typo this all the time
+
if $DEBUG then
module Test # :nodoc:
module Unit # :nodoc: