Testing Rails validations

Today, I extracted some code from an older IBLP project and polished it up a bit for use on the Ruby Web site. It makes it quite easy to test validations on model objects in Rails. I present:

validation_helper.rb

When you include ValidationTestHelper into your test case you can access to two additional assertions: assert_valid and assert_invalid. Use them to assert that a model object is valid or invalid when a field is set to a certain value.

For example, suppose you have a model object that looks like this:

class Page < ActiveRecord::Base
  validates_presence_of :title, :slug, :breadcrumb, :status_id, :message => 'required'
  validates_format_of :title, :slug, :breadcrumb, :with => /^.*?\S.*?$/, :message => 'required'
  validates_format_of :slug, :with => /^[-_.A-Za-z]*$/, :message => 'invalid format'
end

To test it, first set the @model instance variable to an object that will validate without errors:

@model = Page.new(
  :title => 'New Page',
  :slug => 'new-page',
  :breadcrumb => 'New Page',
  :status_id => '1'
)

Were you to call @model.valid? at this point, it would return true. But hold steady, you are ready to write your first assertion:

assert_invalid :title, 'required', '', ' ', nil

This will assert that when the title field on your @model object is set to "", " ", or nil that a validation error occurs and that the error message is set to “required”. Note that the first two parameters are for the field name and message, while the parameters at the end are all values to test.

The next assertion, assert_valid, is useful for testing that an object should be valid when when a field is set to a value or series of values. For example, to test the regular expression that is being used to validate the slug field we can do:

assert_valid :slug, 'abc', 'abcd-efg', 'abcd_efg', 'abc.html'

This will set the slug attribute on the @model object to ‘abc’, ‘abcd-efg’, ‘abcd-efg’, and ‘abc.html’. Each time it will check to see if the model is valid with the new value. If it is not for any one of the values, the assertion will fail.

Pretty nifty, eh?

Here’s an entire test method for all of the validations shown in the model above:

def test_validations
  @model = Page.new(
    :title => 'New Page',
    :slug => 'new-page',
    :breadcrumb => 'New Page',
    :status_id => '1'
  )
  
  [:title, :breadcrumb, :slug].each do |field|
    assert_invalid field, 'required', '', ' ', nil
  end 
    
  assert_valid :slug, 'abc', 'abcd-efg', 'abcd_efg', 'abc.html'
  assert_invalid :slug, 'invalid format', 'abcd efg', 'abcd/efg'
    
  assert_invalid :status_id, 'required', '', nil
end

Special thanks to Ryan Platte for his part in conceiving and coding ValidationTestHelper.

© 2013 John W. Long