在传递给RSpec共享示例的块的情况下,启用`let`分配形式参数

Pet*_*vin 4 ruby rspec

在RSpec中,为共享示例提供值的技术之一是let用于定义该示例使用的变量,如本文档中所述.

目前,传递给形式参数的值优先于由其建立的任何值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]
Run Code Online (Sandbox Code Playgroud)

我的问题是,改变RSpec语义是否可能/合理/可取,以便let传递块内部设置的变量优先于传递的参数,以及上面的输出[2, 2, 3].这将允许将"简单"值作为参数传递,并通过块设置更复杂的值.

Myr*_*ton 5

用于let定义变量

let没有定义变量; 它定义了一个memoized帮助方法.区别很重要,因为ruby以不同的方式处理变量和方法.具体来说,局部变量(例如x1块中的块arg shared_examples_for)始终优先于同名方法,除非您使用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
Run Code Online (Sandbox Code Playgroud)

在未来的某个时刻,Superclass更新为有一个name方法:

class Superclass
  def name
    "superclass name"
  end
end
Run Code Online (Sandbox Code Playgroud)

如果ruby没有优先考虑局部变量而不是方法,那么该Subclass#do_something方法将被一个无关的变化打破Superclass.局部变量始终优先的事实意味着您可以更容易地推断出代码的作用而不必担心改变某些远程代码突然导致特定标识符重新绑定到方法而不是局部变量.