Created
November 18, 2011 20:05
-
-
Save jonathanpenn/1377594 to your computer and use it in GitHub Desktop.
An expectation framework with matchers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is just a fun experiment to write an expectation | |
# framework with matchers. NOT PRODUCTION READY! :) | |
def main | |
include Expectation | |
my_matchers = matchers do | |
define_matcher :to_be do |expected, actual| | |
matches? { expected == actual } | |
message do | |
"Expected %p to be equal to %p" % [actual, expected] | |
end | |
end | |
define_matcher :to_be_within do |args, actual| | |
within = args.first | |
expected = args[1].fetch(:of) | |
matches? { expected + within >= actual && expected - within <= actual } | |
message do | |
"Expected %p to be within %p of %p" % [actual, within, expected] | |
end | |
end | |
end | |
include my_matchers | |
expect 5, to_be(5) | |
expect 30, to_be_within(2, of: 21) | |
end | |
module Expectation | |
def matchers &block | |
mod = Module.new | |
mod.extend MatcherBuilder | |
mod.class_eval &block | |
mod | |
end | |
def expect value, matcher | |
matcher.match_to value | |
raise MatchError.new(matcher.message) unless matcher.matches? | |
end | |
class MatchError < StandardError; end | |
module MatcherBuilder | |
def define_matcher name, &definition | |
define_method name do |*expected| | |
expected = expected.first if expected.length == 1 | |
MatcherContainer.new expected, &definition | |
end | |
end | |
end | |
class MatcherContainer | |
class DefinitionProxy | |
attr_reader :matches_block, :message_block | |
def matches? &block | |
@matches_block = block | |
end | |
def message &block | |
@message_block = block | |
end | |
end | |
def initialize expected, &definition | |
@expected = expected | |
@definition = definition | |
end | |
def match_to actual | |
@proxy = DefinitionProxy.new | |
@proxy.instance_exec(@expected, actual, &@definition) | |
end | |
def matches? | |
@proxy.matches_block.call | |
end | |
def message | |
@proxy.message_block.call | |
end | |
end | |
end | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment