iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
自我挑戰組

Rails測試寫起乃!!!系列 第 14

Day14 測試寫起乃-request vs controller test

我們公司的專案在 rails4 所以一般我都還是在寫 controller test
一直到某天看到有 request test 才開始好奇到底跟 controller test 差別在哪?

Request test VS Controller test

我們先來看如果是 簡單的 Controller test 與 Request test 寫法差異

# controller test

require 'rails_helper'

RSpec.describe CollectionsController, type: :controller do
  describe 'Get #index' do
    it 'when resource is found' do
      get :index
      collection = create(:collection)
      expect(response.status).to eq 200
      expect(assigns(:collection)).to eq([collection])
    end
  end

  describe 'Post #create' do
    it 'redirect to index when create collection success' do
      post :create, params: { collection: { title: '11', description: '222' } }
      expect(response).to redirect_to(collections_path)
      expect(Collection.count).to eq 1
    end
  end

  describe 'Get #show' do
    let(:collection) { create(:collection) }
    it 'redirect to index when create collection success' do
      get :show, params: { id: collection }
      expect(response).to have_http_status(200)
      expect(response).to render_template(:show)
    end
  end
end
# request test
require 'rails_helper'

RSpec.describe CollectionsController, type: :request do
  describe 'Get #index' do
    it 'when resource is found' do
      get '/collections'
      expect(response).to have_http_status(200)
      expect(response).to render_template(:index)
    end
  end

  describe 'Post #create' do
    it 'redirect to index when create collection success' do
      post '/collections', params: { collection: { title: '11', description: '222' } }
      expect(response).to redirect_to(collections_path)
      expect(Collection.count).to eq 1
    end
  end

  describe 'Get #show' do
    let(:collection) { create(:collection) }
    it 'redirect to index when create collection success' do
      get "/collections/#{collection.id}"
      expect(response).to have_http_status(200)
      expect(response).to render_template(:show)
    end
  end
end

如果遇到 host 問題 可以看這篇

其實很像只是在於 http 動詞後方路徑的寫法不同而已

額外補充

在 Rails3.5 時釋放可以開始使用 Controller spec

但是到了 Rails 5 DHH 開始移除了 assignsassert_templete

Testing what instance variables are set by your controller is a bad idea. That's grossly overstepping the boundaries of what the test should know about. You can test what cookies are set, what HTTP code is returned, how the view looks, or what mutations happened to the DB, but testing the innards of the controller is just not a good idea.

The same goes for assert_template. This ties the test to the internal structure of how your views are organized. That's not what the test should be testing. It should be testing what DOM elements it expect to be there. Rearranging your templates and partials should not cause these tests to break. Deprecate and recommend using assert_select instead.

這邊也說到他已經移除了ActionController::TestCase

With the speed increase we achieved for ActionDispatch::IntegrationTest in Rails 5, there's no longer a need to also have ActionController::TestCase around. We're changing the scaffolds in #22076 but we should also get the message out that ActionController::TestCase is deprecated and will be made into a gem from Rails 5.1.

個人理解是鼓勵工程師將 Controller 測試改成 Request 測試
所以他才在 Rails5 的時候提升 request spec 的速度

所以你問我到底該選哪個?

==Rails3.5~4 => controller spec==
==Rails5 up => request spec==

因為在 rails5 之前 request 速度確實比 controller 還要慢
在我們自己的專案上 blog test

controller spec

request spec

但我在 rails6 自己的專案上確實 request test 速度有變快! 但其實我自己覺得速度差不多XDD 不過官方都鼓勵說要開始轉寫 request 了就照著官方的來吧!

參考來源有以下:
Deprecate assigns() and assert_template in controller testing
Deprecate ActionController::TestCase in favor of ActionDispatch::IntegrationTest
rspec relish-request spec
各個spec該如何設定host
Testing with RSpec - Request Spec
Controller Specs vs Request Specs?


上一篇
Day13 測試寫起乃 - controller test
下一篇
Day15 測試寫起乃 - Devise login user
系列文
Rails測試寫起乃!!!30

尚未有邦友留言

立即登入留言