跳至內容 跳至搜尋

整合測試跨多個控制器和動作,將它們全部串聯在一起,以確保它們能按預期一起運作。它以比單元測試或功能測試更完整的方式進行測試,執行整體堆疊,從派遣器到資料庫。

以最簡單的方式來說,您只需延伸 IntegrationTest並使用 Integration::RequestHelpers#get 和/或 Integration::RequestHelpers#post 方法撰寫測試

require "test_helper"

class ExampleTest < ActionDispatch::IntegrationTest
  fixtures :people

  def test_login
    # get the login page
    get "/login"
    assert_equal 200, status

    # post the login and follow through to the home page
    post "/login", params: { username: people(:jamis).username,
      password: people(:jamis).password }
    follow_redirect!
    assert_equal 200, status
    assert_equal "/home", path
  end
end

但是,您也可以在每個測試開啟多個工作階段執行個體,甚至延伸這些執行個體包含斷言和方法,以建立針對您的應用程式專屬且非常強大的測試 DSL。您甚至可以參照您碰巧已定義的任何命名路由。

require "test_helper"

class AdvancedTest < ActionDispatch::IntegrationTest
  fixtures :people, :rooms

  def test_login_and_speak
    jamis, david = login(:jamis), login(:david)
    room = rooms(:office)

    jamis.enter(room)
    jamis.speak(room, "anybody home?")

    david.enter(room)
    david.speak(room, "hello!")
  end

  private

    module CustomAssertions
      def enter(room)
        # reference a named route, for maximum internal consistency!
        get(room_url(id: room.id))
        assert(...)
        ...
      end

      def speak(room, message)
        post "/say/#{room.id}", xhr: true, params: { message: message }
        assert(...)
        ...
      end
    end

    def login(who)
      open_session do |sess|
        sess.extend(CustomAssertions)
        who = people(who)
        sess.post "/login", params: { username: who.username,
          password: who.password }
        assert(...)
      end
    end
end

另一個較長的範例可能是

一個執行多個控制器的簡單整合測試

require "test_helper"

class UserFlowsTest < ActionDispatch::IntegrationTest
  test "login and browse site" do
    # login via https
    https!
    get "/login"
    assert_response :success

    post "/login", params: { username: users(:david).username, password: users(:david).password }
    follow_redirect!
    assert_equal '/welcome', path
    assert_equal 'Welcome david!', flash[:notice]

    https!(false)
    get "/articles/all"
    assert_response :success
    assert_select 'h1', 'Articles'
  end
end

如您所見,整合測試涉及多個控制器,而且會執行從資料庫到派遣器的整體堆疊。此外,您可以在一個測試中同時開啟多個工作階段執行個體,並且延伸這些執行個體包含斷言方法,以建立針對您的應用程式專屬且非常強大的測試 DSL(特定領域語言)。

以下是整合測試中多個工作階段執行個體和自訂 DSL 的範例

require "test_helper"

class UserFlowsTest < ActionDispatch::IntegrationTest
  test "login and browse site" do
    # User david logs in
    david = login(:david)
    # User guest logs in
    guest = login(:guest)

    # Both are now available in different sessions
    assert_equal 'Welcome david!', david.flash[:notice]
    assert_equal 'Welcome guest!', guest.flash[:notice]

    # User david can browse site
    david.browses_site
    # User guest can browse site as well
    guest.browses_site

    # Continue with other assertions
  end

  private

    module CustomDsl
      def browses_site
        get "/products/all"
        assert_response :success
        assert_select 'h1', 'Products'
      end
    end

    def login(user)
      open_session do |sess|
        sess.extend(CustomDsl)
        u = users(user)
        sess.https!
        sess.post "/login", params: { username: u.username, password: u.password }
        assert_equal '/welcome', sess.path
        sess.https!(false)
      end
    end
end

請查看 [要求輔助器文件] (ActionDispatch::Integration::RequestHelpers) 中關於如何使用 get 等方法的說明。

變更要求編碼

您也可以透過設定要求應編譯成什麼來輕鬆地測試您的 JSON API

require "test_helper"

class ApiTest < ActionDispatch::IntegrationTest
  test "creates articles" do
    assert_difference -> { Article.count } do
      post articles_path, params: { article: { title: "Ahoy!" } }, as: :json
    end

    assert_response :success
    assert_equal({ id: Article.last.id, title: "Ahoy!" }, response.parsed_body)
  end
end

as 選項傳遞一個「application/json」接受標頭 (從而將要求格式設定為 JSON,除非另有設定優先),將內容類型設定為「application/json」,並將參數編碼為 JSON。

在回應上呼叫 TestResponse#parsed_body 會根據最後回應 MIME 類型解析回應本文。

馬上支援 :json。但對於您已註冊的任何自訂 MIME 類型,您可以透過下列方式新增自訂編碼器

ActionDispatch::IntegrationTest.register_encoder :wibble,
  param_encoder: -> params { params.to_wibble },
  response_parser: -> body { body }

其中 param_encoder 定義如何編碼參數,而 response_parser 定義如何透過 TestResponse#parsed_body 解析回應本文。

請參閱 Rails 測試指南 以取得更多資訊。

命名空間
包含的模組