Anyone? -------- Original Message -------- Subject: Functional test problem Date: Wed, 14 Jun 2006 19:49:03 +0100 From: Chris T <ctmailinglists@gmail.com> Reply-To: ctmailinglists@gmail.com To: rails@lists.rubyonrails.org 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.. <div id=\"usermenu\">\r\nHello quentin ... </div> ... 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.. > <div id=\"usermenu\">\r\nHello quentin > ... > </div> > ... > 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? -- Posted via http://www.ruby-forum.com/.
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 ;-) Eric D. Nielsen wrote:> 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.. >> <div id=\"usermenu\">\r\nHello quentin >> ... >> </div> >> ... >> 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? > > >
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 -- Posted via http://www.ruby-forum.com/.
Eric D. Nielsen wrote:> 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. > >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> 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 > >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. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---