module Matchy::Expectations::TestCaseExtensions

Public Instance Methods

be(*obj) click to toggle source

Simply checks if the receiver matches the expected object. TODO: Fill this out to implement much of the RSpec functionality (and then some)

Examples

"hello".should be("hello")
(13 < 20).should be(true)
# File lib/matchy/built_in/truth_expectations.rb, line 12
def be(*obj)
  build_matcher(:be, obj) do |receiver, matcher, args|
    @receiver, expected = receiver, args[0]
    matcher.positive_failure_message = "Expected #{@receiver.inspect} to be #{expected.inspect}."
    matcher.negative_failure_message = "Expected #{@receiver.inspect} to not be #{expected.inspect}."
    expected == @receiver
  end
end
be_close(obj, delta = 0.3) click to toggle source

Checks if the given object is within a given object and delta.

Examples

(20.0 - 2.0).should be_close(18.0)
(13.0 - 4.0).should be_close(9.0, 0.5)
# File lib/matchy/built_in/truth_expectations.rb, line 28
def be_close(obj, delta = 0.3)
  build_matcher(:be_close, [obj, delta]) do |receiver, matcher, args|
    @receiver, expected, delta = receiver, args[0], args[1]
    matcher.positive_failure_message = "Expected #{@receiver.inspect} to be close to #{expected.inspect} (delta: #{delta})."
    matcher.negative_failure_message = "Expected #{@receiver.inspect} to not be close to #{expected.inspect} (delta: #{delta})."
    (@receiver - expected).abs < delta
  end
end
be_success() click to toggle source

Asks given for success?(). This is necessary because Rails Integration::Session overides #method_missing without grace.

Examples

@response.should be_success
# File lib/matchy/built_in/truth_expectations.rb, line 110
def be_success
  ask_for(:success, :with_arg => nil)
end
change(&block) click to toggle source

Checks if the given block alters the value of the block attached to change

Examples

lambda {var += 1}.should change {var}.by(1)
lambda {var += 2}.should change {var}.by_at_least(1)
lambda {var += 1}.should change {var}.by_at_most(1)
lambda {var += 2}.should change {var}.from(1).to(3) if var = 1
# File lib/matchy/built_in/change_expectations.rb, line 11
def change(&block)
  build_matcher(:change) do |receiver, matcher, args|
    before, done, after = block.call, receiver.call, block.call
    comparison = after != before
    if list = matcher.chained_messages
      comparison = case list[0].name
        # todo: provide meaningful messages
      when :by          then (after == before + list[0].args[0] || after == before - list[0].args[0])
      when :by_at_least then (after >= before + list[0].args[0] || after <= before - list[0].args[0])
      when :by_at_most  then (after <= before + list[0].args[0] && after >= before - list[0].args[0])
      when :from        then (before == list[0].args[0]) && (after == list[1].args[0])
      end
    end
    matcher.positive_failure_message = "given block shouldn't alter the block attached to change"
    matcher.negative_failure_message = "given block should alter the block attached to change"
    comparison
  end
end
eql(*obj) click to toggle source

Calls eql? on the given object (i.e., are the objects the same value?)

Examples

1.should_not eql(1.0)
(12 / 6).should eql(6)
# File lib/matchy/built_in/truth_expectations.rb, line 55
def eql(*obj)
  ask_for(:eql, :with_arg => obj)
end
equal(*obj) click to toggle source

Calls equal? on the given object (i.e., do the two objects have the same object_id?)

Examples

x = [1,2,3]
y = [1,2,3]

# Different object_id's...
x.should_not equal(y)

# The same object_id
x[0].should equal(y[0])
# File lib/matchy/built_in/truth_expectations.rb, line 72
def equal(*obj)
  ask_for(:equal, :with_arg => obj)
end
exclude(*obj) click to toggle source

Expects the receiver to exclude the given object(s). You can provide multiple arguments to see if all of them are included.

Examples

[1,2,3].should exclude(16)
[7,8,8].should_not exclude(7)
['a', 'b', 'c'].should exclude('e', 'f', 'g')
# File lib/matchy/built_in/enumerable_expectations.rb, line 27
def exclude(*obj)
  _clude(:exclude, obj)
end
exist() click to toggle source

Calls exist? on the given object.

Examples

# found_user.exist?
found_user.should exist
# File lib/matchy/built_in/truth_expectations.rb, line 44
def exist
  ask_for(:exist, :with_arg => nil)
end
include(*obj) click to toggle source

Calls include? on the receiver for any object. You can also provide multiple arguments to see if all of them are included.

Examples

[1,2,3].should include(1)
[7,8,8].should_not include(3)
['a', 'b', 'c'].should include('a', 'c')
# File lib/matchy/built_in/enumerable_expectations.rb, line 14
def include(*obj)
  _clude(:include, obj)
end
method_missing(name, *args, &block) click to toggle source

be_*something(*args)

This #method_missing acts as a matcher builder.

If a call to be_xyz() reaches this #method_missing (say: obj.should be_xyz), a matcher with the name xyz will be built, whose defining property is that it returns the value of obj.xyz? for matches?.

Examples

