mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Move MiniTest::Assertions to Test::Unit::Assertions
This commit is contained in:
parent
cd829bb078
commit
1bec4f251d
Notes:
git
2021-09-11 08:48:44 +09:00
4 changed files with 607 additions and 702 deletions
|
@ -26,18 +26,15 @@ module Test
|
||||||
module CoreAssertions
|
module CoreAssertions
|
||||||
require_relative 'envutil'
|
require_relative 'envutil'
|
||||||
|
|
||||||
if defined?(MiniTest)
|
unless defined?(MiniTest)
|
||||||
# for ruby core testing
|
|
||||||
include MiniTest::Assertions
|
|
||||||
else
|
|
||||||
module MiniTest
|
module MiniTest
|
||||||
class Assertion < Exception; end
|
class Assertion < Exception; end
|
||||||
class Skip < Assertion; end
|
class Skip < Assertion; end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
require 'pp'
|
require 'pp'
|
||||||
include Test::Unit::Assertions
|
include Test::Unit::Assertions
|
||||||
end
|
|
||||||
|
|
||||||
def mu_pp(obj) #:nodoc:
|
def mu_pp(obj) #:nodoc:
|
||||||
obj.pretty_inspect.chomp
|
obj.pretty_inspect.chomp
|
||||||
|
@ -733,6 +730,14 @@ eom
|
||||||
end
|
end
|
||||||
alias all_assertions assert_all_assertions
|
alias all_assertions assert_all_assertions
|
||||||
|
|
||||||
|
def assert_all_assertions_foreach(msg = nil, *keys, &block)
|
||||||
|
all = AllFailures.new
|
||||||
|
all.foreach(*keys, &block)
|
||||||
|
ensure
|
||||||
|
assert(all.pass?, message(msg) {all.message.chomp(".")})
|
||||||
|
end
|
||||||
|
alias all_assertions_foreach assert_all_assertions_foreach
|
||||||
|
|
||||||
def message(msg = nil, *args, &default) # :nodoc:
|
def message(msg = nil, *args, &default) # :nodoc:
|
||||||
if Proc === msg
|
if Proc === msg
|
||||||
super(nil, *args) do
|
super(nil, *args) do
|
||||||
|
|
|
@ -69,690 +69,6 @@ module MiniTest
|
||||||
backtrace_filter.filter bt
|
backtrace_filter.filter bt
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
|
||||||
# MiniTest Assertions. All assertion methods accept a +msg+ which is
|
|
||||||
# printed if the assertion fails.
|
|
||||||
|
|
||||||
module Assertions
|
|
||||||
##
|
|
||||||
# Returns the diff command to use in #diff. Tries to intelligently
|
|
||||||
# figure out what diff to use.
|
|
||||||
|
|
||||||
def self.diff
|
|
||||||
unless defined? @diff
|
|
||||||
exe = RbConfig::CONFIG['EXEEXT']
|
|
||||||
@diff = %W"gdiff#{exe} diff#{exe}".find do |diff|
|
|
||||||
if system(diff, "-u", __FILE__, __FILE__)
|
|
||||||
break "#{diff} -u"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@diff
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Set the diff command to use in #diff.
|
|
||||||
|
|
||||||
def self.diff= o
|
|
||||||
@diff = o
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Returns a diff between +exp+ and +act+. If there is no known
|
|
||||||
# diff command or if it doesn't make sense to diff the output
|
|
||||||
# (single line, short output), then it simply returns a basic
|
|
||||||
# comparison between the two.
|
|
||||||
|
|
||||||
def diff exp, act
|
|
||||||
require "tempfile"
|
|
||||||
|
|
||||||
expect = mu_pp_for_diff exp
|
|
||||||
butwas = mu_pp_for_diff act
|
|
||||||
result = nil
|
|
||||||
|
|
||||||
need_to_diff =
|
|
||||||
MiniTest::Assertions.diff &&
|
|
||||||
(expect.include?("\n") ||
|
|
||||||
butwas.include?("\n") ||
|
|
||||||
expect.size > 30 ||
|
|
||||||
butwas.size > 30 ||
|
|
||||||
expect == butwas)
|
|
||||||
|
|
||||||
return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless
|
|
||||||
need_to_diff
|
|
||||||
|
|
||||||
tempfile_a = nil
|
|
||||||
tempfile_b = nil
|
|
||||||
|
|
||||||
Tempfile.open("expect") do |a|
|
|
||||||
tempfile_a = a
|
|
||||||
a.puts expect
|
|
||||||
a.flush
|
|
||||||
|
|
||||||
Tempfile.open("butwas") do |b|
|
|
||||||
tempfile_b = b
|
|
||||||
b.puts butwas
|
|
||||||
b.flush
|
|
||||||
|
|
||||||
result = `#{MiniTest::Assertions.diff} #{a.path} #{b.path}`
|
|
||||||
result.sub!(/^\-\-\- .+/, "--- expected")
|
|
||||||
result.sub!(/^\+\+\+ .+/, "+++ actual")
|
|
||||||
|
|
||||||
if result.empty? then
|
|
||||||
klass = exp.class
|
|
||||||
result = [
|
|
||||||
"No visible difference in the #{klass}#inspect output.\n",
|
|
||||||
"You should look at the implementation of #== on ",
|
|
||||||
"#{klass} or its members.\n",
|
|
||||||
expect,
|
|
||||||
].join
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
result
|
|
||||||
ensure
|
|
||||||
tempfile_a.close! if tempfile_a
|
|
||||||
tempfile_b.close! if tempfile_b
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# This returns a human-readable version of +obj+. By default
|
|
||||||
# #inspect is called. You can override this to use #pretty_print
|
|
||||||
# if you want.
|
|
||||||
|
|
||||||
def mu_pp obj
|
|
||||||
s = obj.inspect
|
|
||||||
s = s.encode Encoding.default_external if defined? Encoding
|
|
||||||
s
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# This returns a diff-able human-readable version of +obj+. This
|
|
||||||
# differs from the regular mu_pp because it expands escaped
|
|
||||||
# newlines and makes hex-values generic (like object_ids). This
|
|
||||||
# uses mu_pp to do the first pass and then cleans it up.
|
|
||||||
|
|
||||||
def mu_pp_for_diff obj
|
|
||||||
mu_pp(obj).gsub(/(?<!\\)(?:\\\\)*\K\\n/, "\n").gsub(/:0x[a-fA-F0-9]{4,}/m, ':0xXXXXXX')
|
|
||||||
end
|
|
||||||
|
|
||||||
def _assertions= n # :nodoc:
|
|
||||||
@_assertions = n
|
|
||||||
end
|
|
||||||
alias assertions= _assertions=
|
|
||||||
|
|
||||||
def _assertions # :nodoc:
|
|
||||||
@_assertions ||= 0
|
|
||||||
end
|
|
||||||
alias assertions _assertions
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +test+ is a true value.
|
|
||||||
|
|
||||||
def assert test, msg = nil
|
|
||||||
msg ||= "Failed assertion, no message given."
|
|
||||||
self._assertions += 1
|
|
||||||
unless test then
|
|
||||||
msg = msg.call if Proc === msg
|
|
||||||
raise MiniTest::Assertion, msg
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +obj+ is empty.
|
|
||||||
|
|
||||||
def assert_empty obj, msg = nil
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(obj)} to be empty" }
|
|
||||||
assert_respond_to obj, :empty?
|
|
||||||
assert obj.empty?, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless <tt>exp == act</tt> printing the difference between
|
|
||||||
# the two, if possible.
|
|
||||||
#
|
|
||||||
# If there is no visible difference but the assertion fails, you
|
|
||||||
# should suspect that your #== is buggy, or your inspect output is
|
|
||||||
# missing crucial details.
|
|
||||||
#
|
|
||||||
# For floats use assert_in_delta.
|
|
||||||
#
|
|
||||||
# See also: MiniTest::Assertions.diff
|
|
||||||
|
|
||||||
def assert_equal exp, act, msg = nil
|
|
||||||
msg = message(msg, "") { diff exp, act }
|
|
||||||
assert exp == act, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# For comparing Floats. Fails unless +exp+ and +act+ are within +delta+
|
|
||||||
# of each other.
|
|
||||||
#
|
|
||||||
# assert_in_delta Math::PI, (22.0 / 7.0), 0.01
|
|
||||||
|
|
||||||
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}"
|
|
||||||
}
|
|
||||||
assert delta >= n, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# For comparing Floats. Fails unless +exp+ and +act+ have a relative
|
|
||||||
# error less than +epsilon+.
|
|
||||||
|
|
||||||
def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
|
|
||||||
assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +collection+ includes +obj+.
|
|
||||||
|
|
||||||
def assert_includes collection, obj, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
"Expected #{mu_pp(collection)} to include #{mu_pp(obj)}"
|
|
||||||
}
|
|
||||||
assert_respond_to collection, :include?
|
|
||||||
assert collection.include?(obj), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +obj+ is an instance of +cls+.
|
|
||||||
|
|
||||||
def assert_instance_of cls, obj, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
"Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert obj.instance_of?(cls), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +obj+ is a kind of +cls+.
|
|
||||||
|
|
||||||
def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
|
|
||||||
msg = message(msg) {
|
|
||||||
"Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
|
|
||||||
|
|
||||||
assert obj.kind_of?(cls), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +matcher+ <tt>=~</tt> +obj+.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +obj+ is nil
|
|
||||||
|
|
||||||
def assert_nil obj, msg = nil
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
|
|
||||||
assert obj.nil?, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# For testing with binary operators.
|
|
||||||
#
|
|
||||||
# assert_operator 5, :<=, 4
|
|
||||||
|
|
||||||
def assert_operator o1, op, o2 = (predicate = true; nil), msg = nil
|
|
||||||
return assert_predicate o1, op, msg if predicate
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
|
|
||||||
assert o1.__send__(op, o2), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if stdout or stderr do not output the expected results.
|
|
||||||
# Pass in nil if you don't care about that streams output. Pass in
|
|
||||||
# "" if you require it to be silent. Pass in a regexp if you want
|
|
||||||
# to pattern match.
|
|
||||||
#
|
|
||||||
# NOTE: this uses #capture_io, not #capture_subprocess_io.
|
|
||||||
#
|
|
||||||
# See also: #assert_silent
|
|
||||||
|
|
||||||
def assert_output stdout = nil, stderr = nil
|
|
||||||
out, err = capture_io do
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
|
|
||||||
err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr
|
|
||||||
out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout
|
|
||||||
|
|
||||||
y = send err_msg, stderr, err, "In stderr" if err_msg
|
|
||||||
x = send out_msg, stdout, out, "In stdout" if out_msg
|
|
||||||
|
|
||||||
(!stdout || x) && (!stderr || y)
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# For testing with predicates.
|
|
||||||
#
|
|
||||||
# assert_predicate str, :empty?
|
|
||||||
#
|
|
||||||
# This is really meant for specs and is front-ended by assert_operator:
|
|
||||||
#
|
|
||||||
# str.must_be :empty?
|
|
||||||
|
|
||||||
def assert_predicate o1, op, msg = nil
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" }
|
|
||||||
assert o1.__send__(op), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# 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
|
|
||||||
|
|
||||||
begin
|
|
||||||
yield
|
|
||||||
rescue MiniTest::Skip => e
|
|
||||||
return e if exp.include? MiniTest::Skip
|
|
||||||
raise e
|
|
||||||
rescue Exception => e
|
|
||||||
expected = exp.any? { |ex|
|
|
||||||
if ex.instance_of? Module then
|
|
||||||
e.kind_of? ex
|
|
||||||
else
|
|
||||||
e.instance_of? ex
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
assert expected, proc {
|
|
||||||
exception_details(e, "#{msg}#{mu_pp(exp)} exception expected, not")
|
|
||||||
}
|
|
||||||
|
|
||||||
return e
|
|
||||||
end
|
|
||||||
|
|
||||||
exp = exp.first if exp.size == 1
|
|
||||||
|
|
||||||
flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised."
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +obj+ responds to +meth+.
|
|
||||||
|
|
||||||
def assert_respond_to obj, meth, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
"Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
|
|
||||||
}
|
|
||||||
assert obj.respond_to?(meth), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless +exp+ and +act+ are #equal?
|
|
||||||
|
|
||||||
def assert_same exp, act, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
|
|
||||||
"Expected %s (oid=%d) to be the same as %s (oid=%d)" % data
|
|
||||||
}
|
|
||||||
assert exp.equal?(act), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# +send_ary+ is a receiver, message and arguments.
|
|
||||||
#
|
|
||||||
# Fails unless the call returns a true value
|
|
||||||
# TODO: I should prolly remove this from specs
|
|
||||||
|
|
||||||
def assert_send send_ary, m = nil
|
|
||||||
recv, msg, *args = send_ary
|
|
||||||
m = message(m) {
|
|
||||||
"Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" }
|
|
||||||
assert recv.__send__(msg, *args), m
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if the block outputs anything to stderr or stdout.
|
|
||||||
#
|
|
||||||
# See also: #assert_output
|
|
||||||
|
|
||||||
def assert_silent
|
|
||||||
assert_output "", "" do
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails unless the block throws +sym+
|
|
||||||
|
|
||||||
def assert_throws sym, msg = nil
|
|
||||||
default = "Expected #{mu_pp(sym)} to have been thrown"
|
|
||||||
caught = true
|
|
||||||
catch(sym) do
|
|
||||||
begin
|
|
||||||
yield
|
|
||||||
rescue ThreadError => e # wtf?!? 1.8 + threads == suck
|
|
||||||
default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}"
|
|
||||||
rescue ArgumentError => e # 1.9 exception
|
|
||||||
default += ", not #{e.message.split(/ /).last}"
|
|
||||||
rescue NameError => e # 1.8 exception
|
|
||||||
default += ", not #{e.name.inspect}"
|
|
||||||
end
|
|
||||||
caught = false
|
|
||||||
end
|
|
||||||
|
|
||||||
assert caught, message(msg) { default }
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_path_exists(path, msg = nil)
|
|
||||||
msg = message(msg) { "Expected path '#{path}' to exist" }
|
|
||||||
assert File.exist?(path), msg
|
|
||||||
end
|
|
||||||
alias assert_path_exist assert_path_exists
|
|
||||||
alias refute_path_not_exist assert_path_exists
|
|
||||||
|
|
||||||
def refute_path_exists(path, msg = nil)
|
|
||||||
msg = message(msg) { "Expected path '#{path}' to not exist" }
|
|
||||||
refute File.exist?(path), msg
|
|
||||||
end
|
|
||||||
alias refute_path_exist refute_path_exists
|
|
||||||
alias assert_path_not_exist refute_path_exists
|
|
||||||
|
|
||||||
##
|
|
||||||
# Captures $stdout and $stderr into strings:
|
|
||||||
#
|
|
||||||
# out, err = capture_io do
|
|
||||||
# puts "Some info"
|
|
||||||
# warn "You did a bad thing"
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# assert_match %r%info%, out
|
|
||||||
# assert_match %r%bad%, err
|
|
||||||
#
|
|
||||||
# NOTE: For efficiency, this method uses StringIO and does not
|
|
||||||
# capture IO for subprocesses. Use #capture_subprocess_io for
|
|
||||||
# that.
|
|
||||||
|
|
||||||
def capture_io
|
|
||||||
require 'stringio'
|
|
||||||
|
|
||||||
captured_stdout, captured_stderr = StringIO.new, StringIO.new
|
|
||||||
|
|
||||||
synchronize do
|
|
||||||
orig_stdout, orig_stderr = $stdout, $stderr
|
|
||||||
$stdout, $stderr = captured_stdout, captured_stderr
|
|
||||||
|
|
||||||
begin
|
|
||||||
yield
|
|
||||||
ensure
|
|
||||||
$stdout = orig_stdout
|
|
||||||
$stderr = orig_stderr
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return captured_stdout.string, captured_stderr.string
|
|
||||||
end
|
|
||||||
alias capture_output capture_io
|
|
||||||
|
|
||||||
##
|
|
||||||
# Captures $stdout and $stderr into strings, using Tempfile to
|
|
||||||
# ensure that subprocess IO is captured as well.
|
|
||||||
#
|
|
||||||
# out, err = capture_subprocess_io do
|
|
||||||
# system "echo Some info"
|
|
||||||
# system "echo You did a bad thing 1>&2"
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# assert_match %r%info%, out
|
|
||||||
# assert_match %r%bad%, err
|
|
||||||
#
|
|
||||||
# NOTE: This method is approximately 10x slower than #capture_io so
|
|
||||||
# only use it when you need to test the output of a subprocess.
|
|
||||||
|
|
||||||
def capture_subprocess_io
|
|
||||||
require 'tempfile'
|
|
||||||
|
|
||||||
captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err")
|
|
||||||
|
|
||||||
synchronize do
|
|
||||||
orig_stdout, orig_stderr = $stdout.dup, $stderr.dup
|
|
||||||
$stdout.reopen captured_stdout
|
|
||||||
$stderr.reopen captured_stderr
|
|
||||||
|
|
||||||
begin
|
|
||||||
yield
|
|
||||||
|
|
||||||
$stdout.rewind
|
|
||||||
$stderr.rewind
|
|
||||||
|
|
||||||
[captured_stdout.read, captured_stderr.read]
|
|
||||||
ensure
|
|
||||||
$stdout.reopen orig_stdout
|
|
||||||
$stderr.reopen orig_stderr
|
|
||||||
orig_stdout.close
|
|
||||||
orig_stderr.close
|
|
||||||
captured_stdout.close!
|
|
||||||
captured_stderr.close!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Returns details for exception +e+
|
|
||||||
|
|
||||||
def exception_details e, msg
|
|
||||||
[
|
|
||||||
"#{msg}",
|
|
||||||
"Class: <#{e.class}>",
|
|
||||||
"Message: <#{e.message.inspect}>",
|
|
||||||
"---Backtrace---",
|
|
||||||
"#{MiniTest::filter_backtrace(e.backtrace).join("\n")}",
|
|
||||||
"---------------",
|
|
||||||
].join "\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails with +msg+
|
|
||||||
|
|
||||||
def flunk msg = nil
|
|
||||||
msg ||= "Epic Fail!"
|
|
||||||
assert false, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Returns a proc that will output +msg+ along with the default message.
|
|
||||||
|
|
||||||
def message msg = nil, ending = ".", &default
|
|
||||||
proc {
|
|
||||||
msg = msg.call.chomp(".") if Proc === msg
|
|
||||||
custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty?
|
|
||||||
"#{custom_message}#{default.call}#{ending}"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# used for counting assertions
|
|
||||||
|
|
||||||
def pass msg = nil
|
|
||||||
assert true
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +test+ is a true value
|
|
||||||
|
|
||||||
def refute test, msg = nil
|
|
||||||
msg ||= "Failed refutation, no message given"
|
|
||||||
not assert(! test, msg)
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +obj+ is empty.
|
|
||||||
|
|
||||||
def refute_empty obj, msg = nil
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" }
|
|
||||||
assert_respond_to obj, :empty?
|
|
||||||
refute obj.empty?, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if <tt>exp == act</tt>.
|
|
||||||
#
|
|
||||||
# For floats use refute_in_delta.
|
|
||||||
|
|
||||||
def refute_equal exp, act, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
"Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}"
|
|
||||||
}
|
|
||||||
refute exp == act, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# 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}"
|
|
||||||
}
|
|
||||||
refute delta >= n, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# For comparing Floats. Fails if +exp+ and +act+ have a relative error
|
|
||||||
# less than +epsilon+.
|
|
||||||
|
|
||||||
def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
|
|
||||||
refute_in_delta a, b, a * epsilon, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +collection+ includes +obj+.
|
|
||||||
|
|
||||||
def refute_includes collection, obj, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
"Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}"
|
|
||||||
}
|
|
||||||
assert_respond_to collection, :include?
|
|
||||||
refute collection.include?(obj), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +obj+ is an instance of +cls+.
|
|
||||||
|
|
||||||
def refute_instance_of cls, obj, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
"Expected #{mu_pp(obj)} to not be an instance of #{cls}"
|
|
||||||
}
|
|
||||||
refute obj.instance_of?(cls), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# 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}" }
|
|
||||||
refute obj.kind_of?(cls), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +matcher+ <tt>=~</tt> +obj+.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +obj+ is nil.
|
|
||||||
|
|
||||||
def refute_nil obj, msg = nil
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
|
|
||||||
refute obj.nil?, msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +o1+ is not +op+ +o2+. Eg:
|
|
||||||
#
|
|
||||||
# refute_operator 1, :>, 2 #=> pass
|
|
||||||
# refute_operator 1, :<, 2 #=> fail
|
|
||||||
|
|
||||||
def refute_operator o1, op, o2 = (predicate = true; nil), msg = nil
|
|
||||||
return refute_predicate o1, op, msg if predicate
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"}
|
|
||||||
refute o1.__send__(op, o2), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# For testing with predicates.
|
|
||||||
#
|
|
||||||
# refute_predicate str, :empty?
|
|
||||||
#
|
|
||||||
# This is really meant for specs and is front-ended by refute_operator:
|
|
||||||
#
|
|
||||||
# str.wont_be :empty?
|
|
||||||
|
|
||||||
def refute_predicate o1, op, msg = nil
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" }
|
|
||||||
refute o1.__send__(op), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +obj+ responds to the message +meth+.
|
|
||||||
|
|
||||||
def refute_respond_to obj, meth, msg = nil
|
|
||||||
msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
|
|
||||||
|
|
||||||
refute obj.respond_to?(meth), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Fails if +exp+ is the same (by object identity) as +act+.
|
|
||||||
|
|
||||||
def refute_same exp, act, msg = nil
|
|
||||||
msg = message(msg) {
|
|
||||||
data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
|
|
||||||
"Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data
|
|
||||||
}
|
|
||||||
refute exp.equal?(act), msg
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Skips the current test. Gets listed at the end of the run but
|
|
||||||
# doesn't cause a failure exit code.
|
|
||||||
|
|
||||||
def skip msg = nil, bt = caller
|
|
||||||
msg ||= "Skipped, no message given"
|
|
||||||
@skip = true
|
|
||||||
raise MiniTest::Skip, msg, bt
|
|
||||||
end
|
|
||||||
|
|
||||||
alias omit skip
|
|
||||||
|
|
||||||
##
|
|
||||||
# Was this testcase skipped? Meant for #teardown.
|
|
||||||
|
|
||||||
def skipped?
|
|
||||||
defined?(@skip) and @skip
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Takes a block and wraps it with the runner's shared mutex.
|
|
||||||
|
|
||||||
def synchronize
|
|
||||||
Minitest::Unit.runner.synchronize do
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Unit # :nodoc:
|
class Unit # :nodoc:
|
||||||
VERSION = "4.7.5" # :nodoc:
|
VERSION = "4.7.5" # :nodoc:
|
||||||
|
|
||||||
|
@ -1469,7 +785,6 @@ module MiniTest
|
||||||
|
|
||||||
def teardown; end
|
def teardown; end
|
||||||
|
|
||||||
include MiniTest::Assertions
|
|
||||||
end # class TestCase
|
end # class TestCase
|
||||||
end # class Unit
|
end # class Unit
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,600 @@ require 'pp'
|
||||||
module Test
|
module Test
|
||||||
module Unit
|
module Unit
|
||||||
module Assertions
|
module Assertions
|
||||||
include Test::Unit::CoreAssertions
|
|
||||||
|
##
|
||||||
|
# Returns the diff command to use in #diff. Tries to intelligently
|
||||||
|
# figure out what diff to use.
|
||||||
|
|
||||||
|
def self.diff
|
||||||
|
unless defined? @diff
|
||||||
|
exe = RbConfig::CONFIG['EXEEXT']
|
||||||
|
@diff = %W"gdiff#{exe} diff#{exe}".find do |diff|
|
||||||
|
if system(diff, "-u", __FILE__, __FILE__)
|
||||||
|
break "#{diff} -u"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@diff
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Set the diff command to use in #diff.
|
||||||
|
|
||||||
|
def self.diff= o
|
||||||
|
@diff = o
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns a diff between +exp+ and +act+. If there is no known
|
||||||
|
# diff command or if it doesn't make sense to diff the output
|
||||||
|
# (single line, short output), then it simply returns a basic
|
||||||
|
# comparison between the two.
|
||||||
|
|
||||||
|
def diff exp, act
|
||||||
|
require "tempfile"
|
||||||
|
|
||||||
|
expect = mu_pp_for_diff exp
|
||||||
|
butwas = mu_pp_for_diff act
|
||||||
|
result = nil
|
||||||
|
|
||||||
|
need_to_diff =
|
||||||
|
MiniTest::Assertions.diff &&
|
||||||
|
(expect.include?("\n") ||
|
||||||
|
butwas.include?("\n") ||
|
||||||
|
expect.size > 30 ||
|
||||||
|
butwas.size > 30 ||
|
||||||
|
expect == butwas)
|
||||||
|
|
||||||
|
return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless
|
||||||
|
need_to_diff
|
||||||
|
|
||||||
|
tempfile_a = nil
|
||||||
|
tempfile_b = nil
|
||||||
|
|
||||||
|
Tempfile.open("expect") do |a|
|
||||||
|
tempfile_a = a
|
||||||
|
a.puts expect
|
||||||
|
a.flush
|
||||||
|
|
||||||
|
Tempfile.open("butwas") do |b|
|
||||||
|
tempfile_b = b
|
||||||
|
b.puts butwas
|
||||||
|
b.flush
|
||||||
|
|
||||||
|
result = `#{MiniTest::Assertions.diff} #{a.path} #{b.path}`
|
||||||
|
result.sub!(/^\-\-\- .+/, "--- expected")
|
||||||
|
result.sub!(/^\+\+\+ .+/, "+++ actual")
|
||||||
|
|
||||||
|
if result.empty? then
|
||||||
|
klass = exp.class
|
||||||
|
result = [
|
||||||
|
"No visible difference in the #{klass}#inspect output.\n",
|
||||||
|
"You should look at the implementation of #== on ",
|
||||||
|
"#{klass} or its members.\n",
|
||||||
|
expect,
|
||||||
|
].join
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
ensure
|
||||||
|
tempfile_a.close! if tempfile_a
|
||||||
|
tempfile_b.close! if tempfile_b
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# This returns a human-readable version of +obj+. By default
|
||||||
|
# #inspect is called. You can override this to use #pretty_print
|
||||||
|
# if you want.
|
||||||
|
|
||||||
|
def mu_pp obj
|
||||||
|
s = obj.inspect
|
||||||
|
s = s.encode Encoding.default_external if defined? Encoding
|
||||||
|
s
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# This returns a diff-able human-readable version of +obj+. This
|
||||||
|
# differs from the regular mu_pp because it expands escaped
|
||||||
|
# newlines and makes hex-values generic (like object_ids). This
|
||||||
|
# uses mu_pp to do the first pass and then cleans it up.
|
||||||
|
|
||||||
|
def mu_pp_for_diff obj
|
||||||
|
mu_pp(obj).gsub(/(?<!\\)(?:\\\\)*\K\\n/, "\n").gsub(/:0x[a-fA-F0-9]{4,}/m, ':0xXXXXXX')
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +test+ is a true value.
|
||||||
|
|
||||||
|
def assert test, msg = nil
|
||||||
|
msg ||= "Failed assertion, no message given."
|
||||||
|
self._assertions += 1
|
||||||
|
unless test then
|
||||||
|
msg = msg.call if Proc === msg
|
||||||
|
raise MiniTest::Assertion, msg
|
||||||
|
end
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +obj+ is empty.
|
||||||
|
|
||||||
|
def assert_empty obj, msg = nil
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(obj)} to be empty" }
|
||||||
|
assert_respond_to obj, :empty?
|
||||||
|
assert obj.empty?, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# For comparing Floats. Fails unless +exp+ and +act+ are within +delta+
|
||||||
|
# of each other.
|
||||||
|
#
|
||||||
|
# assert_in_delta Math::PI, (22.0 / 7.0), 0.01
|
||||||
|
|
||||||
|
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}"
|
||||||
|
}
|
||||||
|
assert delta >= n, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# For comparing Floats. Fails unless +exp+ and +act+ have a relative
|
||||||
|
# error less than +epsilon+.
|
||||||
|
|
||||||
|
def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
|
||||||
|
assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +collection+ includes +obj+.
|
||||||
|
|
||||||
|
def assert_includes collection, obj, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
"Expected #{mu_pp(collection)} to include #{mu_pp(obj)}"
|
||||||
|
}
|
||||||
|
assert_respond_to collection, :include?
|
||||||
|
assert collection.include?(obj), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +obj+ is an instance of +cls+.
|
||||||
|
|
||||||
|
def assert_instance_of cls, obj, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
"Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert obj.instance_of?(cls), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +obj+ is a kind of +cls+.
|
||||||
|
|
||||||
|
def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
|
||||||
|
msg = message(msg) {
|
||||||
|
"Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
|
||||||
|
|
||||||
|
assert obj.kind_of?(cls), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +matcher+ <tt>=~</tt> +obj+.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +obj+ is nil
|
||||||
|
|
||||||
|
def assert_nil obj, msg = nil
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
|
||||||
|
assert obj.nil?, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# For testing with binary operators.
|
||||||
|
#
|
||||||
|
# assert_operator 5, :<=, 4
|
||||||
|
|
||||||
|
def assert_operator o1, op, o2 = (predicate = true; nil), msg = nil
|
||||||
|
return assert_predicate o1, op, msg if predicate
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
|
||||||
|
assert o1.__send__(op, o2), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if stdout or stderr do not output the expected results.
|
||||||
|
# Pass in nil if you don't care about that streams output. Pass in
|
||||||
|
# "" if you require it to be silent. Pass in a regexp if you want
|
||||||
|
# to pattern match.
|
||||||
|
#
|
||||||
|
# NOTE: this uses #capture_io, not #capture_subprocess_io.
|
||||||
|
#
|
||||||
|
# See also: #assert_silent
|
||||||
|
|
||||||
|
def assert_output stdout = nil, stderr = nil
|
||||||
|
out, err = capture_io do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
|
||||||
|
err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr
|
||||||
|
out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout
|
||||||
|
|
||||||
|
y = send err_msg, stderr, err, "In stderr" if err_msg
|
||||||
|
x = send out_msg, stdout, out, "In stdout" if out_msg
|
||||||
|
|
||||||
|
(!stdout || x) && (!stderr || y)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# For testing with predicates.
|
||||||
|
#
|
||||||
|
# assert_predicate str, :empty?
|
||||||
|
#
|
||||||
|
# This is really meant for specs and is front-ended by assert_operator:
|
||||||
|
#
|
||||||
|
# str.must_be :empty?
|
||||||
|
|
||||||
|
def assert_predicate o1, op, msg = nil
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" }
|
||||||
|
assert o1.__send__(op), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +obj+ responds to +meth+.
|
||||||
|
|
||||||
|
def assert_respond_to obj, meth, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
"Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
|
||||||
|
}
|
||||||
|
assert obj.respond_to?(meth), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless +exp+ and +act+ are #equal?
|
||||||
|
|
||||||
|
def assert_same exp, act, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
|
||||||
|
"Expected %s (oid=%d) to be the same as %s (oid=%d)" % data
|
||||||
|
}
|
||||||
|
assert exp.equal?(act), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if the block outputs anything to stderr or stdout.
|
||||||
|
#
|
||||||
|
# See also: #assert_output
|
||||||
|
|
||||||
|
def assert_silent
|
||||||
|
assert_output "", "" do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails unless the block throws +sym+
|
||||||
|
|
||||||
|
def assert_throws sym, msg = nil
|
||||||
|
default = "Expected #{mu_pp(sym)} to have been thrown"
|
||||||
|
caught = true
|
||||||
|
catch(sym) do
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
rescue ThreadError => e # wtf?!? 1.8 + threads == suck
|
||||||
|
default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}"
|
||||||
|
rescue ArgumentError => e # 1.9 exception
|
||||||
|
default += ", not #{e.message.split(/ /).last}"
|
||||||
|
rescue NameError => e # 1.8 exception
|
||||||
|
default += ", not #{e.name.inspect}"
|
||||||
|
end
|
||||||
|
caught = false
|
||||||
|
end
|
||||||
|
|
||||||
|
assert caught, message(msg) { default }
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_path_exists(path, msg = nil)
|
||||||
|
msg = message(msg) { "Expected path '#{path}' to exist" }
|
||||||
|
assert File.exist?(path), msg
|
||||||
|
end
|
||||||
|
alias assert_path_exist assert_path_exists
|
||||||
|
alias refute_path_not_exist assert_path_exists
|
||||||
|
|
||||||
|
def refute_path_exists(path, msg = nil)
|
||||||
|
msg = message(msg) { "Expected path '#{path}' to not exist" }
|
||||||
|
refute File.exist?(path), msg
|
||||||
|
end
|
||||||
|
alias refute_path_exist refute_path_exists
|
||||||
|
alias assert_path_not_exist refute_path_exists
|
||||||
|
|
||||||
|
##
|
||||||
|
# Captures $stdout and $stderr into strings:
|
||||||
|
#
|
||||||
|
# out, err = capture_io do
|
||||||
|
# puts "Some info"
|
||||||
|
# warn "You did a bad thing"
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# assert_match %r%info%, out
|
||||||
|
# assert_match %r%bad%, err
|
||||||
|
#
|
||||||
|
# NOTE: For efficiency, this method uses StringIO and does not
|
||||||
|
# capture IO for subprocesses. Use #capture_subprocess_io for
|
||||||
|
# that.
|
||||||
|
|
||||||
|
def capture_io
|
||||||
|
require 'stringio'
|
||||||
|
|
||||||
|
captured_stdout, captured_stderr = StringIO.new, StringIO.new
|
||||||
|
|
||||||
|
synchronize do
|
||||||
|
orig_stdout, orig_stderr = $stdout, $stderr
|
||||||
|
$stdout, $stderr = captured_stdout, captured_stderr
|
||||||
|
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
$stdout = orig_stdout
|
||||||
|
$stderr = orig_stderr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return captured_stdout.string, captured_stderr.string
|
||||||
|
end
|
||||||
|
alias capture_output capture_io
|
||||||
|
|
||||||
|
##
|
||||||
|
# Captures $stdout and $stderr into strings, using Tempfile to
|
||||||
|
# ensure that subprocess IO is captured as well.
|
||||||
|
#
|
||||||
|
# out, err = capture_subprocess_io do
|
||||||
|
# system "echo Some info"
|
||||||
|
# system "echo You did a bad thing 1>&2"
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# assert_match %r%info%, out
|
||||||
|
# assert_match %r%bad%, err
|
||||||
|
#
|
||||||
|
# NOTE: This method is approximately 10x slower than #capture_io so
|
||||||
|
# only use it when you need to test the output of a subprocess.
|
||||||
|
|
||||||
|
def capture_subprocess_io
|
||||||
|
require 'tempfile'
|
||||||
|
|
||||||
|
captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err")
|
||||||
|
|
||||||
|
synchronize do
|
||||||
|
orig_stdout, orig_stderr = $stdout.dup, $stderr.dup
|
||||||
|
$stdout.reopen captured_stdout
|
||||||
|
$stderr.reopen captured_stderr
|
||||||
|
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
|
||||||
|
$stdout.rewind
|
||||||
|
$stderr.rewind
|
||||||
|
|
||||||
|
[captured_stdout.read, captured_stderr.read]
|
||||||
|
ensure
|
||||||
|
$stdout.reopen orig_stdout
|
||||||
|
$stderr.reopen orig_stderr
|
||||||
|
orig_stdout.close
|
||||||
|
orig_stderr.close
|
||||||
|
captured_stdout.close!
|
||||||
|
captured_stderr.close!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns details for exception +e+
|
||||||
|
|
||||||
|
def exception_details e, msg
|
||||||
|
[
|
||||||
|
"#{msg}",
|
||||||
|
"Class: <#{e.class}>",
|
||||||
|
"Message: <#{e.message.inspect}>",
|
||||||
|
"---Backtrace---",
|
||||||
|
"#{MiniTest::filter_backtrace(e.backtrace).join("\n")}",
|
||||||
|
"---------------",
|
||||||
|
].join "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails with +msg+
|
||||||
|
|
||||||
|
def flunk msg = nil
|
||||||
|
msg ||= "Epic Fail!"
|
||||||
|
assert false, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# used for counting assertions
|
||||||
|
|
||||||
|
def pass msg = nil
|
||||||
|
assert true
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +test+ is a true value
|
||||||
|
|
||||||
|
def refute test, msg = nil
|
||||||
|
msg ||= "Failed refutation, no message given"
|
||||||
|
not assert(! test, msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +obj+ is empty.
|
||||||
|
|
||||||
|
def refute_empty obj, msg = nil
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" }
|
||||||
|
assert_respond_to obj, :empty?
|
||||||
|
refute obj.empty?, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if <tt>exp == act</tt>.
|
||||||
|
#
|
||||||
|
# For floats use refute_in_delta.
|
||||||
|
|
||||||
|
def refute_equal exp, act, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
"Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}"
|
||||||
|
}
|
||||||
|
refute exp == act, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# 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}"
|
||||||
|
}
|
||||||
|
refute delta >= n, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# For comparing Floats. Fails if +exp+ and +act+ have a relative error
|
||||||
|
# less than +epsilon+.
|
||||||
|
|
||||||
|
def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
|
||||||
|
refute_in_delta a, b, a * epsilon, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +collection+ includes +obj+.
|
||||||
|
|
||||||
|
def refute_includes collection, obj, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
"Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}"
|
||||||
|
}
|
||||||
|
assert_respond_to collection, :include?
|
||||||
|
refute collection.include?(obj), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +obj+ is an instance of +cls+.
|
||||||
|
|
||||||
|
def refute_instance_of cls, obj, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
"Expected #{mu_pp(obj)} to not be an instance of #{cls}"
|
||||||
|
}
|
||||||
|
refute obj.instance_of?(cls), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# 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}" }
|
||||||
|
refute obj.kind_of?(cls), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +matcher+ <tt>=~</tt> +obj+.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +obj+ is nil.
|
||||||
|
|
||||||
|
def refute_nil obj, msg = nil
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
|
||||||
|
refute obj.nil?, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +o1+ is not +op+ +o2+. Eg:
|
||||||
|
#
|
||||||
|
# refute_operator 1, :>, 2 #=> pass
|
||||||
|
# refute_operator 1, :<, 2 #=> fail
|
||||||
|
|
||||||
|
def refute_operator o1, op, o2 = (predicate = true; nil), msg = nil
|
||||||
|
return refute_predicate o1, op, msg if predicate
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"}
|
||||||
|
refute o1.__send__(op, o2), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# For testing with predicates.
|
||||||
|
#
|
||||||
|
# refute_predicate str, :empty?
|
||||||
|
#
|
||||||
|
# This is really meant for specs and is front-ended by refute_operator:
|
||||||
|
#
|
||||||
|
# str.wont_be :empty?
|
||||||
|
|
||||||
|
def refute_predicate o1, op, msg = nil
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" }
|
||||||
|
refute o1.__send__(op), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +obj+ responds to the message +meth+.
|
||||||
|
|
||||||
|
def refute_respond_to obj, meth, msg = nil
|
||||||
|
msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
|
||||||
|
|
||||||
|
refute obj.respond_to?(meth), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fails if +exp+ is the same (by object identity) as +act+.
|
||||||
|
|
||||||
|
def refute_same exp, act, msg = nil
|
||||||
|
msg = message(msg) {
|
||||||
|
data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
|
||||||
|
"Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data
|
||||||
|
}
|
||||||
|
refute exp.equal?(act), msg
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Skips the current test. Gets listed at the end of the run but
|
||||||
|
# doesn't cause a failure exit code.
|
||||||
|
|
||||||
|
def skip msg = nil, bt = caller
|
||||||
|
msg ||= "Skipped, no message given"
|
||||||
|
@skip = true
|
||||||
|
raise MiniTest::Skip, msg, bt
|
||||||
|
end
|
||||||
|
|
||||||
|
alias omit skip
|
||||||
|
|
||||||
|
##
|
||||||
|
# Was this testcase skipped? Meant for #teardown.
|
||||||
|
|
||||||
|
def skipped?
|
||||||
|
defined?(@skip) and @skip
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Takes a block and wraps it with the runner's shared mutex.
|
||||||
|
|
||||||
|
def synchronize
|
||||||
|
Minitest::Unit.runner.synchronize do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# :call-seq:
|
# :call-seq:
|
||||||
# assert_block( failure_message = nil )
|
# assert_block( failure_message = nil )
|
||||||
|
@ -290,14 +883,6 @@ EOT
|
||||||
assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0")
|
assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0")
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_all_assertions_foreach(msg = nil, *keys, &block)
|
|
||||||
all = AllFailures.new
|
|
||||||
all.foreach(*keys, &block)
|
|
||||||
ensure
|
|
||||||
assert(all.pass?, message(msg) {all.message.chomp(".")})
|
|
||||||
end
|
|
||||||
alias all_assertions_foreach assert_all_assertions_foreach
|
|
||||||
|
|
||||||
def build_message(head, template=nil, *arguments) #:nodoc:
|
def build_message(head, template=nil, *arguments) #:nodoc:
|
||||||
template &&= template.chomp
|
template &&= template.chomp
|
||||||
template.gsub(/\G((?:[^\\]|\\.)*?)(\\)?\?/) { $1 + ($2 ? "?" : mu_pp(arguments.shift)) }
|
template.gsub(/\G((?:[^\\]|\\.)*?)(\\)?\?/) { $1 + ($2 ? "?" : mu_pp(arguments.shift)) }
|
||||||
|
|
|
@ -7,7 +7,7 @@ module Test
|
||||||
remove_const(:TestCase) if defined?(self::TestCase)
|
remove_const(:TestCase) if defined?(self::TestCase)
|
||||||
|
|
||||||
class TestCase < MiniTest::Unit::TestCase # :nodoc: all
|
class TestCase < MiniTest::Unit::TestCase # :nodoc: all
|
||||||
include Assertions
|
include CoreAssertions
|
||||||
|
|
||||||
def on_parallel_worker?
|
def on_parallel_worker?
|
||||||
false
|
false
|
||||||
|
|
Loading…
Reference in a new issue