说我有以下测试
describe "bob" do
subject {
response = get "/expensive_lookup"
JSON.parse(response.body)
}
its(["transaction_id"]) { should == 1 }
its(["order_id"]) { should == 33 }
end
然后对于每个its() {}
,主题将被重新评估,在我的情况下,这是一个非常慢的查找。
我可以将所有测试捆绑在一起,例如
describe "bob" do
subject(res) {
response = get "/expensive_lookup"
JSON.parse(response.body)
}
it "returns the right stuff" do
res["transaction_id"]).should == 1
res["order_id"].should == 33
end
end
但是,如果发生故障,这会使测试的哪一行失败变得不那么明显。
有没有办法可以阻止每个it
块重新评估主题?
答案 0 :(得分:3)
您可以将其放入before(:all)
块。我不知道新的rspec版本中的语法是否已经改变,但无论如何,你的测试都会变成这样:
before(:all) do
response = get "/expensive_lookup"
@res = JSON.parse(response.body)
end
it "returns the right transaction ID" do
@res["transaction_id"].should == 1
end
# etc
专家认为,前所有块中的代码只为您的规范运行一次。可以看出,正如你所看到的,你无法利用这个主题;你需要更明确地写出每一个。另一个问题是,保存到测试数据库的任何数据都不是事务的一部分,也不会回滚。
答案 1 :(得分:1)
有两个可能的问题来源
您应该真正嘲笑所有网络请求,无论是否缓慢。
宝石VCR
非常棒。只需运行一次请求并保留结果以进行后续测试,就变得微不足道了。
如果您有多个it
区块,则主题将每次都重建。有一种避免这种情况的方法:
let(:expensive) { very_long_computation }
subject { @cache ||= expensive.freeze }
it { is_expected.to have_attributes(foo: 42) }
it { is_expected.to # ... }
这样very_long_computation
仅运行一次,并且在两个it
块中共享。
注意:我在freeze
块中调用subject
是为了避免错误地对其进行修改,但是当然这并不是很深的冻结,因此您仍然需要注意什么你在做。如果您要更改主题,则测试将不再独立,并且不应共享主题。