I always seem to overlook testing. For one reason or another, it is really easy to forget about. But before getting too far into a project, it is a good idea to make sure you have some tests and that they are passing. Getting the initial tests to pass will be the focus of this post. The problem I have run into with restful_authentication is that the tests have not been updated for rails 2.0. Updating those tests to pass will be the subject of this post.

If you haven’t already, add the line ‘include AuthenticatedTestHelper’ to the bottom of the test/test_helper.rb file.

Before moving on, lets see where we stand with the current test cases. Here are my results

rake
...
...
1) Failure:
test_should_initialize_activation_code_upon_creation(UserTest) [./test/unit/user_test.rb:18]:
expected to not be nil.
24 tests, 42 assertions, 1 failures, 0 errors

Not a bad start. In my first post about restful_authentication, I changed what happens when users create accounts. This tests makes sure there is an activation code after creation, but is not needed now. To solve this, I’m just going to comment out that particular test and create a test that passes when the activation code is nil after creation. The test is almost identical and looks like this

def test_should_not_initialize_activation_code_upon_creation
  user = create_user
  assert_nil user.reload.activation_code
end

All tests now pass, but we are not finished. Lets add the admin_required filter to the articles controller except for the show and index actions and rerun the tests.

class ArticlesController < ApplicationController
  before_filter :admin_required, :except => [:index, :show]


rake
...
...
1) Failure:
test_should_create_article(ArticlesControllerTest)
<3> expected but was
<2>.
2) Failure:
test_should_destroy_article(ArticlesControllerTest)
<1> expected but was
<2>.
3) Failure:
test_should_get_edit(ArticlesControllerTest)
Expected response to be a <:success>, but was <302>
4) Failure:
test_should_get_new(ArticlesControllerTest)
Expected response to be a <:success>, but was <302>
5) Failure:
test_should_update_article(ArticlesControllerTest)
expected a redirect to <{"action"=>"index", "controller"=>"articles"}>, found one to <{"action"=>"new", "controller"=>"sessions"}>, a difference of <{"action"=>"new", "controller"=>"sessions"}>
26 tests, 43 assertions, 5 failures, 0 errors

The unit tests still pass, but the functional tests now get 5 failures
From here, the next thing to do is change the restful_authentication test code to the rails 2.0 way. Open up your users fixture and change it to this

quentin:
  login: quentin
  email: quentin@example.com
  salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
  crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
  created_at: <%= 5.days.ago.to_s :db %>
  activated_at: <%= 5.days.ago.to_s :db %>
  state: active
  role: administrator
aaron:
  login: aaron
  email: aaron@example.com
  salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
  crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
  created_at: <%= 1.days.ago.to_s :db %>
  activated_at: <%= 1.days.ago.to_s :db %>
  state: active
  role: subscriber

All I did was delete the id and activation code. Next thing to do is modify the sessions and users controller test files. The tests themselves to not need to be changed, just the top portion. Posted below is what your edited files will look like through the first test. As you can see, all the stuff that rails now does automatically has been removed and the controller tests changed from Test::Unit::TestCase to ActionController::TestCase.

# test/functional/users_controller_test.rb
require File.dirname(__FILE__) + '/../test_helper'

class UsersControllerTest < ActionController::TestCase

  def test_should_allow_signup
    assert_difference 'User.count' do
      create_user
      assert_response :redirect
    end
  end

# test/functional/sessions_controller_test.rb
require File.dirname(__FILE__) + '/../test_helper'

class SessionsControllerTest < ActionController::TestCase

  def test_should_login_and_redirect
    post :create, :login => 'quentin', :password => 'test'
    assert session[:user_id]
    assert_response :redirect
  end

For our articles tests, we now need to login_as :quentin for the tests that require admin privileges. Add that line to the top of the five test cases that require admin privileges and all those tests pass. The only test that fails now is the the test_should_activate_user(UsersControllerTest), but like the first test failure, is not needed anymore.

It might also be a good idea to add in the tests that make sure users can’t do things without the required privileges. Here are the five I added to make sure only authorized users can create and edit articles

  def test_should_not_get_new
    get :new
    assert_redirected_to login_path
  end

  def test_should_not_create_article
    assert_difference('Article.count', 0) do
      post :create, :article => { :title => "title one", :body => "body one" }
    end
  end

  def test_should_not_get_edit
    get :edit, :id => articles(:one).id
    assert_redirected_to login_path
  end

  def test_should_not_update_article
    put :update, :id => articles(:one).id, :article => {:title => "this is the new title"}
    assert_redirected_to login_path
  end

  def test_should_not_destroy_article
    assert_difference('Article.count', 0) do
      delete :destroy, :id => articles(:one).id
    end
    assert_redirected_to login_path
  end

Of course, it is a good idea to make sure only admins can create and edit articles and that subscribers cannot. That will be left for you when you to complete.

Since I’ve been trying to keep this discussion to restful_authentication, I haven’t really touched on the articles model. I just want to mention though, I am making the assumption that an article model will always need a title and body. Because of this, I added the validates_presence_of :title, :body line to my model.

That should be enough to get your tests passing. Eventually, this info will be obsolete, but until then, this should help.

Tags: ,