Rails Unit/Functional Tests

In my latest rails project, I am trying to write good tests for everything important. My first tests were all unit tests. These are pretty easy. All they basically do is make sure that the data that’s stored in the database is formatted properly. So I have a bunch of tests that make sure that my validations are correct. A sample test looks like this:

  test "save a project without a subaccount" do
    project = Project.new(:name => 'Bit Test', :account => '123432')
    assert !project.save, "Saved a project without a subaccount"
  end

This is pretty basic. What I like about unit tests though are how they make sure a custom validation is working correctly. In this application, I’m tracking costs for a number of projects. Each project has an account and subaccount stored with it. The account-subaccount combination must be unique. So I have a validation in my model like this:

validates_uniqueness_of :account, :scope => [:subaccount]

And I can check this validation with this unit test:

  test "save the same account-subaccount combo twice" do
    project = Project.new(:name => 'NSF', :account => '12345', :subaccount => '1234')
    assert project.save, "Didn't save first account-subaccount combo"
    project2 = Project.new(:name => 'DOE', :account => '12345', :subaccount => '1234')
    assert !project2.save, "Saved an account-subaccount combo twice"
  end

Functional tests check the controller. For this project, everything is behind a login. No one can see anything without logging in. So, the only controller test I can really make is to check that anyone trying to get to a page without logging in is directed to the login page. So I really only have a single functional test for all my controllers.

  test "should not get index" do
    get :index
    assert_response 302, "Didn't get redirected"
    assert_redirected_to login_url, "Didn't go back to login page"
  end

I guess I could write a test for each page (new, edit, show, etc.) behind the login, but I’m satisfied with just checking a single one.