lib/ae/assertor.rb in ae-1.7.0 vs lib/ae/assertor.rb in ae-1.7.1
- old
+ new
@@ -25,21 +25,21 @@
$assertion_counts
end
# Reset assertion counts.
#
- # reset - Hash which will be used to set counts manually (optional).
+ # reset - Hash which can be used to set counts manually (optional).
#
# Returns the Hash of previous counts.
- def self.recount(reset={})
+ def self.recount(reset=nil)
old_counts = counts.dup
- if reset.empty?
- counts.replace(ZERO_COUNTS.dup)
- else
+ if reset
reset.each do |type, value|
counts[type.to_sym] = value
end
+ else
+ counts.replace(ZERO_COUNTS.dup)
end
return old_counts
end
# Increment assertion counts. If +pass+ is +true+ then +:total+
@@ -55,39 +55,55 @@
return counts
end
# Basic assertion. This method by-passes all the Assertor fluent
# constructs and performs the underlying assertion procedure. It
- # is used by Assertor as the end result of an assertion.
- def self.assert(pass, message=nil, backtrace=nil)
+ # is used by Assertor as the end call of an assertion.
+ def self.assert(pass, error=nil, negated=nil, backtrace=nil)
+ pass = negated ^ !!pass
increment_counts(pass)
if !pass
backtrace = backtrace || caller
- message = message || 'flunk'
- raise_assertion(message, backtrace)
+ raise_assertion(error, negated, backtrace)
end
return pass
end
- # This method can be replaced to support alternate frameworks.
- # The intent of the method is to raise the assertion failure
- # class that the framework uses.
- def self.raise_assertion(message, backtrace=nil)
- backtrace = backtrace || caller
-
- error = assertion_error.new(message)
- error.set_backtrace(backtrace)
+ # The intent of the method is to raise an assertion failure
+ # class that the test framework supports.
+ def self.raise_assertion(error, negated, backtrace=nil)
+ if not Exception === error
+ error = assertion_error.new(error)
+ end
+ error.set_negative(negated)
+ error.set_backtrace(backtrace || caller)
error.set_assertion(true)
fail error
end
# Returns the Exception class to be raised when an assertion fails.
def self.assertion_error
::Assertion
end
+ # NOT HAPPENING
+ ## Is ::Assay defined. This is used for integration of the Assay library.
+ #def self.assay?
+ # @_assay ||= defined?(::Assay)
+ #end
+
#
+ #def self.message(sym, neg, *args, &blk)
+ # if method = Message.lookup(sym)
+ # method = "non_#{method}" if neg
+ # Message.send(method, *args, &blk)
+ # else
+ # nil
+ # end
+ #end
+
+ #
if ::RUBY_VERSION >= '1.9'
eval "private :==, :!, :!=" # using eval here b/c it's a syntax error in 1.8-
end
# New Assertor.
@@ -122,35 +138,49 @@
# instead of
#
# assert something, parameter
#
# Returns +true+ or +false+ based on assertions success.
+ #--
+ # The use of #to_proc and #matches? as sepcial cases is not
+ # a robust solution.
+ #++
def assert(*args, &block)
return self if args.empty? && !block
target = block || args.shift
+ error = nil
+ # Lambda
if ::Proc === target || target.respond_to?(:to_proc)
block = target.to_proc
match = args.shift
result = block.arity > 0 ? block.call(@delegate) : block.call
if match
- pass = (match == result)
- msg = @message || "#{match.inspect} == #{result.inspect}"
+ pass = (match == result)
+ error = @message || "#{match.inspect} == #{result.inspect}"
else
- pass = result
- msg = @message || block.inspect # "#{result.inspect}"
+ pass = result
+ error = @message || block.inspect # "#{result.inspect}"
end
- elsif target.respond_to?(:matches?)
- pass = target.matches?(@delegate)
- msg = @message || matcher_message(target) || target.inspect
+
+ # Matcher
+ elsif target.respond_to?(:matches?) # Matchers
+ pass = target.matches?(@delegate)
+ error = @message || matcher_message(target) #|| target.inspect
+ if target.respond_to?(:exception)
+ #error_class = target.failure_class
+ error = target.exception #(:backtrace=>@backtrace, :negated=>@negated)
+ end
+
+ # Truthiness
else
- pass = target # truthiness
- msg = args.shift # optional mesage for TestUnit compatiability
+ pass = target # truthiness
+ error = args.shift # optional message for TestUnit compatiability
end
- __assert__(pass, msg)
+ __assert__(pass, error)
end
# Internal expect, provides all functionality associated
# with external #expect method. (See Expect#expect)
#
@@ -160,43 +190,53 @@
#++
def expect(*args, &block)
return self if args.empty? && !block # same as #assert
target = block || args.shift
+ error = nil
+ # Lambda
if ::Proc === target #|| target.respond_to?(:to_proc)
#block = target.to_proc
match = args.shift || @delegate
if exception?(match)
$DEBUG, debug = false, $DEBUG # b/c it always spits-out a NameError
begin
block.arity > 0 ? block.call(@delegate) : block.call
- pass = false
- msg = "#{match} not raised"
+ pass = false
+ error = "#{match} not raised"
rescue match => error
- pass = true
- msg = "#{match} raised"
+ pass = true
+ error = "#{match} raised"
rescue ::Exception => error
- pass = false
- msg = "#{match} expected but #{error.class} was raised"
+ pass = false
+ error = "#{match} expected but #{error.class} was raised"
ensure
$DEBUG = debug
end
else
result = block.arity > 0 ? block.call(@delegte) : block.call
pass = (match === result)
- msg = @message || "#{match.inspect} === #{result.inspect}"
+ error = @message || "#{match.inspect} === #{result.inspect}"
end
+
+ # Matcher
elsif target.respond_to?(:matches?)
- pass = target.matches?(@delegate)
- msg = @message || matcher_message(target) || target.inspect
+ pass = target.matches?(@delegate)
+ error = @message || matcher_message(target) #|| target.inspect
+ if target.respond_to?(:exception)
+ #error_class = target.failure_class
+ error = target.exception #failure(:backtrace=>@backtrace, :negated=>@negated)
+ end
+
+ # Case Equals
else
- pass = (target === @delegate)
- msg = @message || "#{target.inspect} === #{@delegate.inspect}"
+ pass = (target === @delegate)
+ error = @message || "#{target.inspect} === #{@delegate.inspect}"
end
- __assert__(pass, msg)
+ __assert__(pass, error)
end
#
def flunk(message=nil, backtrace=nil)
__assert__(false, message || @message)
@@ -231,56 +271,75 @@
end
# Converts a missing method into an Assertion.
#
# TODO: In future should probably be `@delegate.public_send(sym, *a, &b)`.
- def method_missing(sym, *a, &b)
- pass = @delegate.__send__(sym, *a, &b)
- __assert__(pass, @message || __msg__(sym, *a, &b))
- end
+ def method_missing(sym, *args, &block)
+ error = @message || compare_message(sym, *args, &block) || generic_message(sym, *args, &block)
- # Puts together a suitable error message.
- #
- def __msg__(m, *a, &b)
- inspection = @delegate.send(:inspect)
- if @negated
- "! #{inspection} #{m} #{a.collect{|x| x.inspect}.join(',')}"
- else
- "#{inspection} #{m} #{a.collect{|x| x.inspect}.join(',')}"
- end
- #self.class.message(m)[@delegate, *a] )
+ pass = @delegate.__send__(sym, *args, &block)
+
+ __assert__(pass, error)
end
+
# Simple assert.
#--
# TODO: Can the handling of the message be simplified/improved?
#++
- def __assert__(pass, message=nil)
- pass = @negated ^ pass
- Assertor.assert(pass, message, @backtrace)
+ def __assert__(pass, error=nil)
+ Assertor.assert(pass, error, @negated, @backtrace)
end
#
def matcher_message(matcher)
if @negated
if matcher.respond_to?(:negative_failure_message)
return matcher.failure_message
end
+ else
+ if matcher.respond_to?(:failure_message)
+ return matcher.failure_message
+ end
end
- if matcher.respond_to?(:failure_message)
- return matcher.failure_message
+ return nil
+ end
+
+ COMPARISON_OPERATORS = { :"==" => :"!=" }
+
+ # Message to use when making a comparion assertion.
+ def compare_message(operator, *args, &blk)
+ return nil unless COMPARISON_OPERATORS.key?(operator)
+ prefix = ""
+ a, b = @delegate, args.first
+ if @negated
+ op = COMPARISON_OPERATORS[operator]
+ if op
+ operator = op
+ else
+ prefix = "NOT "
+ end
end
- false
+ if a.size > 13 or b.size > 13
+ diff = ANSI::Diff.new(a,b)
+ prefix + "a #{operator} b\na) " + diff.diff1 + "\nb) " + diff.diff2
+ else
+ prefix + "#{a.inspect} #{operator} #{b.inspect}"
+ end
end
- # TODO: Ultimately better messages might be nice.
+ # Puts together a suitable error message.
#
- #def self.message(op,&block)
- # @message ||= {}
- # block ? @message[op.to_sym] = block : @message[op.to_sym]
- #end
- #
- #message(:==){ |*a| "Expected #{a[0].inspect} to be equal to #{a[1].inspect}" }
+ def generic_message(op, *a, &b)
+ inspection = @delegate.send(:inspect)
+ if @negated
+ "! #{inspection} #{op} #{a.collect{|x| x.inspect}.join(',')}"
+ else
+ "#{inspection} #{op} #{a.collect{|x| x.inspect}.join(',')}"
+ end
+ #self.class.message(m)[@delegate, *a] )
+ end
+
end
end
# DO WE MAKE THESE EXCEPTIONS?