Permalink
Browse files

Matchers created with the DSL can call methods directly on the current

running example.
  • Loading branch information...
1 parent ec3a147 commit e9a9e465b5a5691d49929766cca5c3cd0fe69cd7 @dchelimsky dchelimsky committed Mar 19, 2010
View
38 features/matchers/access_running_example.feature
@@ -1,17 +1,20 @@
-@wip
Feature: access running example
In order to take advantage of services that are available
in my examples when I'm writing matchers
- As an spec author
- I want to have an object that represents the running example
+ As a spec author
+ I want to call methods on the running example
- Scenario: matcher defined via DSL
+ If the method exists in the context of the example, it gets
+ called. If not, a NoMethodError is raised on the Matcher itself
+ (not the example).
+
+ Scenario: call method defined on example from matcher
Given a file named "example_spec.rb" with:
"""
Rspec::Matchers.define :bar do
match do |_|
- running_example.foo == "foo"
+ foo == "foo"
end
end
@@ -27,27 +30,24 @@ Feature: access running example
"""
When I run "rspec example_spec.rb"
Then I should see "1 example, 0 failures"
-
- Scenario: matcher defined via #new
+
+ Scenario: call method _not_ defined on example from matcher
Given a file named "example_spec.rb" with:
"""
- describe "something" do
- def bar
- Rspec::Matchers::Matcher.new :bar do
- match do |_|
- running_example.foo == "foo"
- end
- end
- end
-
- def foo
- "foo"
+ Rspec::Matchers.define :bar do
+ match do |_|
+ foo == "foo"
end
+ end
+ describe "something" do
it "does something" do
"foo".should bar
end
end
"""
When I run "rspec example_spec.rb"
- Then I should see "1 example, 0 failures"
+ Then I should see "1 example, 1 failure"
+ And I should see "undefined method"
+ And I should see "Rspec::Matchers::Matcher"
+ And I should not see "ExampleGroup"
View
1 lib/rspec/matchers/dsl.rb
@@ -4,6 +4,7 @@ module DSL
# See Rspec::Matchers
def define(name, &declarations)
define_method name do |*expected|
+ $matcher_execution_context = self
Rspec::Matchers::Matcher.new name, *expected, &declarations
end
end
View
16 lib/rspec/matchers/matcher.rb
@@ -22,11 +22,6 @@ def initialize(name, *expected, &declarations)
end
end
- def instance_exec(*args, &block)
- self.running_example ||= eval("running_example", block.binding) rescue nil
- super(*args, &block)
- end
-
#Used internally by objects returns by +should+ and +should_not+.
def matches?(actual)
@actual = actual
@@ -92,10 +87,15 @@ def chain(method, &block)
end
end
- protected
- attr_accessor :running_example
-
private
+
+ def method_missing(name, *args, &block)
+ begin
+ $matcher_execution_context.send name, *args, &block
+ rescue NoMethodError
+ super(name, *args, &block)
+ end
+ end
def making_declared_methods_public # :nodoc:
# Our home-grown instance_exec in ruby 1.8.6 results in any methods
View
33 spec/rspec/matchers/matcher_spec.rb
@@ -286,37 +286,32 @@ def assert_equal(a,b)
end
context "defined using the dsl" do
- it "can access the running_example" do
+ def a_method_in_the_example
+ "method defined in the example"
+ end
+
+ it "can access methods in the running_example" do
Rspec::Matchers.define(:__access_running_example) do
match do |actual|
- actual == running_example
+ a_method_in_the_example == "method defined in the example"
end
end
running_example.should __access_running_example
end
- end
-
- context "defined using #new" do
- it "can access the running_example" do
- @matcher = Rspec::Matchers::Matcher.new(:something) {}
- @matcher.send(:running_example).should eq(running_example)
- end
- end
- context "wrapped in a method" do
-
- def access_running_example
- Matcher.new(:access_running_example) do
+ it "raises NoMethodError for methods not in the running_example" do
+ Rspec::Matchers.define(:__raise_no_method_error) do
match do |actual|
- actual == running_example
+ a_method_not_in_the_example == "method defined in the example"
end
end
- end
-
- it "can access the running_example" do
- running_example.should access_running_example
+
+ expect do
+ running_example.should __raise_no_method_error
+ end.to raise_error(NoMethodError, /Rspec::Matchers::Matcher/)
end
end
+
end
end
end

0 comments on commit e9a9e46

Please sign in to comment.