RSPEC 让备用作用域
Posted
技术标签:
【中文标题】RSPEC 让备用作用域【英文标题】:RSPEC Let Alternate Scoping 【发布时间】:2014-02-02 20:19:03 【问题描述】:let 的正常行为本质上是绑定到示例块(即 it 块)。这在大多数情况下都很好,但如果您碰巧在 let 中创建用于多个的大型对象,则可能会出现严重问题例子。在这种情况下,实例变量几乎成为测试套件健全性的必需品。
时间会这样复合:
let = # 调用的示例 * 对象创建时间 实例 = 对象创建时间在调用的示例数量超过 3 个的情况下,这个时间很快就会成为问题。
大多数人会说使用实例变量是异端,但在 let 的当前状态下,它似乎是过于教条的胡言乱语,相反没有太多的研究。在我读过的所有支持 let 的文章中,唯一的论点是对延迟加载和作用域问题的一些吸引力,这两者在编写良好的测试中都无关紧要。
延迟加载在测试中似乎没有意义,因为它仅在您不确定是否需要数据时才有用。如果是这种情况,您为什么还要费心为该测试首先构建数据?
如果你没有在你的测试中改变你的对象(提示:你永远不应该,存根它),那么实例变量可能永远不会成为问题。如果是,则耦合不是变量的错,而是测试本身的错。
TL;DR: 有没有一种已知的方法可以将 let 类型语句绑定到备用块区域?理想情况下,我想将它绑定到描述块和上下文块以缓解这个问题。
例子:
describe 'Person' do
local_bind let(:person) Person.new(actual_data)
context 'It has no data' do
local_bind let(:person) Person.new(blank_data)
# tests
end
end
local_bind 将 let 绑定到当前块上下文而不是它运行的示例。当然这是推测的语法,但在这里给出了一般的想法。
这将允许我们声明一个要在块区域内的所有示例中使用的对象,这将大大减少让我们仅示例记忆的不良影响。
虽然这些问题不会在基本对象上明显表现出来(50 次调用 * 0.001 次实例化仍然相当快),但它会在更昂贵的对象上变得明显可见(50 次调用 * 0.1 = 5 秒。)
我以前见过一些需要这么长时间的工具,当它们以某种方式进入规范助手并在糟糕的性能抽象上到处使用时,您可以想象一个包含 3,500 个测试的测试套件如何快速适应它膝盖。到目前为止观察到的差异是 JSON 问题从 8:15 到 1:57 的时间下降了 75%,当我这样做时让修复我估计下降到不到 20 秒。正在努力获取这方面的证据。
【问题讨论】:
您能提供一个代码示例,说明您最想做的事情吗? 您能否澄清一下您如何看待实例变量来避免对象创建时间?你是说使用before(:all)
吗?
在这种情况下,是的。之前 :all 将是最有可能的候选人。我不喜欢其中的含义和拆解,但在现阶段它似乎是最可行的。如上所述,let 语句只会缓存单个示例,这意味着它会为调用它的每个示例重新加载全部数据。如果您不对测试变量进行变异,则实例变量对于广泛使用的变量来说要便宜得多.
编辑主帖以反映我的想法。
【参考方案1】:
https://github.com/rspec/rspec-core/issues/1246
我已经与 RSPEC Core 团队讨论过这个确切的问题,他们无意清除这个不幸的命名约定。相反,他们似乎坚持认为程序员不知道更好,必须握住他们的手,然后再拿起。一件作品,那么多......
【讨论】:
以上是关于RSPEC 让备用作用域的主要内容,如果未能解决你的问题,请参考以下文章