Basic TDD in Rails : Writing a Controller Test

Objective


  • Learn how to write controller tests.

Steps


Step 1

Run the articles controller test.

$ rspec spec/controllers/articles_controller_spec.rb 

Step 2

Let's write a test to list articles in the articles page.

  it 'should get all the articles' do
    get :index

    expect(assigns[:articles]).not_to be_nil
  end

Step 3

You get the error:

 1) ArticlesController should get all the articles
     Failure/Error: expect(assigns[:articles]).not_to be_nil
       expected: not nil
            got: nil

Step 4

Implement the index action in articles_controller:

class ArticlesController < ApplicationController
  def index
    @articles = []
  end
end

Step 5

Run the test.

$ rspec spec/controllers/articles_controller_spec.rb 
..

Finished in 0.02335 seconds (files took 4.54 seconds to load)
2 examples, 0 failures

Step 6

Change the test so that it is more specific.

  it 'should get all the articles' do
    get :index

    expect(assigns[:articles]).not_to be_empty 
  end

Instead of checking for nil, we now check it is not empty.

Step 7

 1) ArticlesController should get all the articles
     Failure/Error: expect(assigns[:articles]).not_to be_empty
       expected `[].empty?` to return false, got true

Step 8

Create the article model.

$ rails g model article title:string description:text

Step 9

Create the articles table.

$ rake db:migrate

Step 10

Run the test. It fails. So we need to create an article in the database before we can call the index action. Change the test like this:

  it 'should get all the articles' do
    Article.create(title: 'test')

    get :index

    expect(assigns[:articles]).not_to be_empty 
  end

Step 11

Run the test it fails.

Step 12

Change the index action so that it retrieves all the articles in the database.

class ArticlesController < ApplicationController
  def index
    @articles = Article.all
  end
end

Step 13

Run the test. It passes.

Step 14

Make the test precise.

  it 'should get all the articles' do
    Article.create(title: 'test')

    get :index

    expect(assigns[:articles].size).to eq(1)
  end

It should pass.

Step 15

Run all the controller tests. It will pass.

Summary


In this lesson, you learned how to write a controller test. We started with a trivial controller test that checked for not nil, then not empty and finally check for the size. We gradually refined the test to become more specific, forcing the implementation to become generic.


Related Articles


Ace the Technical Interview

  • Easily find the gaps in your knowledge
  • Get customized lessons based on where you are
  • Take consistent action everyday
  • Builtin accountability to keep you on track
  • You will solve bigger problems over time
  • Get the job of your dreams

Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.