在RSpec中,为共享示例提供值的一种技术是使用let
来定义该示例使用的变量,如this documentation中所述。
目前,传递给形式参数的值优先于let
建立的任何值,如以下示例所示:
shared_examples_for "foo" do |x1|
specify {puts [x1, x2, x3].inspect}
end
describe "" do
let(:x1) {3}
let(:x2) {3}
let(:x3) {3}
it_behaves_like "foo", 1 do
let(:x1) {2}
let(:x2) {2}
end
end
# => [1, 2, 3]
我的问题是,改变RSpec语义是否可能/合理/可取,以便传递块内的let
设置的变量优先于传递的参数,上面会输出{{ 1}}。这将允许将“简单”值作为参数传递,并通过块设置更复杂的值。
答案 0 :(得分:5)
使用
let
来定义变量
let
没有定义变量;它定义了一个memoized帮助方法。区别很重要,因为ruby以不同的方式处理变量和方法。具体来说,局部变量(例如x1
块中的shared_examples_for
块arg)始终优先于同名方法,除非您使用self.x1
制作它明确表示您正在发送消息。
所以,回答你的问题:不,你问的是不可能的。我认为这也不可取;当有名称冲突时,局部变量总是“赢”对于能够推断你的代码是非常重要的。如果情况并非如此,请考虑重新调查。假设你开始使用这段代码:
# in superclass.rb
class Superclass
end
# in subclass.rb
class Subclass < Superclass
def do_something(name)
# do something with the `name` variable
end
end
在将来的某个时间点,Superclass
会更新为name
方法:
class Superclass
def name
"superclass name"
end
end
如果ruby没有优先考虑方法的局部变量,那么Subclass#do_something
方法会被Superclass
的无关更改打破。局部变量始终优先的事实意味着您可以更容易地推断出代码的作用而不必担心在某些远程代码中进行更改会突然导致特定标识符重新绑定到方法而不是局部变量。
答案 1 :(得分:0)
如果我只想用新的context
更改上下文,我会使用let
s。
您可以在context
块内部或外部使用describe
块。基本相同,但为您创建一种方式以不同的方式组织您的规范(IMO更好)
describe "adding a credit card" do
let(:card_number) { "123456789012" }
it "accepts cards" do
pending
# do something with card_number
end
context "failure" do
let(:card_number) { "BLUEBEARD666" }
it "doesn't handle weird formats" do
# oh yeah!
end
end
end
在这种情况下,您拥有嵌入式let
,但它在语义上更有意义。
我希望这不会完全忽略这一点:P