Cucumber步骤定义中的实例变量(即什么是self)有什么对象?

时间:2014-08-27 14:39:50

标签: ruby cucumber

我不了解在Ruby中使用Cucumber时的范围,特别是关于实例变量。

对于我的直接示例的上下文,在hooks.rb的Before部分中,已分配变量@browser

@browser = Watir::Browser.new @browser_selected.to_sym

(其中@browser_selected通常是'chrome')

在步骤定义中使用@browser。举个简单的例子:@browser.send_keys(:tab)

我不明白的是什么对象包含@browser作为属性。它在这方面有什么意义?我知道我困惑的代码总是在一个块中,并且我认识到每个这样的块被使用(通过它附加的Given / When / Then消息)以某种神秘的方式进行预处理。

在这个神秘的笼罩中,是实例变量的范围。我如何知道这些块中实例变量的范围?

1 个答案:

答案 0 :(得分:5)

Cucumber中的

self步骤和钩子只是一个Ruby对象," world",在每个场景中都使用它。每个步骤定义中的块在具有the_world.instance_eval或类似内容的世界的上下文中执行,这意味着当每个块运行时self是世界。因此,所有这些实例变量所属的对象是同一个对象,即世界。所有这些实例变量的范围都是整个场景。

因此,在Cucumber步骤中谨慎使用实例变量非常重要,并在步骤名称中明确表示您正在使用它们(也就是说,在步骤名称中明确指出它们是指某些一块国家)。这些步骤清楚地指的是在幕后保存的东西(即引用相同的实例变量):

Given there is a thing
When I frob the thing
Then the thing should be frobbed

这很好,很正常。但是如果When I frob the thing预先计算了一些预期的断言结果并将它们隐藏在实例变量中,那将是非常糟糕的,并且Then the thing should be frobbed在其断言中使用了这些实例变量。除非Then the thing should be frobbed位于When I frob the thing之前,否则Object将不起作用,使其不再可重复使用,并且对于其他人写作功能而言,这种限制并不明显,他们会感到沮丧。 (不要跟我以前的同事一样。)

回到世界:Cucumber为每个场景创造了一个新的世界,并在最后将其抛弃,因此场景的实例变量不会影响下一个场景。在普通的Cucumber中,世界只是Cucumber::Rails::World的一个实例。在cucumber-rails中,它是the_world.extend SomeModulewhich is interesting to read)的一个实例。除了在cucumber-rails中为世界构建的方法之外,世界通过扩展模块来获得其方法(如{{1}}中所述)。与实例变量一样,世界扩展的所有模块中的所有方法都被卡在同一个对象(世界)上,因此您有时需要担心名称冲突。