Some of the more rudimentary aspects of unit testing involve validation. These tests may exercise ActiveRecord or the database constraints created by a migration.

In a chapter from Enterprise Rails, 'Database As a Fortress', author Dan Chak advocates for employing the data integrity features of modern databases, particularly PostgreSQL. With Realized-app, we use PostgreSQL as a persistent data store.

To go beyond just testing the ActiveRecord model validations, in testing a database constraint Dan suggests using the following test_helper.rb method:

def expect_db_error(&block)
  begin
    yield
  rescue ActiveRecord::StatementInvalid
    database_threw_error = true
  rescue
    something_else_threw_error = true
  end
  assert !something_else_threw_error, 'defective case'
  assert database_threw_error && !something_else_threw_error
end

One difficulty with testing database constraints is that the ActiveRecord model validations may catch some errors before they reach the PostgreSQL database. As a work-around, we can add another method:

def svf(obj) obj.save_with_validation(false) end	

Using these test helpers, this test will properly exercise the database constraints defined by a migration.

test 'name too long' do
  expect_db_error { svf(some_model_save(:name => 'name_too_long')) }
end

Such validation tests tend to be similar among different models. Just as concerned_with allowed for division of model logic into discrete files, we place unit test validation tests in a separate /test/unit/validation directory. This prevents cluttering model-specific logic with boilerplate validation checks.