【问题标题】:How to write integration test for complicated rails index (best practices)如何为复杂的 Rails 索引编写集成测试(最佳实践)
【发布时间】:2013-06-08 11:31:34
【问题描述】:

假设我有一个列出文章的页面。控制器中的代码以前是

# articles#index
@articles = Article.paginate(page: params[:page], per_page: 10, order: :title)

我的测试是这样的

# spec/requests/article_pages_spec
Article.paginate(page: 1, per_page:10, order: :title).each do |a|
  a.should have_selector('h3', text: a.title)
end

好的。现在我的代码改变了一堆。索引就像

@articles = Article.find(:all, conditions: complicated_status_conditions)
  .sort_by { |a| complicated_weighted_rating_stuff }
  .select { |a| complicated_filters }
  .paginate(...)

什么的。那么我的请求规范现在应该是什么样子?我不想只是将应用程序代码复制并粘贴到测试中,但与此同时,条件和排序现在相当复杂,所以测试所有预期元素的存在和顺序肯定会失败,除非我模拟索引控制器。

最好的方法是什么,避免专门测试,复制应用程序代码?将查询重构到某个中心位置(例如模型)并在测试中重用它?

【问题讨论】:

  • 为什么代码变了?有没有新的要求?如果是这样,测试应该反映新的要求。
  • 是的,有几个复杂的排序和过滤要求。例如,按加权评分排序,并在加权评分上添加时间衰减。在测试中试探性地这样做似乎不精确,并且不会产生与实际代码相同的结果,但在测试中复制相同的查询似乎是多余的......

标签: ruby-on-rails testing rspec


【解决方案1】:
# articles#index
@articles = Article.paginate(page: params[:page], per_page: 10, order: :title)

我们测试的方式是不是,在规范中再次写入Article.paginate(page: params[:page], per_page: 10, order: :title)。规范必须测试您的程序代码的结果,而不是复制您的程序代码本身!

长话短说-您必须调用articles#index 控制器,然后检查@articles 变量。即

# We usually call this as a controller spec
# spec/controllers/articles_controller
# But feel free to put it anywhere you want
describe ArticlesController do
  it "should ..." do
    get :index

    # assigns[:articles] will give the @articles variable contents
    assigns[:articles].each do |a|
      response.should have_selector('h3', text: a.title)
    end
  end
end

这样,您可以直接使用@articles 变量本身进行测试,而无需进行第二次查询(这既会消耗不必要的时间,也会导致代码复制)。

如果您想测试实际查询本身,那么由于您的查询很复杂,您应该编写如下规范:

it "should ..." do
  # Create 10 articles in the database
  # out of which only 5 are expected to match the expected output
  article1  = Article.create! ...
  ...
  article10 = Article.create! ...

  get :index

  # Test whether the articles are correctly filtered and ordered
  assigns[:articles].should == [article5, article3, article7, article1, article4]

编辑:脚注 编辑 2:添加了测试实际查询的额外示例

【讨论】:

  • 所以我由此推断您正在测试的事实是该操作从控制器中吐出结果,而不是控制器产生正确的结果?因此,控制器选择正确结果的测试会转移到其他地方吗?
  • 是的@futuresandwich,控制器的输出是不同的规格。使用正确查询选择正确结果的控制器是不同的规范,测试 的最佳方法是首先在数据库中保存 10 篇文章(其中只有 5 篇符合所有条件) ,调用控制器,然后断言 assigns[:articles] 有正确的 5 个文章 ID。
  • 这篇文章的未来读者-你们也可以阅读this article
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多