从Shoulda应该访问断言方法

时间:2010-02-11 04:43:38

标签: ruby assertions shoulda testunit

我有一个shoulda宏/方法来测试XPath条件的控制器响应,如下所示:

def self.should_have_xpath(path, &block)
  should "have an element 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

XPath匹配和内置断言非常有效。但是,我有一个测试用例,我希望完全存在一个匹配元素。这是可选块的作用:将XPath匹配公开给调用者,以便它可以执行其他/特定于上下文的断言。

不幸的是,当我实际传递一个块时:

should_have_xpath("//my/xpath/expression") { |match| assert_equal 1, match.size }

...我收到此错误:

  

NoMethodError:用户的未定义方法`assert_equal':: SessionsControllerTest:Class

这是(据我所知)因为Shoulda的工作方式:传递给“should”调用的参数(包括块)是在测试类的上下文中定义的,而不是测试类的实例。 Test :: Unit :: Assertions.assert *是模块实例方法,因此我无法方便地访问它们。

所以,我的问题是:是否有一种方便/惯用的方法从Test :: Unit :: Assertions访问assert *方法而不会有太多麻烦?解决方案必须与Shoulda一起使用,尽管它不一定需要依赖依赖在Shoulda上;直接的Ruby方式会很好。

2 个答案:

答案 0 :(得分:1)

这应该按照您的要求运作:

def self.should_have_xpath(path, &block)
  should "have an element matching the path: #{path}" do
    # ...
    block.bind(self).call(match)
  end
end

答案 1 :(得分:0)

我有一个有效的解决方案:

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 }

我并不特别喜欢每次都必须(记得)传递测试实例,这就是为什么我希望Stack Overflow能够提出更好的答案。