require 'test/unit' require 'rubygems' require 'rubygems/version' require 'test_help' # hopefully temporary, required for Test::Rails to work # until we get rid of test_help so Test::Unit::TestCase # is kept virgin. require 'rails/version' unless defined? Rails::VERSION $TESTING = true ## # = Introduction # # Test::Rails helps you build industrial-strength Rails code by: # * testing views separate from controllers # * enhancing the assertion vocabulary, and # * auditing your tests for consistency. # # = Details # # Test::Rails: # * splits Functional test into Controller and View tests. # * Splits view assertions away from controller assertions. # * Helps decouple views from controllers. # * Allows you to test AJAX actions in isolation. # * Allows you to test a single partial. # * Clearer failures when assert_tag fails. # * An auditing script analyzes missing assertions in your controllers and # views. # * Library of assertions for testing views. # # = How to Convert to Test::Rails # # You will need to make three small changes to test/test_helper.rb to set up # Test::Rails: # # First, add the following to 'test/test_helper.rb' before you require # +test_help+: # # require 'test/rails' # # Next, change the class from "Unit" to "Rails" right after you # require +test_help+. # # Your 'test/test_helper.rb' will end up looking like this: # # ENV["RAILS_ENV"] = "test" # require File.expand_path(File.dirname(__FILE__) + "/../config/environment") # require 'test/rails' # require 'test_help' # # class Test::Rails::TestCase # ... # # Finally, you need to add the extra rake tasks Test::Rails provides. # Add the following line to your Rakefile after you require # 'tasks/rails': # # require 'test/rails/rake_tasks' # # *NOTE*: # # * get/post/etc. no longer have a session or flash argument. Use the session # and flash accessor instead. # * assert_tag will (eventually) not work in controller tests. # # == Writing View Tests # # View tests live in test/views. They are named after the controller that is # being tested. For exampe, RouteViewTest will live in the file # test/views/route_view_test.rb. # # === Example View Test Case # # require 'test/test_helper' # # # We are testing RouteController's views # class RouteViewTest < Test::Rails::ViewTestCase # # fixtures :users, :routes, :points, :photos # # # testing the view for the delete action of RouteController # def test_delete # # Instance variables necessary for this view # assigns[:loggedin_user] = users(:herbert) # assigns[:route] = routes(:work) # # # render this view # render # # # assert everything is as it should be # assert_links_to "/route/flickr_refresh/#{routes(:work).id}" # # form_url = '/route/destroy' # assert_post_form form_url # assert_input form_url, :hidden, :id # assert_submit form_url, 'Delete!' # assert_links_to "/route/show/#{routes(:work).id}", 'No, I do not!' # end # # # ... # # end # # All view tests are a subclass of Test::Rails::ViewTestCase. The name of the # subclass must match the controller this view depends upon. ViewTestCase # takes care of all the setup necessary for running the tests. # # The +test_delete+ method is named after the delete method in # RouteController. The ViewTestCase#render method looks at the name of the # test and tries to figure out which view file to use, so naming tests after # actions will save you headaches and typing. # # Use +assigns+ to set up the variables the view will use when it renders. # # The call to render is the equivalent to a functional tests' get/post # methods. It makes several assumptions, so be sure to read # ViewTestCase#render carefully. # # ViewTestCase has a vastly expanded assertion library to help you out with # testing. See ViewTestCase for all the helpful assertions you can use in # your view tests. # # == Writing Controller Tests # # Controller tests are essentially functional tests without the view assertions. # # They live in test/controllers, subclass ControllerTestCase, and are # named after the controller they are testing. For example, # RouteControllerTest will live in the file # test/controllers/route_controller_test.rb. # # === Example Controller Test Case # # require 'test/test_helper' # # # We are testing RouteController's actions # class RouteControllerTest < Test::Rails::ControllerTestCase # # fixtures :users, :routes, :points, :photos # # # Testing the delete method # def test_delete # # A session accessor is provided instead of passing a hash to get. # session[:username] = users(:herbert).username # # get :delete, :id => routes(:work).id # # # assert we got a 200 # assert_success # # # assert that instance variables are correctly assigned # assert_assigned :action_title, "Deleting \"#{routes(:work).name}\"" # assert_assigned :route, routes(:work) # end # # # ... # # end # # == Writing Abstract Test Cases # # Abstract test cases are a great way to refactor your tests and # ensure you do not violate the DRY principal and share code between # different test classes. If you have common setup code for your test # classes you can create your own subclass of ControllerTestCase or # ViewTestCase. # # === Example Abstract Test Case # # class RobotControllerTestCase < Test::Rails::ControllerTestCase # # fixtures :markets, :people # # def setup # super # # # We're running tests in this class so we don't need to do any more # # setup # return if self.class == RobotControllerTestCase # # # Set our current host # @host = 'www.test.robotcoop.com' # util_set_host @host # end # # ## # # Sets the hostname to +host+ for this request. # # def util_set_host(hoston) # @request.host = host # end # # end # # = How to Audit Your Tests # # bin/rails_test_audit ensures that your view tests' # +assign+s are compared against your controller tests' # assert_assigned, warning you when you've forgotten to test # something. # # Given: # # class RouteControllerTest < Test::Rails::ControllerTestCase # def test_flickr_refresh # get :flickr_refresh, :id => routes(:work).id # assert_success # # assert_assigned :tz_name, 'Pacific Time (US & Canada)' # end # end # # And: # # class RouteViewTest < Test::Rails::ViewTestCase # def test_flickr_refresh # assigns[:route] = routes(:work) # assigns[:tz_name] = 'Pacific Time (US & Canada)' # # render # # # ... # end # end # # +rails_test_audit+ will see that you don't have an +assert_assigned+ # for +route+ and will output: # # require 'test/test_helper' # # class RouteControllerTest < Test::Rails::ControllerTestCase # # def test_flickr_refresh # assert_assigned :route, routes(:work) # end # # end # # = How 'rake test' Changed # # test:views and test:controllers targets get added so you can run just the # view or controller tests. # # The "test" target runs tests in the following order: units, controllers, # views, functionals, integration. # # The test target no longer runs all tests, it stops on the first # failure. This way a failure in a unit test doesn't fill your screen # with less important errors because the underlying failure also # affected your controllers and views. # # The stats target is updated to account for controller and view tests. module Test::Rails @rails_version = Gem::Version.new Rails::VERSION::STRING @v1_2 = Gem::Version.new '1.2' ## # The currently loaded rails version. Better than Rails::VERSION::STRING # since this one is comparable. def self.rails_version @rails_version end def self.v1_2 # :nodoc: @v1_2 end end class Object # :nodoc: def self.path2class(klassname) klassname.split('::').inject(Object) { |k,n| k.const_get n } end end require 'active_support' require 'active_support/test_case' require 'active_record/fixtures' require 'test/zentest_assertions' require 'test/rails/test_case' require 'test/rails/functional_test_case' require 'test/rails/controller_test_case' require 'test/rails/helper_test_case' require 'test/rails/ivar_proxy' require 'test/rails/view_test_case' ## # Use sensible defaults. class ActiveSupport::TestCase # :nodoc: self.use_transactional_fixtures = true self.use_instantiated_fixtures = false end