| Module | BareTest::Assertion::Support |
| In: |
lib/baretest/assertion/support.rb
|
BareTest::Assertion::Support is per default included into BareTest::Assertion. It provides several methods to make it easier to write assertions.
Uses === to test whether the objects are equal
Can be used in either of the following ways:
equal expected, actual equal :expected => expected, :actual => actual
# File lib/baretest/assertion/support.rb, line 263
263: def case_equal(*args)
264: expected, actual, message = extract_args(args, :expected, :actual, :message)
265:
266: unless expected === actual then
267: failure_with_optional_message \
268: "Expected %s to be case equal (===) to %p but was %p",
269: "Expected %p but got %p",
270: message, expected, actual
271: end
272: true
273:
274: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
275: ::Kernel.raise
276: rescue Exception => e
277: failure "Could not compare %p with %p due to %s", expected, actual, e
278: end
To compare two collections (which must implement each) without considering order. E.g. two sets, or the keys of two hashes.
# File lib/baretest/assertion/support.rb, line 283
283: def equal_unordered(*args)
284: expected, actual, message = extract_args(args, :expected, :actual, :message)
285:
286: count = Hash.new(0)
287: expected.each { |element| count[element] += 1 }
288: actual.each { |element| count[element] -= 1 }
289:
290: unless count.all? { |key, value| value.zero? } then
291: only_in_expected = count.select { |ele, n| n > 0 }.map { |ele, n| ele }
292: only_in_actual = count.select { |ele, n| n < 0 }.map { |ele, n| ele }
293: if message then
294: failure "Expected %s to have the same items the same number of times, " \
295: "but %p are only in expected, and %p only in actual",
296: message, only_in_expected, only_in_actual
297: else
298: failure "Expected %p and %p to have the same items the same number of times, " \
299: "but %p are only in expected, and %p only in actual",
300: expected, actual, only_in_expected, only_in_actual
301: end
302: end
303: true
304:
305: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
306: ::Kernel.raise
307: rescue Exception => e
308: failure "Could not compare %p with %p due to %s", expected, actual, e
309: end
extract arg allows to use named or positional args
Example:
extract_args([1,2,3], :foo, :bar, :baz) # => [1,2,3]
extract_args({:foo => 1,:bar => 2, :baz => 3}, :foo, :bar, :baz) # => [1,2,3]
Usage:
def foo(*args)
x,y,z = extract_args(args, :x, :y, :z)
end
foo(1,2,3)
foo(:x => 1, :y => 2, :z => 3) # equivalent to the one above
# File lib/baretest/assertion/support.rb, line 400
400: def extract_args(args, *named)
401: if args.size == 1 && Hash === args.first then
402: args.first.values_at(*named)
403: else
404: args.first(named.size)
405: end
406: end
Raises Test::Assertion::Failure, which causes the Assertion to get the status :failure. Runs sprintf over message with *args Particularly useful with %p and %s.
# File lib/baretest/assertion/support.rb, line 376
376: def failure(message="Assertion failed", *args)
377: raise ::BareTest::Assertion::Failure, sprintf(message, *args)
378: end
A method to make raising failures that only optionally have a message easier.
# File lib/baretest/assertion/support.rb, line 365
365: def failure_with_optional_message(with_message, without_message, message, *args)
366: if message then
367: failure(with_message, message, *args)
368: else
369: failure(without_message, *args)
370: end
371: end
Uses eql? to test whether the objects are equal
Can be used in either of the following ways:
equal expected, actual equal :expected => expected, :actual => actual
# File lib/baretest/assertion/support.rb, line 216
216: def hash_key_equal(*args)
217: expected, actual, message = extract_args(args, :expected, :actual, :message)
218:
219: unless expected.eql?(actual) then
220: if message then
221: failure "Expected %s to be hash-key equal (eql?) to %p but was %p", message, expected, actual
222: else
223: failure "Expected %p but got %p", expected, actual
224: end
225: end
226: true
227:
228: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
229: ::Kernel.raise
230: rescue Exception => e
231: failure "Could not compare %p with %p due to %s", expected, actual, e
232: end
Raises a Failure if the given object is not an instance of the given class
# File lib/baretest/assertion/support.rb, line 330
330: def instance_of(*args)
331: expected, actual, message = extract_args(args, :expected, :actual, :message)
332: unless actual.instance_of?(expected) then
333: failure_with_optional_message \
334: "Expected %1$s to be an instance of %3$p, but was a %4$p",
335: "Expected %2$p to be an instance of %1$p, but was a %3$p",
336: message, expected, actual, actual.class
337: end
338: true
339:
340: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
341: ::Kernel.raise
342: rescue Exception => e
343: failure "Could not test whether %p is an instance of %p due to %s", actual, expected, e
344: end
Raises a Failure if the given object is not an instance of the given class or a descendant thereof
# File lib/baretest/assertion/support.rb, line 313
313: def kind_of(*args)
314: expected, actual, message = extract_args(args, :expected, :actual, :message)
315: unless actual.kind_of?(expected) then
316: failure_with_optional_message \
317: "Expected %1$s to be a kind of %3$p, but was a %4$p",
318: "Expected %2$p to be a kind of %1$p, but was a %3$p",
319: message, expected, actual, actual.class
320: end
321: true
322:
323: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
324: ::Kernel.raise
325: rescue Exception => e
326: failure "Could not test whether %p is a kind of %p due to %s", actual, expected, e
327: end
Uses == to test whether the objects are equal
Can be used in either of the following ways:
equal expected, actual equal :expected => expected, :actual => actual
# File lib/baretest/assertion/support.rb, line 239
239: def order_equal(*args)
240: expected, actual, message = extract_args(args, :expected, :actual, :message)
241:
242: unless expected == actual then
243: if message then
244: failure "Expected %s to be order equal (==) to %p but was %p", message, expected, actual
245: else
246: failure "Expected %p but got %p", expected, actual
247: end
248: end
249: true
250:
251: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
252: ::Kernel.raise
253: rescue Exception => e
254: failure "Could not compare %p with %p due to %s", expected, actual, e
255: end
Will raise a Failure if the given block doesn‘t raise or raises a different exception than the one provided You can optionally give an options :with_message, which is tested with === against the exception message.
Examples:
raises do raise "will work" end # => true raises SomeException do raise SomeException end # => true raises :with_message => "bar" do raise "bar" end # => true raises SomeException, :with_message => "bar"; raise SomeException, "bar" end # => true raises :with_message => /\Aknown \w+\z/; raise "known unknown" end # => true
# File lib/baretest/assertion/support.rb, line 93
93: def raises(expected_exception_class=nil, with_message=nil, opts={})
94: exception_class = expected_exception_class || StandardError
95: yield
96: rescue exception_class => exception
97: if expected_exception_class && exception.class != expected_exception_class then
98: failure "Expected the code to raise #{expected_exception_class}, but it raised #{exception.class} instead"
99: elsif with_message && !(with_message === exception.message) then
100: failure "Expected the code to raise with the message %p, but the message was %p",
101: with_message, exception.message
102: else
103: true
104: end
105: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
106: ::Kernel.raise
107: rescue => exception
108: failure "Expected the code to raise #{expected_exception_class}, but it raised #{exception.class} instead"
109: else
110: if expected_exception_class then
111: failure "Expected the code to raise #{expected_exception_class}, but nothing was raised"
112: else
113: failure "Expected the code to raise, but nothing was raised"
114: end
115: end
Will raise a Failure if the given block raises.
# File lib/baretest/assertion/support.rb, line 118
118: def raises_nothing
119: yield
120: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
121: ::Kernel.raise
122: rescue Exception => exception
123: failure "Expected the code to raise nothing, but it raised #{exception.class} (#{exception.message})"
124: else
125: true
126: end
Raises a Failure if the given object does not respond to all of the given method names. The method names may be specified as String or Symbol.
# File lib/baretest/assertion/support.rb, line 348
348: def respond_to(obj, *methods)
349: not_responded_to = methods.reject { |method_name| obj.respond_to?(method_name) }
350: unless not_responded_to.empty? then
351: must_respond_to = methods.map { |m| m.to_sym.inspect }.join(', ')
352: not_responded_to = not_responded_to.map { |m| m.to_sym.inspect }.join(', ')
353: failure "Expected %1$s to respond to all of %2$s, but it did not respond to %3$s",
354: obj, must_respond_to, not_responded_to
355: end
356: true
357:
358: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
359: ::Kernel.raise
360: rescue Exception => e
361: failure "Could not test whether %p responds to %p due to %s", obj, methods, e
362: end
Uses equal? to test whether the objects are the same
Can be used in either of the following ways:
same expected, actual same :expected => expected, :actual => actual
# File lib/baretest/assertion/support.rb, line 193
193: def same(*args)
194: expected, actual, message = extract_args(args, :expected, :actual, :message)
195:
196: unless expected.equal?(actual) then
197: if message then
198: failure "Expected %s to be the same (equal?) as %p but was %p", message, expected, actual
199: else
200: failure "Expected %p but got %p", expected, actual
201: end
202: end
203: true
204:
205: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
206: ::Kernel.raise
207: rescue Exception => e
208: failure "Could not compare %p with %p due to %s", expected, actual, e
209: end
Raises Test::Assertion::Skip, which causes the Assertion to get the status :skipped. Runs sprintf over message with *args Particularly useful with %p and %s.
# File lib/baretest/assertion/support.rb, line 383
383: def skip(message="Assertion was skipped", *args)
384: raise ::BareTest::Assertion::Skip, sprintf(message, *args)
385: end
Use this method to test whether certain code (e.g. a callback) was reached. touch marks that it was reached, touched tests for whether it was reached.
Example:
assert "Code in a Proc object is executed when invoking #call on it" do
a_proc = proc { touch :executed }
a_proc.call
touched(:executed)
end
# File lib/baretest/assertion/support.rb, line 153
153: def touch(thing=nil)
154: ::BareTest.touch(self, thing)
155: end
Used to verify that something was touched. You can also verify that something was touched a specific amount of times.
See touch
# File lib/baretest/assertion/support.rb, line 161
161: def touched(thing=nil, times=nil)
162: touched_times = ::BareTest.touched(self, thing)
163: if times then
164: unless touched_times == times then
165: if thing then
166: failure "Expected the code to touch %p %s times, but did %s times", thing, times, touched_times
167: else
168: failure "Expected the code to touch %s times, but did %s times", times, touched_times
169: end
170: end
171: elsif touched_times < 1 then
172: if thing then
173: failure "Expected the code to touch %p, but it was not touched", thing
174: else
175: failure "Expected the code to touch, but no touch happened"
176: end
177: end
178: true
179: end
For comparisons of Floats you shouldn‘t use == but for example a delta comparison instead, to take care of the possible rounding differences.
# File lib/baretest/assertion/support.rb, line 131
131: def within_delta(a, b, delta)
132: actual_delta = (a-b).abs
133: if actual_delta >= delta then
134: failure "Expected %p and %p to differ less than %p, but they were different by %p", a, b, delta, actual_delta
135: else
136: true
137: end
138: rescue ::BareTest::Assertion::Failure, *::BareTest::Assertion::PassthroughExceptions
139: ::Kernel.raise
140: rescue Exception => e
141: failure "Could not compare %p with %p due to %s", a, b, e
142: end
FIXME: undocumented and untested It‘s really ugly. You should use a mock instead.
# File lib/baretest/assertion/support.rb, line 48
48: def yields(subject, meth, args, *expected)
49: subject.__send__(meth, *args) do |*actual|
50: current = expected.shift
51: return false unless actual == current
52: end
53: return expected.empty?
54: end