класс ActionDispatch::IntegrationTest
Интеграционный тест охватывает несколько контроллеров и действий, связывая их все вместе, чтобы гарантировать, что они работают вместе как ожидается. Он тестирует более полно, чем модульные или функциональные тесты, используя весь стек, от диспетчера до базы данных.
В самом простом случае вы просто расширяете IntegrationTest и пишете свои тесты, используя методы get/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
См. документацию по вспомогательным функциям запросов за помощью в использовании 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» Accept (тем самым устанавливая формат запроса в JSON, если он не переопределён), устанавливает тип содержимого в «application/json» и кодирует параметры в JSON.
Вызов parsed_body для ответа анализирует тело ответа на основе последнего MIME типа ответа.
По умолчанию поддерживается только :json. Но для любых пользовательских MIME типов, которые вы зарегистрировали, вы можете добавить свои собственные кодировщики с:
ActionDispatch::IntegrationTest.register_encoder :wibble,
param_encoder: -> params { params.to_wibble },
response_parser: -> body { body }
Где param_encoder определяет, как должны кодироваться параметры, и response_parser определяет, как тело ответа должно быть проанализировано через parsed_body.
См. Руководство по тестированию Rails для получения дополнительной информации.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.