Everyone should read and understand A Guide to testing Rails it is an invaluable resource for understanding how to write tests for your Rails application.
This article in not intended as a complete introduction to functional testing in Rails, read the Guide for that.
The objective of this howto is to write a functional test to verify that a user creation form and action actually creates a user.
Given an input form like:
(Omitting the form tag and submit button for clarity)
<%= error_messages_for 'user' %>
<%= text_field ‘user’, ‘user_name’ %>
<%= text_field ‘user’, ‘last_name’ %>
<%= text_field ‘user’, ‘first_name’ %>
<%= text_field ‘user’, ‘email_address’ %>
<%= password_field ‘user’, ‘password’ %>
<%= password_field ‘user’, ‘password_confirmation’ %>
The functional test code starts with the regular suspects (this is the code that was generated when the controller was made):
require File.dirname(__FILE__) + '/../test_helper'
require 'user_controller'
require 'user' # Active records to support creation test
# Re-raise errors caught by the controller.
class UserController; def rescue_action(e) raise e end; end
class UserControllerTest < Test::Unit::TestCase
def setup
@controller = UserController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
Nothing fancy there. The meat of the issue is the actual test method:
def test_create
post(:create, {
:user => {
'user_name' => 'testuser1',
'last_name' => 'User',
'first_name' => 'First',
'email_address' => 'testuser1\@test.com',
'password' => 'b00bies',
'password_confirmation' => 'b00bies'
} } )
assert_response( :redirect )
assert_redirected_to( :action => 'view' )
assert User.find_by_user_name('testuser1');
end
@params to an actionNote that the user hash must be explicitly constructed as part of the post operation in the test.
In order to run the :create action, we need to provide test values for @params (the values that would in real life come from the form). The test methods make this an easy job: the second paramater given is assumed to be a hash of @param values:
get some_action, params_values, session_values
So, for example, if we wanted to process the :show method and pass in a @param value of “5” for “id”, we would do it like so:
get :show, {’id’ => 5}
:create, the process is the same, the only difference is that the hash has more values, and that the forms produced by FormHelper pass values within a hash named after the object parameter. Within rails, this nesting happens automagically; in the functional test it’s the testers responsibility to build the nested hash.
There are two key tests involved in this case. 1) Test that after running the create action, the user should be redirected(in this case to the view action) and 2) Test that a new User record has been created that matches the given details.
The assertions involved for this part are:
assert_response( :redirect )
assert_redirected_to( :action => 'view' )
One must also be careful to realize that a redirect response is not a success response. I stumbled over that for a few hours.
Simple enough. Assert that finding the user doesn’t return nil:
assert User.find_by_user_name('testuser1');
Note: that this test could be improved. As written this test could show false positives (where the create method failed to actually make a new user, but our test incorrectly thinks it has). This could happen if there was already a user with the username “testuser1”. One way around this pitfall would be to assert that no such user exists before the method is called. Another would by including a fixture which does not include the user in question.
category:Howto
Everyone should read and understand A Guide to testing Rails it is an invaluable resource for understanding how to write tests for your Rails application.
This article in not intended as a complete introduction to functional testing in Rails, read the Guide for that.
The objective of this howto is to write a functional test to verify that a user creation form and action actually creates a user.
Given an input form like:
(Omitting the form tag and submit button for clarity)
<%= error_messages_for 'user' %>
<%= text_field ‘user’, ‘user_name’ %>
<%= text_field ‘user’, ‘last_name’ %>
<%= text_field ‘user’, ‘first_name’ %>
<%= text_field ‘user’, ‘email_address’ %>
<%= password_field ‘user’, ‘password’ %>
<%= password_field ‘user’, ‘password_confirmation’ %>
The functional test code starts with the regular suspects (this is the code that was generated when the controller was made):
require File.dirname(__FILE__) + '/../test_helper'
require 'user_controller'
require 'user' # Active records to support creation test
# Re-raise errors caught by the controller.
class UserController; def rescue_action(e) raise e end; end
class UserControllerTest < Test::Unit::TestCase
def setup
@controller = UserController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
Nothing fancy there. The meat of the issue is the actual test method:
def test_create
post(:create, {
:user => {
'user_name' => 'testuser1',
'last_name' => 'User',
'first_name' => 'First',
'email_address' => 'testuser1\@test.com',
'password' => 'b00bies',
'password_confirmation' => 'b00bies'
} } )
assert_response( :redirect )
assert_redirected_to( :action => 'view' )
assert User.find_by_user_name('testuser1');
end
@params to an actionNote that the user hash must be explicitly constructed as part of the post operation in the test.
In order to run the :create action, we need to provide test values for @params (the values that would in real life come from the form). The test methods make this an easy job: the second paramater given is assumed to be a hash of @param values:
get some_action, params_values, session_values
So, for example, if we wanted to process the :show method and pass in a @param value of “5” for “id”, we would do it like so:
get :show, {’id’ => 5}
:create, the process is the same, the only difference is that the hash has more values, and that the forms produced by FormHelper pass values within a hash named after the object parameter. Within rails, this nesting happens automagically; in the functional test it’s the testers responsibility to build the nested hash.
There are two key tests involved in this case. 1) Test that after running the create action, the user should be redirected(in this case to the view action) and 2) Test that a new User record has been created that matches the given details.
The assertions involved for this part are:
assert_response( :redirect )
assert_redirected_to( :action => 'view' )
One must also be careful to realize that a redirect response is not a success response. I stumbled over that for a few hours.
Simple enough. Assert that finding the user doesn’t return nil:
assert User.find_by_user_name('testuser1');
Note: that this test could be improved. As written this test could show false positives (where the create method failed to actually make a new user, but our test incorrectly thinks it has). This could happen if there was already a user with the username “testuser1”. One way around this pitfall would be to assert that no such user exists before the method is called. Another would by including a fixture which does not include the user in question.
category:Howto