Getting access to assertion methods from a Shoulda should method
I have a shoulda macro/method that tests controller responses for XPath conditions like so:
def self.should_have_xpath(path, &block)
should "have an ele开发者_开发知识库ment matching the path: #{path}" do
xml = REXML::Document.new @response.body
match = XPath.match(xml, path)
if block_given?
yield match
else
assert match.size != 0, "No nodes matching '#{path}'"
end
end
end
The XPath matching and built-in assertion works great. However, I have one testcase where I want exactly one match element to exist. This is the job of the optional block: expose the XPath match to the caller so that it can perform additional/context-specific assertions.
Unfortunately, when I actually pass a block:
should_have_xpath("//my/xpath/expression") { |match| assert_equal 1, match.size }
... I get this error:
NoMethodError: undefined method `assert_equal' for Users::SessionsControllerTest:Class
This is (as I understand it) because of the way Shoulda works: the parameters passed to the "should" call (including the block) are defined in the context of the test class and not the instance of the test class. Test::Unit::Assertions.assert* are module instance methods, so I can't access them conveniently.
So, my question is: Is there a convenient/idiomatic way to access the assert* methods from Test::Unit::Assertions without too much trouble? The solution has to work with Shoulda, though it doesn't necessarily need to be dependent on Shoulda; a straight Ruby way would be fine.
This should work as you want it to:
def self.should_have_xpath(path, &block)
should "have an element matching the path: #{path}" do
# ...
block.bind(self).call(match)
end
end
I've got a working solution:
def self.should_have_xpath(path, &block)
should "have an element matching the path: #{path}" do
# ...
yield match, self
end
end
should_have_xpath( "//my/xpath/expression" ) { |match, test | test.assert_equal 1, match.size }
I don't especially like having to (remember to) pass the test instance every time, which is why I'm hoping Stack Overflow will be able to come up with a better answer.
精彩评论