From 07e1378a99ab6c4210882a1c48037bc026c8af62 Mon Sep 17 00:00:00 2001 From: Matthias Hennemeyer Date: Fri, 6 Feb 2009 17:51:46 +0800 Subject: [PATCH] Refactored def_matcher(), introduced build_matcher method. Signed-off-by: Jeremy McAnally --- .gitignore | 2 + lib/matchy.rb | 1 + lib/matchy/def_matcher.rb | 40 +------------------ lib/matchy/matcher_builder.rb | 44 +++++++++++++++++++++ test/test_def_matcher.rb | 4 +- test/test_matcher_builder.rb | 72 +++++++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 40 deletions(-) create mode 100644 lib/matchy/matcher_builder.rb create mode 100644 test/test_matcher_builder.rb diff --git a/.gitignore b/.gitignore index 088af20..2f30a53 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ pkg/* +.DS_Store + diff --git a/lib/matchy.rb b/lib/matchy.rb index b048db3..fcc110b 100644 --- a/lib/matchy.rb +++ b/lib/matchy.rb @@ -7,6 +7,7 @@ require 'matchy/expectation' require 'matchy/modals' require 'matchy/version' +require 'matchy/matcher_builder' require 'matchy/def_matcher' require 'matchy/built_in/enumerable_expectations' diff --git a/lib/matchy/def_matcher.rb b/lib/matchy/def_matcher.rb index 7b70b41..387a338 100644 --- a/lib/matchy/def_matcher.rb +++ b/lib/matchy/def_matcher.rb @@ -1,45 +1,9 @@ module Matchy module DefMatcher + include Matchy::MatcherBuilder def def_matcher(matcher_name, &block) self.class.send :define_method, matcher_name do |*args| - match_block = lambda do |actual, matcher| - block.call(actual, matcher, args) - end - body = lambda do |klass| - @matcher_name = matcher_name.to_s - def self.matcher_name - @matcher_name - end - - attr_accessor :positive_msg, :negative_msg, :msgs - attr_reader :matcher_name - def initialize match_block, test_case - @test_case = test_case - @match_block = match_block - @matcher_name = self.class.matcher_name - end - - def method_missing id, *args, &block - require 'ostruct' - (self.msgs ||= []) << OpenStruct.new( "name" => id, "args" => args, "block" => block ) - self - end - - def matches? given - @positive_msg ||= "Matching with '#{matcher_name}' failed, although it should match." - @negative_msg ||= "Matching with '#{matcher_name}' passed, although it should_not match." - @match_block.call(given, self) - end - - def failure_message - self.positive_msg - end - - def negative_failure_message - self.negative_msg - end - end - Class.new(Matchy::Expectations::Base, &body).new(match_block, self) + build_matcher(matcher_name, args, &block) end end end diff --git a/lib/matchy/matcher_builder.rb b/lib/matchy/matcher_builder.rb new file mode 100644 index 0000000..9130589 --- /dev/null +++ b/lib/matchy/matcher_builder.rb @@ -0,0 +1,44 @@ +module Matchy + module MatcherBuilder + def build_matcher(matcher_name=nil, args=[], &block) + match_block = lambda do |actual, matcher| + block.call(actual, matcher, args) + end + body = lambda do |klass| + @matcher_name = matcher_name.to_s + def self.matcher_name + @matcher_name + end + + attr_accessor :positive_msg, :negative_msg, :msgs + attr_reader :matcher_name + def initialize match_block, test_case + @test_case = test_case + @match_block = match_block + @matcher_name = self.class.matcher_name + end + + def method_missing id, *args, &block + require 'ostruct' + (self.msgs ||= []) << OpenStruct.new( "name" => id, "args" => args, "block" => block ) + self + end + + def matches? given + @positive_msg ||= "Matching with '#{matcher_name}' failed, although it should match." + @negative_msg ||= "Matching with '#{matcher_name}' passed, although it should_not match." + @match_block.call(given, self) + end + + def failure_message + self.positive_msg + end + + def negative_failure_message + self.negative_msg + end + end + Class.new(Matchy::Expectations::Base, &body).new(match_block, self) + end + end +end \ No newline at end of file diff --git a/test/test_def_matcher.rb b/test/test_def_matcher.rb index 4929864..ec13058 100644 --- a/test/test_def_matcher.rb +++ b/test/test_def_matcher.rb @@ -29,7 +29,7 @@ def test_pass_positive def_matcher :matcher do |given, matcher, args| true end - lambda {1.should matcher}.should_not raise_error + 1.should matcher end def test_fail_negative @@ -43,7 +43,7 @@ def test_pass_negative def_matcher :matcher do |given, matcher, args| false end - lambda {1.should_not matcher}.should_not raise_error + 1.should_not matcher end def test_takes_arguments diff --git a/test/test_matcher_builder.rb b/test/test_matcher_builder.rb new file mode 100644 index 0000000..1cf7f61 --- /dev/null +++ b/test/test_matcher_builder.rb @@ -0,0 +1,72 @@ +require File.dirname(__FILE__) + '/test_helper.rb' + +class TestMatcherBuilder < Test::Unit::TestCase + include Matchy::MatcherBuilder + + def setup + @obj = Object.new + end + + def test_matcher_responds_to_matches + block = lambda {|given, matcher, args| true} + build_matcher(:m, &block).should respond_to(:matches?) + end + + def test_fail_positive + block = lambda {|given, matcher, args| false} + lambda {@obj.should build_matcher(:m, &block)}.should raise_error + end + + def test_pass_positive + block = lambda {|given, matcher, args| true} + @obj.should build_matcher(:m, &block) + end + + def test_fail_negative + block = lambda {|given, matcher, args| true} + lambda {@obj.should_not build_matcher(:m, &block)}.should raise_error + end + + def test_pass_negative + block = lambda {|given, matcher, args| false} + @obj.should_not build_matcher(:m, &block) + end + + def test_takes_arguments + block = lambda {|given, matcher, args| $args = args; true} + @obj.should build_matcher(:m,[1,2,3], &block) + $args.should eql([1,2,3]) + end + + def test_received_method + block = lambda {|given, matcher, args| $msgs = matcher.msgs; true} + @obj.should build_matcher(:m, &block).method1 + $msgs[0].name.should eql(:method1) + end + + def test_received_method_takes_args + block = lambda {|given, matcher, args| $msgs = matcher.msgs; true} + @obj.should build_matcher(:m, &block).method1(1,2,3) + $msgs[0].args.should eql([1,2,3]) + end + + def test_received_method_takes_block + block = lambda {|given, matcher, args| $msgs = matcher.msgs; true} + @obj.should build_matcher(:m, &block).method1 { "Hello, World!"} + $msgs[0].block.call.should eql("Hello, World!") + end + + def test_received_method_chained + block = lambda {|given, matcher, args| $msgs = matcher.msgs; true} + @obj.should build_matcher(:m, &block).method1(1,2,3) { "Hello, World!"}. + method2(4,5,6) { "Hello chained messages" } + + $msgs[0].name.should eql(:method1) + $msgs[1].name.should eql(:method2) + $msgs[0].args.should eql([1,2,3]) + $msgs[1].args.should eql([4,5,6]) + $msgs[0].block.call.should eql("Hello, World!") + $msgs[1].block.call.should eql("Hello chained messages") + end + +end