An IntegrationTest is one that spans multiple controllers and actions, tying them all together to ensure they work together as expected. It tests more completely than either unit or functional tests do, exercising the entire stack, from the dispatcher to the database.
At its simplest, you simply extend IntegrationTest and write your tests using the get/post methods:
require "#{File.dirname(__FILE__)}/test_helper" class ExampleTest < ActionController::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", :username => people(:jamis).username, :password => people(:jamis).password follow_redirect! assert_equal 200, status assert_equal "/home", path end end
However, you can also have multiple session instances open per test, and even extend those instances with assertions and methods to create a very powerful testing DSL that is specific for your application. You can even reference any named routes you happen to have defined!
require "#{File.dirname(__FILE__)}/test_helper" class AdvancedTest < ActionController::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) xml_http_request "/say/#{room.id}", :message => message assert(...) ... end end def login(who) open_session do |sess| sess.extend(CustomAssertions) who = people(who) sess.post "/login", :username => who.username, :password => who.password assert(...) end end end
Delegate unhandled messages to the current session instance.
[ show source ]
# File vendor/rails/actionpack/lib/action_controller/integration.rb, line 521 521: def method_missing(sym, *args, &block) 522: reset! unless @integration_session 523: returning @integration_session.send(sym, *args, &block) do 524: copy_session_variables! 525: end 526: end
Open a new session instance. If a block is given, the new session is yielded to the block before being returned.
session = open_session do |sess| sess.extend(CustomAssertions) end
By default, a single session is automatically created for you, but you can use this method to open multiple sessions that ought to be tested simultaneously.
[ show source ]
# File vendor/rails/actionpack/lib/action_controller/integration.rb, line 490 490: def open_session 491: session = Integration::Session.new 492: 493: # delegate the fixture accessors back to the test instance 494: extras = Module.new { attr_accessor :delegate, :test_result } 495: self.class.fixture_table_names.each do |table_name| 496: name = table_name.tr(".", "_") 497: next unless respond_to?(name) 498: extras.send(:define_method, name) { |*args| delegate.send(name, *args) } 499: end 500: 501: # delegate add_assertion to the test case 502: extras.send(:define_method, :add_assertion) { test_result.add_assertion } 503: session.extend(extras) 504: session.delegate = self 505: session.test_result = @_result 506: 507: yield session if block_given? 508: session 509: end
Reset the current session. This is useful for testing multiple sessions in a single test case.
[ show source ]
# File vendor/rails/actionpack/lib/action_controller/integration.rb, line 467 467: def reset! 468: @integration_session = open_session 469: end