Basic TDD in Rails : Writing Validation Tests for the Model


Handle the negative case in the model unit tests.


Why are we using unit tests for negative cases? In other words, why not write feature specs for all the negative cases?

alt text

As you can see, in the Testing Pyramid, the bottom has more tests and as we go up the pyramid, we have less tests of those type. We write unit tests to cover all cases while the integration tests are written to cover the happy path. Unit tests run fast so we can write many tests. The integration tests cuts through different layers and is slower. So we minimize the integration tests by focusing only on the happy path.


  1. To create a valid article, it must have both title and description.

  2. If the validation fails we must display the new form with error message and allow user to correct the mistake and resubmit the form.

In this lesson we will handle the requirement #1. The next lesson will handle the requirement #2.


Step 1

Run article_spec.rb.

$ rspec spec/models/article_spec.rb 

You get 'pending' message.

Step 2

Write a test for positive case where title and description are provided.

require 'rails_helper'

describe Article, type: :model do
  it 'is valid if title and description fields have value' do
    article = 'test', description: 'test')

    expect( eq(true)

Step 3

Run the test:

$ rspec spec/models/article_spec.rb 

The test passes without failing. This is fine. Checking the return value is one way to check we saved the article. Another way is to check the article count went up by one, like this:

require 'rails_helper'

describe Article, type: :model do
  it 'is valid if title and description fields have value' do
    expect do
      article = 'test', description: 'test') change{Article.count}.by(1)

Step 4

Add the second test for missing title as follows:

require 'rails_helper'

describe Article, type: :model do

  it 'is not valid if it has no title' do
    article = 'test')

    expect( be(false)

Step 5

Run the test.

$ rspec spec/models/article_spec.rb 

It fails.

 1) Article is not valid if it has no title
     Failure/Error: expect( be(false)

       expected false
            got true

Step 6

Add the validation for title to the article.rb as follows:

class Article < ActiveRecord::Base
  validates :title, presence: true

Step 7

Run the test.

$ rspec spec/models/article_spec.rb 

Finished in 0.05543 seconds (files took 2.1 seconds to load)
2 examples, 0 failures

It passes.

Step 8

You can also make your test precise by changing it like this:

  it 'is not valid if it has no title' do
    article = 'test')

    expect(article.errors[:title]).to eq(["can't be blank"])

This check the error is due to the missing title.


Write a failing test for missing description field and make it pass.


In this lesson you learned about the Testing Pyramid. We ran a pending spec, we wrote a tests for positive case and negative cases using unit tests. We saw two ways of asserting: checking return value vs counting the records. We also saw how to make test precise for validation checks. In the next lesson we will go up a layer and write tests for handling validation failure cases at the controller layer.

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.