Class: ActionController::IntegrationTest

Inherits:
Test::Unit::TestCase show all
Defined in:
lib/action_controller/integration.rb

Overview

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 
    # 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

Constant Summary

Constants included from Assertions

Assertions::NO_STRIP

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TestProcess

#assigns, #build_request_uri, #cookies, #find_all_tag, #find_tag, #fixture_file_upload, #flash, #follow_redirect, #html_document, included, #process, #redirect_to_url, #session, #with_routing, #xml_http_request

Methods included from Assertions

#clean_backtrace, included

Constructor Details

#initialize(name) ⇒ IntegrationTest

Work around a bug in test/unit caused by the default test being named as a symbol (:default_test), which causes regex test filters (like “ruby test.rb -n /foo/”) to fail because =~ doesn’t work on symbols.



443
444
445
# File 'lib/action_controller/integration.rb', line 443

def initialize(name) #:nodoc:
  super(name.to_s)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

Delegate unhandled messages to the current session instance.



545
546
547
548
549
550
# File 'lib/action_controller/integration.rb', line 545

def method_missing(sym, *args, &block)
  reset! unless @integration_session
  returning @integration_session.send(sym, *args, &block) do
    copy_session_variables!
  end
end

Class Method Details

.use_instantiated_fixturesObject

:nodoc:



480
481
482
483
484
# File 'lib/action_controller/integration.rb', line 480

def use_instantiated_fixtures #:nodoc:
  @_use_instantiated_fixtures ?
    @use_instantiated_fixtures :
    superclass.use_instantiated_fixtures
end

.use_instantiated_fixtures=(flag) ⇒ Object

:nodoc:



469
470
471
472
# File 'lib/action_controller/integration.rb', line 469

def use_instantiated_fixtures=(flag) #:nodoc:
  @_use_instantiated_fixtures = true
  @use_instantiated_fixtures = flag
end

.use_transactional_fixturesObject

:nodoc:



474
475
476
477
478
# File 'lib/action_controller/integration.rb', line 474

def use_transactional_fixtures #:nodoc:
  @_use_transactional_fixtures ?
    @use_transactional_fixtures :
    superclass.use_transactional_fixtures
end

.use_transactional_fixtures=(flag) ⇒ Object

:nodoc:



464
465
466
467
# File 'lib/action_controller/integration.rb', line 464

def use_transactional_fixtures=(flag) #:nodoc:
  @_use_transactional_fixtures = true
  @use_transactional_fixtures = flag
end

Instance Method Details

#copy_session_variables!Object

Copy the instance variables from the current session instance into the test instance.



537
538
539
540
541
542
# File 'lib/action_controller/integration.rb', line 537

def copy_session_variables! #:nodoc:
  return unless @integration_session
  %w(controller response request).each do |var|
    instance_variable_set("@#{var}", @integration_session.send(var))
  end
end

#open_session {|session| ... } ⇒ Object

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.

Yields:



514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
# File 'lib/action_controller/integration.rb', line 514

def open_session
  session = Integration::Session.new

  # delegate the fixture accessors back to the test instance
  extras = Module.new { attr_accessor :delegate, :test_result }
  self.class.fixture_table_names.each do |table_name|
    name = table_name.tr(".", "_")
    next unless respond_to?(name)
    extras.send(:define_method, name) { |*args| delegate.send(name, *args) }
  end

  # delegate add_assertion to the test case
  extras.send(:define_method, :add_assertion) { test_result.add_assertion }
  session.extend(extras)
  session.delegate = self
  session.test_result = @_result

  yield session if block_given?
  session
end

#reset!Object

Reset the current session. This is useful for testing multiple sessions in a single test case.



489
490
491
# File 'lib/action_controller/integration.rb', line 489

def reset!
  @integration_session = open_session
end

#run(*args) ⇒ Object

Work around test/unit’s requirement that every subclass of TestCase have at least one test method. Note that this implementation extends to all subclasses, as well, so subclasses of IntegrationTest may also exist without any test methods.



451
452
453
454
# File 'lib/action_controller/integration.rb', line 451

def run(*args) #:nodoc:
  return if @method_name == "default_test"
  super   
end