How to write integration test for complicated rails index (best practices)

僤鯓⒐⒋嵵緔 提交于 2020-01-05 10:14:28

问题


Let's say I have a page which lists articles. The code in the controller used to be

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

and my test was like

# 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

Ok fine. Now my code changes a bunch. The index is like

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

Or something. So what should my request spec now look like? I don't want to just copy and paste the application code into the test, but at the same time, the conditions and ordering are now fairly complex, so testing the existence and order of all the expected elements will definitely fail unless I emulate the index controller.

What's the best way to do this, avoid testing so specifically, copy in the application code? Refactor the query to some central place like a model and re-use it in the tests?


回答1:


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

The way we test this is not by writing Article.paginate(page: params[:page], per_page: 10, order: :title) again in the spec. The spec must test the result of your program code, not copying over your program code itself!

Long story short - you must just call articles#index controller, and afterwards just check the @articles variable. i.e.

# 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

This way, you directly test using the @articles variable itself, without having to do a second query (which both consumes unnecessary time, as well as results in copying over code).

If you want to test the actual query itself, then since your query is complicated, you should write a spec like the following:

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]

Edit: Footnote Edit 2: Added extra example for testing the actual query



来源:https://stackoverflow.com/questions/16999087/how-to-write-integration-test-for-complicated-rails-index-best-practices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!