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 让备用作用域的主要内容,如果未能解决你的问题,请参考以下文章

DHCP如何添加备用DNS

我们可以配置MATLAB让变量的局部作用域最小吗?

九作用域

前端:如何理解 JS 的作用域和作用域链?说说闭包的两个应用场景

函数执行的作用域问题

Kotlin作用域函数的使用经验