[Fwd: Functional test problem]

Anyone?

-------- Original Message --------
Subject: Functional test problem
Date: Wed, 14 Jun 2006 19:49:03 +0100
From: Chris T [email protected]
Reply-To: [email protected]
To: [email protected]

Embarrassingly late (apps already well advanced), have decided top get
to grips with testing and am having a week hopefully covering everything
I’ve already coded (so far it’s been worth it – found a couple of bugs
might not have found otherwise).

But having a bit of a prob with a functional test. I’m trying to
enumerate through through a list of users in a fixtures file, and test
against each one, but it’s doing something very weird. Here’s the basics
of the test

def test_index_user
User.find(:all).each do |user|
get :index, {}, {:user => user.id}
assert_response :success
assert_tag :tag => “div”,
:attributes => {
:id => “usermenu”
},
:content => /Hello\s#{user.login}/
end
end

What’s happening is that it’s failing, saying:

expected tag, but no tag found matching {:tag=>“div”,
:content=>/Hello\sarthur/, :attributes=>{:id=>“usermenu”}} in:
#dump of tags including…

\r\nHello quentin ...
... quentin is the first fixture in users, arthur is the second. It seems like the get :index is not successfully putting the new user id in the session.

Can anyone help me understand what’s going on?

Chris T wrote:

Anyone?

-------- Original Message --------
def test_index_user
User.find(:all).each do |user|
get :index, {}, {:user => user.id}
assert_response :success
assert_tag :tag => “div”,
:attributes => {
:id => “usermenu”
},
:content => /Hello\s#{user.login}/
end
end

What’s happening is that it’s failing, saying:

expected tag, but no tag found matching {:tag=>“div”,
:content=>/Hello\sarthur/, :attributes=>{:id=>“usermenu”}} in:
#dump of tags including…

\r\nHello quentin ...
... quentin is the first fixture in users, arthur is the second. It seems like the get :index is not successfully putting the new user id in the session.

Can anyone help me understand what’s going on?

Here’s some possible ides, they are of the “it takes someone else to
suggest a stupid idea variety” though… so I’m not sure how likely
they’ll be.

  1. Have you confirmed that the page works as desired in the browser
    (perhaps the welcome message was hard-coded?)

  2. Have you done anything “weird” with caching that might somehow be
    causing the test environment to cache the results of the pages?

  3. if you unroll the loop, does it still fail?

Eric

Thanks for the suggestions. Actually it is working in the browser.
After a bit of digging, I thought the problem might be with the
current_user method which wasn’t being updated with the change in
session[:user], so posted the query on Railsweenie hoping Rick might be
able to help (as the author of acts_as_authenticated). This is what he
said (which makes sense):

You can't call a controller method multiple times in a functional
test. Instance variables like @controller, @request, and @response
don't get recycled. So, since the same controller instance is
sticking around, that means the same @current_user is too.

Not sure if there’s a good way to achieve what I’m trying to do – it’s
not particular the Hello user I want to test, but I want to test the
number of items each user sees of a particular kind). Do separate tests
for each case? Or loop through a test rather than the controller method?
Or could (should?) I use integration tests (which i haven’t yet
investigated)?

Still quite new to this whole testing lark. Never had anything like this
in php :wink:

Chris T wrote:

Eric

Thanks for the suggestions. Actually it is working in the browser.
After a bit of digging, I thought the problem might be with the
current_user method which wasn’t being updated with the change in
session[:user], so posted the query on Railsweenie hoping Rick might be
able to help (as the author of acts_as_authenticated). This is what he
said (which makes sense):

You can't call a controller method multiple times in a functional
test. Instance variables like @controller, @request, and @response
don't get recycled. So, since the same controller instance is
sticking around, that means the same @current_user is too.

Interesting, so it was “almost” a caching type issue…

Not sure if there’s a good way to achieve what I’m trying to do – it’s
not particular the Hello user I want to test, but I want to test the
number of items each user sees of a particular kind). Do separate tests
for each case? Or loop through a test rather than the controller method?
Or could (should?) I use integration tests (which i haven’t yet
investigated)?

I tend to subscribe to the ~1 assertion per test approach. Controller
tests already start to push that to 2-4 assertions so I definitely
wouldn’t combined tests for different aspects of the same functionality
into one test. So yes, I’d break up the test to separate cases.

Are you trying to test that the Model retreived the correct number of
things (in which case that would probably belong in a unit test of the
model, not the controller), or is there some controller side logic that
affects the list before rendering that you need to test?

Or are you testing that a list renders properly, perhaps with some
alternate text for cases where there are no elements? From a list
viewpoint, when I’m being pendantic in my tests, I’ll commonly take an
induction-based approach and write a test for each of the following:
base cases (empty list, one item list)
inductive case (assume it works for n, prove that it works for n+1)
Note, some testers talk about testing 0,1,2 and calling it “inductive”,
but unless the test case for 2 is written properly its not inductive.
An inductive test case looks like:
def test_inductive_step_for_foo
current_result = foo.method_to_test
foo.add next_foo
assert_equal current_result+correct_delta, foo.method_to_test
end
(of course method names, variables, and mechanism for combining
current_result and correct_delta will vary, but the key point is that
transformation from one state to the next is correct, not merely that
each state is correct.)

Eric

Eric D. Nielsen wrote:

Not sure if there’s a good way to achieve what I’m trying to do – it’s
into one test. So yes, I’d break up the test to separate cases.

Think you’re prob right here.

Are you trying to test that the Model retreived the correct number of
things (in which case that would probably belong in a unit test of the
model, not the controller), or is there some controller side logic that
affects the list before rendering that you need to test?

No , it’s not that (see below). Interestingly, though, I did on another
controller have some functionality which the process of writing a test
for led me to put the logic into the model, where it more properly
belonged. +1 for tests helping to structure things better

Or are you testing that a list renders properly, perhaps with some
alternate text for cases where there are no elements? From a list
viewpoint, when I’m being pendantic in my tests, I’ll commonly take an
induction-based approach and write a test for each of the following:
base cases (empty list, one item list)
inductive case (assume it works for n, prove that it works for n+1)

Yes, it’s one of those case. Will try this out

transformation from one state to the next is correct, not merely that
each state is correct.)

Eric

Thanks for the suggestions. Much appreciated

I found that you can just recreate a controller before you want to login
with other user in the same test.