nil.should be_nil
17.should be_kind_of(Fixnum)
obj.something? #=> true
obj.should be_something
# File lib/matchy/built_in/truth_expectations.rb, line 127
def method_missing(name, *args, &block)
  if (name.to_s =~ /^be_(.+)/)
    ask_for($1, :with_arg => args)
  else
    old_missing(name, *args, &block)
  end
end
Also aliased as: old_missing
old_missing(name, *args, &block)
Alias for: method_missing
raise_error(*obj) click to toggle source

Expects a lambda to raise an error. You can specify the error or leave it blank to encompass any error.

Examples

lambda { raise "FAILURE." }.should raise_error
lambda { puts i_dont_exist }.should raise_error(NameError)
# File lib/matchy/built_in/error_expectations.rb, line 12
def raise_error(*obj)
  build_matcher(:raise_error, obj) do |receiver, matcher, args|
    expected = args[0] || Exception
    raised = false
    error = nil
    begin
      receiver.call
    rescue Exception => e
      raised = true
      error = e
    end
    if expected.respond_to?(:ancestors) && expected.ancestors.include?(Exception)
      matcher.positive_failure_message = "Expected #{receiver.inspect} to raise #{expected.name}, " + 
        (error ? "but #{error.class.name} was raised instead." : "but none was raised.")
      matcher.negative_failure_message = "Expected #{receiver.inspect} to not raise #{expected.name}."
      comparison = (raised && error.class.ancestors.include?(expected))
    else
      message = error ? error.message : "none"
      matcher.positive_failure_message = "Expected #{receiver.inspect} to raise error with message matching '#{expected}', but '#{message}' was raised."
      matcher.negative_failure_message = "Expected #{receiver.inspect} to raise error with message not matching '#{expected}', but '#{message}' was raised."
      comparison = (raised && (expected.kind_of?(Regexp) ? ((error.message =~ expected) ? true : false) : expected == error.message))
    end
    comparison
  end
end
respond_to(*meth) click to toggle source

Checks if the given object responds to the given method

Examples

"foo".should respond_to(:length)
{}.should respond_to(:has_key?)
# File lib/matchy/built_in/truth_expectations.rb, line 99
def respond_to(*meth)
  ask_for(:respond_to, :with_arg => meth)
end
satisfy(*obj) click to toggle source

A last ditch way to implement your testing logic. You probably shouldn't use this unless you have to.

Examples

(13 - 4).should satisfy(lambda {|i| i < 20})
"hello".should_not satisfy(lambda {|s| s =~ /hi/})
# File lib/matchy/built_in/truth_expectations.rb, line 84
def satisfy(*obj)
  build_matcher(:satisfy, obj) do |receiver, matcher, args|
    @receiver, expected = receiver, args[0]
    matcher.positive_failure_message = "Expected #{@receiver.inspect} to satisfy given block."
    matcher.negative_failure_message = "Expected #{@receiver.inspect} to not satisfy given block."
    expected.call(@receiver) == true
  end
end
throw_symbol(*obj) click to toggle source

Expects a lambda to throw an error.

Examples

lambda { throw :thing }.should throw_symbol(:thing)
lambda { "not this time" }.should_not throw_symbol(:hello)
# File lib/matchy/built_in/error_expectations.rb, line 45
def throw_symbol(*obj)
  build_matcher(:throw_symbol, obj) do |receiver, matcher, args|
    raised, thrown_symbol, expected = false, nil, args[0]
    begin
      receiver.call
    rescue NameError => e
      raise e unless e.message =~ /uncaught throw/
      raised = true
      thrown_symbol = e.name.to_sym if e.respond_to?(:name)
    rescue ArgumentError => e
      raise e unless e.message =~ /uncaught throw/
      thrown_symbol = e.message.match(/uncaught throw :(.+)/)[1].to_sym
    end
    matcher.positive_failure_message = "Expected #{receiver.inspect} to throw :#{expected}, but " +
      "#{thrown_symbol ? ':' + thrown_symbol.to_s + ' was thrown instead' : 'no symbol was thrown'}."
    matcher.negative_failure_message = "Expected #{receiver.inspect} to not throw :#{expected}."
    expected == thrown_symbol
  end
end

Private Instance Methods

_clude(sym, obj) click to toggle source
# File lib/matchy/built_in/enumerable_expectations.rb, line 32
def _clude(sym, obj)
  build_matcher(sym, obj) do |given, matcher, args|
    matcher.positive_failure_message = "Expected #{given.inspect} to #{sym} #{args.inspect}."
    matcher.negative_failure_message = "Expected #{given.inspect} to not #{sym} #{args.inspect}."
    args.inject(true) {|m,o| m && (given.include?(o) == (sym == :include)) }
  end
end
ask_for(sym, option={}) click to toggle source
# File lib/matchy/built_in/truth_expectations.rb, line 136
def ask_for(sym, option={})
  build_matcher(sym, (option[:with_arg] || [])) do |receiver, matcher, args|
    expected, meth = args[0], (sym.to_s + "?" ).to_sym
    matcher.positive_failure_message = "Expected #{receiver.inspect} to return true for #{sym}?, with '#{(expected && expected.inspect) || 'no args'}'."
    matcher.negative_failure_message = "Expected #{receiver.inspect} to not return true for #{sym}?, with '#{(expected && expected.inspect) || 'no args'}'."
    expected ? receiver.send(meth, expected) : receiver.send(meth)
  end
end