lib/assay/assertion.rb in assay-0.3.0 vs lib/assay/assertion.rb in assay-0.4.0
- old
+ new
@@ -1,149 +1,123 @@
-require 'ansi/diff'
-require 'assay/matcher'
+require 'brass'
-module Assay
+require_relative 'core_ext/na'
+require_relative 'core_ext/kernel'
- #
- class Assertion < Exception
+require_relative 'assertor'
+require_relative 'assertable'
- # When displaying errors, use this as a rule of thumb
- # for determining when the inspected object will be too
- # big for a single line message.
- SIZE_LIMIT = 13
+# TODO: Don't care for Proc === subject conditional code, but not
+# sure how else to deal with lambda subjects.
- # Returns Matcher for the failure class.
- def self.to_matcher(*args, &blk)
- Matcher.new(self, *args, &blk)
- end
+# Base class for all Assay classes. This class defines all the logic
+# for assertions as exception classes as well as test assertion matchers.
+#
+class Assertion < Exception
- #
- def self.assertable_method
- "assert_#{assertion_name}"
- end
+ extend Assay::Assertable
- #
- def self.assert(*args, &blk)
- opts = Hash === args.last ? args.pop : {}
+ #
+ # When displaying errors, use this as a rule of thumb
+ # for determining when the inspected object will be too
+ # big for a single line message.
+ #
+ SIZE_LIMIT = 13
- backtrace = opts[:backtrace] || caller
- message = opts[:message]
-
- err = new(message, *args, &blk)
- err.set_backtrace(backtrace)
- err.assert
-
- #chk = check(*args, &blk)
- #msg = fail_message(*args, &blk)
- #if !chk
- # msg = opts[:message]
- # btr = opts[:backtrace] || caller
- # err = new(msg, *args)
- # err.set_backtrace(btr)
- # fail err
- #end
+ #
+ # Each new subclass must call the +register+ method. This is not an option!
+ # The method must be called in order to add the class to the Assertion
+ # name and operator indicies, so they might be looked-up efficiently by
+ # other libraries.
+ #
+ def self.register(op, name=nil)
+ case op.to_s
+ when /\W/
+ @operator = op.to_sym
+ @assertive_name = name.to_sym if name
+ else
+ @operator = (op.to_s + '?').to_sym
+ @assertive_name = op.to_sym
end
- #
- def self.refute(*args, &blk)
- opts = Hash === args.last ? args.pop : {}
+ operator_index[operator] = self
+ name_index[assertive_name] = self
+ end
- backtrace = opts[:backtrace] || caller
- message = opts[:message]
+ #
+ # When Assertion is inherited, a list of all Assertion subclasses is kept.
+ # This can be used to assertions frameworks with dynamic implementations.
+ #
+ def self.inherited(base)
+ @@by_operator = nil
+ @@by_name = nil
+ subclasses << base
+ end
- err = new(message, *args, &blk)
- err.set_backtrace(backtrace)
- err.refute
+ #
+ # List of all subclasses of Assertion.
+ #
+ def self.subclasses
+ @@subclasses ||= []
+ end
- #opts = Hash === args.last ? args.pop : {}
- #chk = check!(*args, &blk)
- ##msg = fail_message!(*args, &blk)
- #if !chk
- # msg = opts[:message]
- # btr = opts[:backtrace] || caller
- # err = new(msg, :backtrace=>btr, :arguments=>args)
- # fail err
- #end
- end
+ #
+ # If operator is not given, returns a hash table of assertion classes
+ # indexed by operator.
+ #
+ def self.by_operator(operator=nil)
+ return operator_index.dup unless operator
+ operator_index[operator.to_sym]
+ end
- #
- def self.pass?(*args, &blk)
- raise NotImplementedError
- end
+ #
+ # If operator is not given, returns a hash table of assertion classes
+ # indexed by assertive name.
+ #
+ def self.by_name(name=nil)
+ return name_index.dup unless name
+ name_index[name.to_sym]
+ end
- #
- def self.fail?(*args, &blk)
- ! pass?(*args, &blk)
- end
+ private
- #
- def initialize(message=nil, *arguments, &block)
- message ? super(message % arguments) : super()
-
- @mesg = message # why isn't this in @mesg from super()?
- @arguments = arguments
- @block = block
-
- #set_arguments options[:arguments] if options[:arguments]
- #set_negative options[:negated] if options[:negated]
- #set_backtrace options[:backtrace] if options[:backtrace]
+ def self.operator_index
+ @@operator_index ||= {}
end
- # Failure is always a type of assertion.
- #
- # This method allows Assay's classes to work in any test framework
- # that supports this interface.
- def assertion?
- true # @assertion = true if @assertion.nil?
+ def self.name_index
+ @@name_index ||= {}
end
- #
- def pass?
- self.class.pass?(*@arguments, &@block) #^ @negative
- end
+ #
+ # Setup new Assertion object.
+ #
+ def initialize(msg=nil) #, *criteria, &block)
+ super(msg)
- #
- def fail?
- not pass?
- end
+ #@criteria = criteria
+ #@block = block
+ #@not = false
- #
- def assert
- #@negative = false
- raise self unless pass?
- end
+ @assertion = true
- #
- def refute
- #@negative = true
- raise self unless fail?
- end
+ #options = (Hash === criteria.last ? criteria.pop : {})
+ #set_backtrace(options[:backtrace]) if options[:backtrace]
+ #set_negative(options[:negated]) if options[:negated]
+ end
- #
- def negative?
- @negative
- end
+end
- # Set whether this failure was the inverse of it's normal meaning.
- # For example, `!=` rather than `==`.
- def set_negative(negative)
- @negative = !!negative
- end
- # Set arguments used to make assertion.
- def set_arguments(arguments)
- @arguments = arguments
- #@block = block
- end
+=begin
- #
- def to_s
- if @negative
- "NOT " + super()
- else
- super()
- end
- end
+ #
+ #def to_s
+ # #if @negative
+ # # "NOT " + super()
+ # #else
+ # super()
+ # #end
+ #end
- end
+=end
-end