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

kal*_*dic 3 ruby cucumber

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

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

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

(@browser_selected通常是'铬')

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

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

这种神秘的遮蔽是实例变量的范围.如何知道这些块中的实例变量的范围?

Dav*_*uth 5

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

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

Given there is a thing
When I frob the thing
Then the thing should be frobbed
Run Code Online (Sandbox Code Playgroud)

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

回到世界:Cucumber为每个场景创建一个新世界并在最后抛出它,因此场景的实例变量不会影响下一个场景.在普通的黄瓜中,世界只是一个例子Object.在cucumber-rails中,它是一个实例Cucumber::Rails::World(有趣的是阅读).除了在cucumber-rails中建立世界的方法之外,世界通过扩展模块(如the_world.extend SomeModule)来获得它的方法.与实例变量一样,来自世界扩展的所有模块的所有方法都被卡在同一个对象(世界)上,因此您有时需要担心名称冲突.