DRY act_as_authenticated functional testing

You can either put the login_as in the setup method or have tests that capture the behavior of not being logged in separately from the behavior when the current user is already known. If you have some authorization process (what a user is allowed to do) separate from the authentication process (who is this user), then you may want to go that route since you have three conditions: not authenticated (i.e., not logged in); authenticated, but unauthorized (e.g., normal user accessing a privileged action); and authenticated and authorized. (Note that someone can be authorized to do something even when not authenticated such as signing up or seeing the login form.)

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

Rob Biedenharn wrote:

You can either put the login_as in the setup method or have tests that
capture the behavior of not being logged in separately from the
behavior when the current user is already known. If you have some
authorization process (what a user is allowed to do) separate from the
authentication process (who is this user), then you may want to go
that route since you have three conditions: not authenticated (i.e.,
not logged in); authenticated, but unauthorized (e.g., normal user
accessing a privileged action); and authenticated and authorized.
(Note that someone can be authorized to do something even when not
authenticated such as signing up or seeing the login form.)

Hi Rob -

Thanks for your help. I do have the authorization and authentication
processes separate from one another. I have:

def setup
   login_as :quentin
end

But now the only way that I'm able to get this to work is if I include
this as the first line for all of my tests.

assert login_as("quentin")

If that assert line is missing, then my response changes from (:success)
to (302) - redirect.

Thanks!

UPDATE:

Actually, I can comment out the def setup and as long as I leave in
assert login_as in each test, the tests pass. Something doesn't seem
right.

You ought to have a bit more in your setup than that for a functional test.

When I want to test both things, I have something like this (with 'foo' and 'bar' standing in for the application specific terms):

   def test_foo_selection_on_restricted_bar
     login_as :regular
     get :foos, :id => 9
     assert_redirected_to bar_url
   end

   def test_foo_selection_needs_login
     get :foos, :id => 1
     assert_response :redirect
   end

   def test_foo_selection
     login_as :admin
     get :foos, :id => 1
     assert_response :success
   end

When I just want to be logged in for every test, the setup looks like:

   def setup
     @controller = FoosController.new
     @request = ActionController::TestRequest.new
     @response = ActionController::TestResponse.new
     login_as :admin
   end

It's also possible that you have two definitions for setup and only the last one is really having any effect (since its definition would have overwritten the original one).

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

Rob Biedenharn wrote:

You ought to have a bit more in your setup than that for a functional
test.

The tests are actually testing other controller functions, not the login
function. But I do have login tests. Is it possible to have the def
setup with the login_as :admin and also have tests that test the login.

For example I would want Test 1 - tests the login, Test 2 - tests the
controller function that needs the login.

If I have def setup with the login, will Test 1 then be useless or can I
set the login user to nil or something like that?

Thanks for all of your help!

The definition of login_as is in:
  lib/authenticated_test_helper.rb

You get the effect of logging out with:
  login_as nil

It can be immensely helpful to read the Ruby code that implements this kind of thing. One reason is to see the answer to this kind of question directly, but also you start to see how easy some of the "magic" really is and start to craft some of your own.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

I am also having a problem running functional tests and putting the
login_as in the setup method. I am on Rails 2.0.2 and trying to use:

def setup
  super
  login_as :dan
end

This does not work. In the controller being tested, current_user is
equal to :false.

However, if I put the login_as directly into each functional test
method, it works.

Anybody know why?

-Shannon

I have implemented this:

def setup
  login_as :quentin
end

  def test_should_get_new
    get :new
    assert_response :success
  end

And get this error:
Expected response to be a <:success>, but was <302>

If I have the test as this it passes.
  def test_should_get_new
    assert login_as :quentin
    get :new
    assert_response :success
  end

Sorry, I meant to write that I have this as def setup. I had copied and
pasted old code. Foos is replaced by name controller name

def setup
     @controller = FoosController.new
     @request = ActionController::TestRequest.new
     @response = ActionController::TestResponse.new
     login_as :admin
   end