How I test Rails validations?

25 Feb 2014 By: Greg Molnar

I often get the question from new rubyist "How should I test my model validations in Rails?". A simple example is when we have a Post model with two required fields:

# app/models/post.rb
class Post < ActiveRecord::Base
  validates_presence_of :title, :body
end

You could write a test like this:

# test/models/post_test.rb
require 'test_helper'

class PostTest < ActiveSupport::TestCase
  test "should not save post without title or body" do
    post = Post.new
    assert_not post.save
    post.title = 'Test'
    assert_not post.save
    post.body = 'Test body'
    assert post.save
  end
end

But this test is already too long and what if you have a lot more required fields? To get around this it is better to test if the validation errors are correct:

# test/models/post_test.rb
test "should have the necessary required validators" do
  post = Post.new
  assert_not post.valid?
  assert_equal [:title, :body], post.errors.keys
end

Now we cover the existence of the validators with a lot shorter and simpler test. We can use the same approach to test ther validation rules like numericality:

# app/models/post.rb
class Post < ActiveRecord::Base
  validates_presence_of :title, :body
  validates :score, numericality: true, allow_blank: true
end
# test/models/post_test.rb
test "should have numeric score" do
  post = Post.new(title: 'test', body: 'test body', score: 'test')
  assert_not post.valid?
  assert_equal ["is not a number"], post.errors.messages[:score]
end

And so on. As some of the readers pointed out if you need a full blown solution with support of on and etcetera thoughbot's shoulda-matchers is has all that.

PS: If you want to get updates from me please subscribe to my email list.
I hate spam as much as you do, so I won't send you anything else than Ruby/Rails related updates occasionally, and of course you can unsubcribe anytime.