Testing In Rails: Functional Testing For Controllers
Hi Guys,
In my previous two blogs Testing In Rails: Introduction and Creating Test Data and Testing In Rails: Unit Testing In Models, I talked about the introduction and usage of the test cases in rails and also discussed about how we can create unit test cases for models. In this section we will talk about how and what should be written for the test cases of controllers.
Controllers in rails deals with the request and responses, and the test cases written for a single request or action are known as functional. There are different kinds of request type which are supported with functional test cases are:
- get
- post
- patch
- put
- head
- delete
We can write test cases for actions with any of these types. Next question for us is what should we test while writing a test cases of controller.
a) Whether the action is for authenticated user - authenticity
b) Whether the request is successful
c) whether the redirection is made to a correct action
d) whether correct template is rendered or not
e) whether the correct message displayed in the view or not.
So whenever we write a test case for controllers we need to take these things into mind. test_helper.rb plays an important role while testing the controllers as some of the controller actions requires login so for a particular controller we can store the user in session to make the user logged in, so that we can test the authenticated actions too.
About all the assertions, we talked in the previous blog also supports here. The full list of avaialble assertions can be found in the following links
http://ruby-doc.org/stdlib-2.1.1/libdoc/test/unit/rdoc/Test/Unit/Assertions.html
http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html
Now finally lets create controller and its test cases. Suppose we have a controller named homes_controller.rb and its test case file is homes_controller_test.rb like this
## homes_controller.rb
class HomeController < ApplicationController
def index
@products = Product.all
render "products"
end
end
Thus you can see that here in this controller the index action fetches all the products and renders products.html.erb page. If we want to test this action first we need to hit the action and then check whether the action is gives a success response and it also has a @products instance variable initialized and one more case will be whether it renders the products.html.erb or not. So will write the test case as follows:
require 'test_helper'
class HomeControllerTest < ActionController::TestCase
test "should get products" do
get :index # Hitting a get request to the action
## If you need to send parameters to the index action you can write it like
## get :index, {param1: value1, param2: value2}
## In case you want to hit js type request you can pass format too.
## get :index, {format: :js}
assert_template :products # To check whether products.html.erb is rendered
assert_response :success # To check whether the response is with success status
assert_not_nil assigns(:products) # To check whether there is a products instance variable available
end
end
In the above example we have seen few different ways for calling an action from test cases. Now lets run the test case for it, to see whether it passes or not.
bin/rake test test/controllers/home_controller_test.rb
#=>
Run options: --seed 271
# Running:
.
Finished in 0.275001s, 3.6363 runs/s, 7.2727 assertions/s.
1 runs, 3 assertions, 0 failures, 0 errors, 0 skips
So here we have seen that it passed with all assertion cases. To give you more options for assertions, here are the 4 types of hashes which are available after the request is hit from the test cases.
a) All instance variables are stored insided assigns hash
b) All cookies are stored insided cookies hash
c) All instance variables are stored insided assigns
d) All session variables are stored insided session
Apart from the above hashes there are also 3 types of instance variables are available:
a) @controller - The controller processing the request
b) @request - The request
c) @response - The response
Thus if you want to add something in request header or so, you can do that using these instance variables like:
# To get a csv in response
@request.headers["Accept"] = "text/csv"
get :index
To test templates, layouts and partial, there are different kind of assertions available like:
assert_template :products # To check whether products.html.erb is rendered
assert_template :products, layout: "layouts/home"
# To check whether the layout rendered is layouts/home
assert_template :products, partial: "_home"
# To check if _home.html.erb is also rendered with the products template
So thus these are the things which are helpful for writing test cases. Now you are ready to write test cases on your own. Hope you enjoyed it.
0 Comment(s)