gpt4 book ai didi

ruby-on-rails - RSpec 中单个设置的多个断言

转载 作者:数据小太阳 更新时间:2023-10-29 07:07:05 25 4
gpt4 key购买 nike

我想优化一些较慢的规范。此类规范的示例如下所示:

require 'rspec'


class HeavyComputation
def compute_result
sleep 1 # something compute heavy here
"very big string"
end

end



describe HeavyComputation, 'preferred style, but slow' do

subject { described_class.new.compute_result }

it { should include 'big' }
it { should match 'string' }
it { should match /very/ }
# +50 others
end

这是非常可读的,我对它总体上很满意,除了每个额外的规范都会增加至少 1 秒的总运行时间。这是不太可接受的。

(请不要讨论 HeavyComputation 类的优化,因为它超出了这个问题的范围)。

所以我必须求助于这样的规范:

describe HeavyComputation, 'faster, but ugly' do
subject { described_class.new.compute_result }

it 'should have expected result overall' do
should include 'big'
should match 'string'
should match /very/
# +50 others
end
end

这显然在性能方面要好得多,因为运行它的时间几乎总是恒定的。问题是故障很难追踪,而且阅读起来不是很直观。

理想情况下,我希望两者兼而有之。沿着这些线的东西:

describe HeavyComputation, 'what I want ideally' do
with_shared_setup_or_subject_or_something_similar_with do
shared(:result) { described_class.new.compute_result }
subject { result }

it { should include 'big' }
it { should match 'string' }
it { should match /very/ }
# +50 others
end
end

但不幸的是,我什至不知道从哪里开始实现它。它有多个潜在问题(是否应该在共享结果上调用 Hook 就是其中之一)。

我想知道这个问题是否有现成的解决方案。如果不是,最好的解决方法是什么?

最佳答案

您可以使用 before(:context) Hook 来实现此目的:

describe HeavyComputation, 'what I want ideally' do
before(:context) { @result = described_class.new.compute_result }
subject { @result }

it { should include 'big' }
it { should match 'string' }
it { should match /very/ }
# +50 others
end

请注意,before(:context) 有一些注意事项,但是:

警告:before(:context)

使用 before(:context) 来加快速度是非常诱人的,但是我们建议您避免这种情况,因为还有很多陷阱作为根本不起作用的东西。

上下文

before(:context) 在生成的示例中运行以提供组 block 的上下文。

实例变量

before(:context) 中声明的实例变量在所有群里的例子。这意味着每个例子都可以改变共享对象的状态,导致可以使对失败的推理变得困难。

不支持的 rspec 结构

RSpec 有几个结构可以在每个例子之间重置状态自动地。这些不适用于在 before(:context) 中使用:

  • let 声明
  • subject 声明
  • 任何模拟、 stub 或测试双重声明

其他框架

模拟对象框架和数据库事务管理器(如ActiveRecord)通常是围绕设置的想法设计的在一个例子之前,运行那个例子,然后拆除。这意味着模拟和 stub 可以(有时)声明在before(:context),但在第一个真实示例出现之前就被拆除了跑。

可以before(:context)中创建数据库支持的模型对象rspec-rails,但它不会为您包装在事务中,所以您需要自己在 after(:context) block 中进行清理。

(来自 http://rubydoc.info/gems/rspec-core/RSpec/Core/Hooks:before)

只要您了解您的before(:context) Hook 在测试替身和数据库事务等正常的每个示例生命周期之外,并且您自己明确地管理必要的设置和拆卸,你会没事的——但在你的代码库上工作的其他人可能没有意识到这些问题。

关于ruby-on-rails - RSpec 中单个设置的多个断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25634700/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com