为什么实例变量有时会在 RSpec 测试中被过度使用?

Why are instance variables sometimes overused in RSpec tests?

我注意到 RSpec 单元测试等中实例变量的使用示例

像这样:

it 'should update something' do
  @user = user(:userone)
  @attr = {
    :name => 'this',
    :phone => 'that'
  }
  put :update, :id => @user.id, :user => @attr

  @user.reload
  expect(response.status).to eq(200)
  expect(@user.name).to eq('this')
  expect(@user.phone).to eq('that')
end

如果不在 before :each 等中设置变量,为什么不直接使用局部变量?

总的来说,测试中的变量(就像任何程序中的变量一样)应该有尽可能小的作用域。这使读者更容易理解测试,因为它最大限度地减少了他们必须考虑的代码量,并且通常可以提高运行时的效率。因此,如果一个实例变量(或者,在当前 RSpec 中,一个 let 变量)可以是本地的(不会重复代码或降低效率)它应该是。

当将数据从 before 块传递到示例(it 块)的最佳可用方式是在实例变量中时,我曾经看到过像您的示例这样的规范时间。有时它们是由没有经验的程序员编写的,他们看到规范中使用了很多实例变量并且不假思索地模仿了它。 (我仍然在 Rails 控制器中看到同样的错误。)有时,它们是由于有人内联了一个 before 块,但没有费心将不再需要作为实例变量的实例变量更改为局部变量。

这几天RSpec提供了letlet 比实例变量更好的原因之一是 let 变量的使用看起来像局部变量,因此如果将局部变量更改为 let 变量,则无需更改它们或相反亦然。然而,我仍然经常看到测试数据的问题,它只在一个示例中使用,而在 let 变量中定义它可以而且应该只是本地的。就像过度使用实例变量一样,这有时是由于缺乏经验的程序员不假思索地模仿示例,有时是由于测试更改后未能清理导致 let 变量变得不必要。