Ruby 步骤定义中的实例变量(即什么是self)起作用的对象是什么?

Ruby 步骤定义中的实例变量(即什么是self)起作用的对象是什么?,ruby,cucumber,Ruby,Cucumber,我不理解在Ruby中使用Cucumber时的作用域,特别是在实例变量方面 对于我的直接示例,在hooks.rb的Before部分中,变量@browser被赋值 @browser=Watir::browser.new@browser\u已选定。to\u sym (其中所选的@browser\通常为“chrome”) 在步骤定义中使用@browser。举个简单的例子:@browser.send_键(:tab) 我不明白的是什么对象包含@browser作为属性。在这种情况下,它有什么意义?我知道让我感

我不理解在Ruby中使用Cucumber时的作用域,特别是在实例变量方面

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

@browser=Watir::browser.new@browser\u已选定。to\u sym

(其中所选的
@browser\通常为“chrome”)

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

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


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

self
在Cucumber steps and hooks中,它只是一个Ruby对象,“world”,在每个场景中都会用到。每个步骤定义中的块是在世界的上下文中执行的,其中包含
世界.instance\u eval
或类似的内容,这意味着当每个块运行时
self
就是世界。所有这些实例变量所属的对象都是同一个对象,即世界。所有这些实例变量的范围都是整个场景

因此,在Cumber步骤中尽量少用实例变量,并在步骤名称中明确说明您正在使用它们(也就是说,在步骤名称中明确说明它们引用的是某种状态),这一点很重要。这些步骤显然是指在幕后保存的内容(即,指同一实例变量):

这很正常。但是如果
当我翻动这个东西时
预先计算了一些预期的断言结果并将它们存储在实例变量中,
那么这个东西应该被翻动
在它的断言中使用这些实例变量,那就太糟糕了
那么这个东西应该被翻动
将不起作用,除非当我翻动它之前的东西时,
会降低它的可重用性,而这个限制对于其他编写特性的人来说并不明显,他们会感到沮丧。(不要像我以前的同事那样。)


回到世界:Cucumber为每个场景创建一个新的世界,并在结束时将其丢弃,以便场景的实例变量不会影响下一个场景。在普通黄瓜中,世界只是
对象的一个实例。在cucumber rails中,它是
cucumber::rails::World
()的一个实例。除了cucumber rails中内置的方法外,world还通过扩展模块(如
the_world.extend SomeModule
)获得其方法。与实例变量一样,world扩展的所有模块中的所有方法都被阻塞在同一个对象(world)上,因此您有时需要担心名称冲突。

对于Cucumber的解释。“Before钩子将在每个场景的第一步之前运行。它们将按照注册的相同顺序运行。”我选择的示例恰好在钩子中定义,但没有它也存在相同的问题。如果我在一个步骤定义中分配一个新的实例变量,那么它的实例是什么对象?在我看来,块运行的顺序对涉及哪些对象、它们是如何产生的,或者哪个是实例变量分配的相关实例没有任何影响(除了时间依赖性)。啊,是的,“世界。”其实我以前就知道了,但我已经忘记了。也许现在更容易记住,谢谢。
Given there is a thing
When I frob the thing
Then the thing should be frobbed