Make a controller test for the limericks index controller action

Controller tests in Rails are automated tests in which we simulate HTTP requests to check whether our controllers process and respond to them correctly. We will write at least one controller test for every controller action.

In this part, we will add a controller test for the index action of the LimericksController controller class. Our aim is to confirm that if our app receives an HTTP GET request with the URL for the limericks index page, the app will process the request without crashing and will respond successfully.

Inspect the LimericksController#index controller action

There are a couple pieces of information that we must collect about the controller action we mean to test:

Open the config/routes.rb file, and locate the route that calls this index action. You should find this route:

  root to: 'limericks#index'

Note that this is the root route for the app. The URL helper for the root route is root_url.

Open the controller class file app/controllers/limericks_controller.rb, which contains the LimericksController class, in VS Code. Inspect the code related to the index method. You should see the following.

class LimericksController < ApplicationController

  before_action :authenticate_user!, except: [:index]
  before_action :require_permission, except: [:index, :new, :create]

  def index
    @limericks = Limerick.all.reverse_order
    render :index
  end

  ...

Note that (as per the before_action declarations) no user authentication is required to run the index action. Also note that the index action behaves in the usual way, retrieving a collection of limericks from the database and rendering a view template app/views/limericks/index.html.erb.

Add a controller test for LimericksController#index

Each automated test we write can divided into three steps:

To test the LimericksController#index action, we plan each of these steps as follows:

The controller tests for the LimericksController controller class should go in the LimericksControllerTest controller test class (defined in test/controller/limericks_controller_test.rb). Note that, in general, for a controller class defined in app/controllers/xxxxx_controller.rb, the controller test class for that controller should be defined in test/controllers/xxxxx_controller_test.rb.

Open the controller test file test/controller/limericks_controller_test.rb in VS Code. It should contain only one test case, the "the truth" test case we uncommented previously.

  test "the truth" do
    assert true
  end

Edit the name of the test case to "should get index" to communicate the action under test (index) and the expected result (“should get”, success being implied by “should”).

  test "should get index" do
    assert true
  end

Arrange. Store the number of Limerick fixtures in a variable, so in the Assert step, we can check that the correct number of limerick cards are rendered on the index page.

  test "should get index" do
    limericks_size = limericks.size
    assert true
  end

Note that the call to limericks retrieves all the Limerick fixture objects from the database. For each fixture file, Rails provides a method of the same name for retrieving the fixtures.

Act. Use the get command to simulate an HTTP GET request with the URL for the root route as follows.

  test "should get index" do
    limericks_size = limericks.size
    get root_url
    assert true
  end

Assert. Replace the assert true call with with a call to assert_response that checks that the HTTP response produced by the app has a success code (a 2xx status code, like 200 OK).

  test "should get index" do
    limericks_size = limericks.size
    get root_url
    assert_response :success
  end

Add an additional call to assert_select that checks that the correct number of cards were rendered on the page.

  test "should get index" do
    limericks_size = limericks.size
    get root_url
    assert_response :success
    assert_select 'div.card', limericks_size
  end

Note that the call to assert_select counts the number of HTML div elements with CSS class card and checks that the count is equal to limericks_size (the number of Limerick fixtures).

Run the controller test

Run the following command to run all test cases defined in the project.

rails test -v

The output of the command should look like the following.

Running 1 tests in a single process (parallelization threshold is 50)
Run options: -v --seed 29234

# Running:

LimericksControllerTest#test_should_get_index = 2.17 s = .

Finished in 2.178224s, 0.4591 runs/s, 0.9182 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips

Note that the output mentions that 1 test ran (LimericksControllerTest#test_should_get_index) and that test had 2 assertions, which makes sense because we called assert_response and assert_select. If either assertion had failed, an error message would have been displayed, and the failure count would have been greater than zero. If the app had crashed while processing the request, error messages would have been displayed, and the error count would have been greater than zero.


⏴ Back Next ⏵