在验收测试中嘲弄昂贵的资源(rspec,黄瓜)

时间:2011-12-13 06:26:16

标签: ruby-on-rails ruby rspec cucumber acceptance-testing

我有点陷入困境,关于如何编写完整的堆栈验收测试,涉及较低级别与我试图避免的昂贵网络呼叫的接口。

我正在使用rspec和黄瓜,并使用rspeck模拟进行大部分模拟。

以下是我正在做的一个人为的例子来说明我正在测试的内容。

您有一个用于添加成分的页面,您可以使用该页面随后构建食谱和什么不是。在成功创建新成分后,成分模型命中网络服务以获取关于给定食物项目的usda营养信息并将其存储在成分模型中。

我编写了一个WebServiceInterface类,负责获取食品的名称,通过webservice发出适当的请求并返回xml响应。然后,另一个辅助类解析xml响应,然后返回营养信息的集合,然后在成分实例中使用。

现在,我已经编写了一套超出WebServiceInterface的单元测试。它看起来像这样


fake-webservice = double('WebserviceInterface')
fake-webservice.should_receive(:get_response_xml).with(ingredient).and_return(fake_xml_response)

result = ResponseParser.new(fake-webservice).get_ingredient_nutritional_info
result.calories.should eql(123)
result.saturated_fat.should eql(10)

请注意,响应解析器会在内部调用get_response_xml。在这种情况下,ResponseParser会在注入的get_response_xml上调用fake-webservice

对于模型而言,它只是精细和花花公子,但在验收测试中情况更复杂。我想为测试“创建新成分”页面(new_ingredient_path)和成分索引路径之间的集成的页面编写验收测试,该路径列出了所有成分及其营养信息(ingredients_path)。

验收测试看起来像这样:

visit new_ingredient_path
fill_in 'ingredient_name' :with => 'pickled herring'
click_button 'Create ingredient'
visit ingredients_path
page.should have_content 'Pickled Herring 123 calories 10g saturated fat'

除了详细的上下文之外,这是一个问题:在确保在流程中不调用实际Web服务的同时,编写此类验收测试的最佳方法是什么。

每个请求的服务费用我测试了很多,因此“你应该真正测试集成/验收测试中的所有交互”在这种情况下对我来说是不够的。

我需要找到一种方法来确保在测试环境中使用虚假的web服务或类似的东西而不是实际的web服务(甚至可能是开发?)。来自.Net背景,我习惯听到的典型答案是“使用依赖注入!!?!!”。虽然我认为DI有它的优点(请不要把它变成DI辩论),但我认为这里有一个更简单的轻量级解决方案。

我做了If ENV["RAILS_ENV"] == 'test'这样的事情,然后使用假的,否则使用真实的。这是铁轨环境中常用的习惯用法还是太俗气了?

有没有办法将此注册为某种类型的提供程序,可以配置为'spec_helper.rb'块或黄瓜功能/支持/ env.rb块?

思想,想法,意见,建议????任何体验Rails开发者都可以。和/或Cucumber / Rspec大师告诉我完成这种测试的常用方法是什么?

1 个答案:

答案 0 :(得分:6)

通过像Cucumber这样的验收测试,我宁愿实际运用系统的所有部分。是否有针对Web服务的测试服务器?大多数优秀的网络服务应该有一个。

否则,您可以使用webmock来删除Web服务而无需修改代码 - 因为您似乎知道Web服务的输入和输出

http://rubygems.org/gems/webmock

使用webmock的VCR gem也可以用来“记录”并保存HTTP响应,这样你只需要点击一次web服务

https://www.relishapp.com/myronmarston/vcr