Class: AE::Assertor
- Inherits:
- BasicObject
- Includes:
- Subjunctive
- Defined in:
- lib/ae/assertor.rb,
lib/ae/subjunctive.rb,
lib/ae/adapters/testunit.rb
Overview
:nodoc:
Constant Summary collapse
- ZERO_COUNTS =
Initial settings of assertion counts.
{:total=>0,:pass=>0,:fail=>0}
Class Method Summary collapse
-
.assert(pass, message = nil, backtrace = nil) ⇒ Object
Basic assertion.
-
.assertion_error ⇒ Object
Returns the Exception class to be raised when an assertion fails.
-
.counts ⇒ Object
Returns Hash used to track assertion counts.
-
.increment_counts(pass) ⇒ Object
Increment assertion counts.
-
.raise_assertion(message, backtrace = nil) ⇒ Object
This method can be replaced to support alternate frameworks.
-
.recount(reset = {}) ⇒ Object
Reset assertion counts.
Instance Method Summary collapse
-
#=~(match) ⇒ Object
Ruby seems to have a quark in it’s implementation whereby this must be defined explicitly, otherwise it somehow skips #method_missing.
-
#assert(*args, &block) ⇒ Object
Internal assert, provides all functionality associated with external #assert method.
-
#expect(*args, &block) ⇒ Object
Internal expect, provides all functionality associated with external #expect method.
- #flunk(message = nil, backtrace = nil) ⇒ Object
-
#initialize(delegate, opts = {}) ⇒ Assertor
constructor
New Assertor.
- #inspect ⇒ Object
-
#not(msg = nil) ⇒ Object
Negate the meaning of the assertion.
- #send(op, *a, &b) ⇒ Object
Methods included from Subjunctive
Methods inherited from BasicObject
find_hidden_method, hide, reveal
Constructor Details
#initialize(delegate, opts = {}) ⇒ Assertor
New Assertor.
95 96 97 98 99 100 |
# File 'lib/ae/assertor.rb', line 95 def initialize(delegate, opts={}) #, backtrace) @delegate = delegate @message = opts[:message] @backtrace = opts[:backtrace] || caller #[1..-1] @negated = !!opts[:negated] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *a, &b) ⇒ Object (private)
Converts a missing method into an Assertion.
TODO: In future should probably be ‘@delegate.public_send(sym, *a, &b)`.
236 237 238 239 |
# File 'lib/ae/assertor.rb', line 236 def method_missing(sym, *a, &b) pass = @delegate.__send__(sym, *a, &b) __assert__(pass, @message || __msg__(sym, *a, &b)) end |
Class Method Details
.assert(pass, message = nil, backtrace = nil) ⇒ Object
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.
61 62 63 64 65 66 67 68 69 |
# File 'lib/ae/assertor.rb', line 61 def self.assert(pass, =nil, backtrace=nil) increment_counts(pass) if !pass backtrace = backtrace || caller = || 'flunk' raise_assertion(, backtrace) end return pass end |
.assertion_error ⇒ Object
Returns the Exception class to be raised when an assertion fails.
84 85 86 |
# File 'lib/ae/assertor.rb', line 84 def self.assertion_error ::Assertion end |
.counts ⇒ Object
Returns Hash used to track assertion counts.
24 25 26 |
# File 'lib/ae/assertor.rb', line 24 def self.counts $assertion_counts end |
.increment_counts(pass) ⇒ Object
Increment assertion counts. If pass
is true
then :total
and :pass
are increased. If pass
if false
then :total
and :fail
are incremented.
48 49 50 51 52 53 54 55 56 |
# File 'lib/ae/assertor.rb', line 48 def self.increment_counts(pass) counts[:total] += 1 if pass counts[:pass] += 1 else counts[:fail] += 1 end return counts end |
.raise_assertion(message, backtrace = nil) ⇒ Object
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.
74 75 76 77 78 79 80 81 |
# File 'lib/ae/assertor.rb', line 74 def self.raise_assertion(, backtrace=nil) backtrace = backtrace || caller error = assertion_error.new() error.set_backtrace(backtrace) error.set_assertion(true) fail error end |
.recount(reset = {}) ⇒ Object
Reset assertion counts.
reset - Hash which will be used to set counts manually (optional).
Returns the Hash of previous counts.
33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/ae/assertor.rb', line 33 def self.recount(reset={}) old_counts = counts.dup if reset.empty? counts.replace(ZERO_COUNTS.dup) else reset.each do |type, value| counts[type.to_sym] = value end end return old_counts end |
Instance Method Details
#=~(match) ⇒ Object
Ruby seems to have a quark in it’s implementation whereby this must be defined explicitly, otherwise it somehow skips #method_missing.
208 209 210 |
# File 'lib/ae/assertor.rb', line 208 def =~(match) method_missing(:"=~", match) end |
#assert(*args, &block) ⇒ Object
Internal assert, provides all functionality associated with external #assert method. (See Assert#assert)
NOTE: I’m calling YAGNI on using extra arguments to pass to the block. The interface is much nicer if a macro is created to handle any neccessry arguments. Eg.
assert something(parameter)
instead of
assert something, parameter
Returns true
or false
based on assertions success.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/ae/assertor.rb', line 127 def assert(*args, &block) return self if args.empty? && !block target = block || args.shift 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}" else pass = result msg = @message || block.inspect # "#{result.inspect}" end elsif target.respond_to?(:matches?) pass = target.matches?(@delegate) msg = @message || (target) || target.inspect else pass = target # truthiness msg = args.shift # optional mesage for TestUnit compatiability end __assert__(pass, msg) end |
#expect(*args, &block) ⇒ Object
Internal expect, provides all functionality associated with external #expect method. (See Expect#expect)
– TODO: Should we deprecate the receiver matches in favor of #expected ? In other words, should the || @delegate
be dropped? ++
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/ae/assertor.rb', line 161 def expect(*args, &block) return self if args.empty? && !block # same as #assert target = block || args.shift 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" rescue match => error pass = true msg = "#{match} raised" rescue ::Exception => error pass = false msg = "#{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}" end elsif target.respond_to?(:matches?) pass = target.matches?(@delegate) msg = @message || (target) || target.inspect else pass = (target === @delegate) msg = @message || "#{target.inspect} === #{@delegate.inspect}" end __assert__(pass, msg) end |
#flunk(message = nil, backtrace = nil) ⇒ Object
201 202 203 |
# File 'lib/ae/assertor.rb', line 201 def flunk(=nil, backtrace=nil) __assert__(false, || @message) end |
#inspect ⇒ Object
218 219 220 |
# File 'lib/ae/assertor.rb', line 218 def inspect @delegate.inspect end |
#not(msg = nil) ⇒ Object
Negate the meaning of the assertion.
– TODO: Should this return a new Assertor instead of in place negation? ++
107 108 109 110 111 |
# File 'lib/ae/assertor.rb', line 107 def not(msg=nil) @negated = !@negated @message = msg if msg self end |
#send(op, *a, &b) ⇒ Object
213 214 215 |
# File 'lib/ae/assertor.rb', line 213 def send(op, *a, &b) method_missing(op, *a, &b) end |