[rspec-users] Specing protected methods
Hi everyone, Do anyone know if there's a way to spec protected methods ? Thanks in advance -- Bastien ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] Specing protected methods
I totally agree with the ''listening to your specs concepts and always divide my code into small methods easier to spec. Now let me get you right, here's my code : class Survey ActiveRecord::Base has_many :participants ... def generate_reports ... sub_total = sub_total(participants.reports) ... end protected def sub_total(reports) sub_total = 0 reports.collect do |report| sub_total = sub_total + report.score end return sub_total end end I m already specing the generate_reports methods with a mock on sub_total, but I would also like to spec that method. I've put this method into protected because it doesn't make sens to call it from outside this class. But you're arguing that I should put that method into a lib ? I m not sure it would make sense as this method is very specific to that class, and would actually be easy to spec. Except that it's not possible to call a protected method from a spec as far as I know, correct me if I m wrong. (I maybe didn't explain my problem well in the first place) Regards -- Bastien On Oct 23, 12:37 pm, Matt Wynne [EMAIL PROTECTED] wrote: On 23 Oct 2008, at 10:16, Bastien wrote: Hi everyone, Do anyone know if there's a way to spec protected methods ? Thanks in advance Sorry if this sounds preachy, but I would always advise you to factor out the code in the method into another class, then test that class. If the behaviour of the method is so complex you need to test it on it's own, it deserves to be in a class all by itself. This is what we call, 'listening to your specs' - if it's hard to spec, you've probably got the design wrong. HTH, Matt ___ rspec-users mailing list [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] Specing protected methods
Thanks for all your answers. I was just wondering how about using send in my specs ? It would bypass the protected limitation without altering my code : @survey.send( :sub_total, [EMAIL PROTECTED] ) Is that the kind of trickery you were referring to David ? Would that be bad practice ? Regards -- Bastien On Oct 23, 3:51 pm, David Chelimsky [EMAIL PROTECTED] wrote: On Thu, Oct 23, 2008 at 6:49 AM, Bastien [EMAIL PROTECTED] wrote: I totally agree with the ''listening to your specs concepts and always divide my code into small methods easier to spec. Now let me get you right, here's my code : class Survey ActiveRecord::Base has_many :participants ... def generate_reports ... sub_total = sub_total(participants.reports) ... end protected def sub_total(reports) sub_total = 0 reports.collect do |report| sub_total = sub_total + report.score end return sub_total end end I m already specing the generate_reports methods with a mock on sub_total, but I would also like to spec that method. I've put this method into protected because it doesn't make sens to call it from outside this class. But you're arguing that I should put that method into a lib ? I m not sure it would make sense as this method is very specific to that class, and would actually be easy to spec. Except that it's not possible to call a protected method from a spec as far as I know, correct me if I m wrong. (I maybe didn't explain my problem well in the first place) This sort of decision is always a balancing act. Leaving it where it is means you have to either * unprotect it, which you clearly prefer not to do * expose it for you code example using clever ruby trickery * give up testing it directly * move it to another class, adding conceptual weight to your system None of these are perfect and all come with some tradeoff. I'll confess that, in practice, I'd probably not test this directly. More often than not, for me, the sub_total method is a result of refactoring the generate_reports method, which by that time would have at least two code examples in which the only difference is the sum of scores of the reports. In this case, however, assuming participants and reports are AR backed models, you don't really need to introduce a new class: subtotal = participants.reports.sum('score') Cheers, David Regards -- Bastien On Oct 23, 12:37 pm, Matt Wynne [EMAIL PROTECTED] wrote: On 23 Oct 2008, at 10:16, Bastien wrote: Hi everyone, Do anyone know if there's a way to spec protected methods ? Thanks in advance Sorry if this sounds preachy, but I would always advise you to factor out the code in the method into another class, then test that class. If the behaviour of the method is so complex you need to test it on it's own, it deserves to be in a class all by itself. This is what we call, 'listening to your specs' - if it's hard to spec, you've probably got the design wrong. HTH, Matt ___ rspec-users mailing list [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list [EMAIL PROTECTED] http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] Can't access actions of a singular nested resource
Thanks for your help Aslak, but I still didn't manage to make it pass get :show, :id=34 it sends me this error then : No route matches {:action=show, :controller=surveys/report, :id=34} Try rake routes, and also try to spec the routing in the associated routing_spec.rb. and this test passes : it should map { :controller = 'report', :action = 'show', :survey_id = 1} to /survey/1/report do route_for(:controller = surveys/report, :action = show, :survey_id = 1).should == /surveys/1/report end also if I try to remove my condition the test passes so the routes must be correct it should return the survey corresponding to the report do #Survey.should_receive(:find) get :show, :survey_id=34, :controller =surveys/report end Any other idea ? ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
[rspec-users] Can't access actions of a singular nested resource
I can't figure out what I do wrong there, I have a nested controller which is defined as a singular resource, the routing works properly, but inside my specs the request never goes through the show action. I keep on getting this error : Spec::Mocks::MockExpectationError in 'Surveys::ReportController should return the survey corresponding to the report' Mock 'Class' expected :find with (any args) once, but received it 0 times In my specs : require File.expand_path(File.dirname(__FILE__) + '/../../ spec_helper') describe Surveys::ReportController do it should return the survey corresponding to the report do Survey.should_receive(:find) get :show, :survey_id=34 end end In route.rb : map.resources :surveys do |survey| survey.resource :report, :controller ='surveys/report' end In controller/surveys/report_controller.rb : class Surveys::ReportController ApplicationController def show @survey = Survey.find(params[:survey_id]) respond_to do |format| format.html format.xml end end end ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] [Stories]Troubles with GivenScenario
done : http://rspec.lighthouseapp.com/projects/5645-rspec/tickets/350 Thanks for your great work. On Mar 25, 1:00 pm, David Chelimsky [EMAIL PROTECTED] wrote: On Tue, Mar 25, 2008 at 6:31 AM, Bastien [EMAIL PROTECTED] wrote: Of course, here you go : steps_for(:work_area_execution) do Given(a company) do @account = Factory.create_valid_account() end Given($amount questions?) do |amount| Question.delete_all category = Factory.create_valid_category work_area = Factory.create_valid_work_area(category) amount.to_i.times do Factory.create_valid_questions(work_area) end end Given(a department) do @department = Factory.create_valid_department(:account_id = @account.id) end Given(a number of replies) do @replies = Reply.find(:all).size end Given(the logged in user $email) do |email| @user = Factory.create_valid_user(:email=email, :department_id = @department.id, :account_id = @account.id) @user_profiles = Profile.find(:all, :conditions = ['user_id = ?',@user.id]).size host! company.example.com post sessions, {:login = email, :password = bacon} follow_redirect! if redirect? end When(the user starts a new profile) do post person_profiles_path(@user) follow_redirect! if redirect? end When(the user answers a question) do q = Question.find(session[:current_question]) # doesn't work with GivenScenario w = q.work_area c = w.category post profile_question_answers_path(@user.profiles.first, q.id), { 'reply[current]' = 4, 'reply[work_area_id]' = w.id, 'reply[question_id]' =q.id, 'reply[category_id]'= c.id, 'reply[base]' = nil, } follow_redirect! if redirect? end Then(there should be a new profile for this user) do @user.profiles.size.should == @user_profiles + 1 end Then(there should be a list of remaining questions) do session[:current_question].should_not == nil session[:pending_questions].should_not == nil @remaining_questions = session[:pending_questions].size end Then(there should be one question less to answer) do session[:pending_questions].size.should == @remaining_questions - 1 @remaining_questions = session[:pending_questions].size end Then(there should be one more answer) do Reply.find(:all).size.should == @replies + 1 @replies = Reply.find(:all).size end Then(there should be no more question to answer) do session[:pending_questions].size.should == 0 session[:current_question].should == nil end Then(the profile should be set as terminated) do @user.profiles.first.finished_at.should_not == nil end end Looks like GivenScenario gets run in a separate instance of RailsStory (which is derived from ActionController::IntegrationSession) from the rest of the scenario. This would explain why the session gets cleared out. I can tell you that the DB state does NOT get cleared out, but the mechanism is different. I'm not going to have cycles to investigate a solution right away, so would you please submit a ticket athttp://rspec.lighthouseapp.com? Thanks, David Thanks for your time and help. On Mar 25, 12:07 pm, David Chelimsky [EMAIL PROTECTED] wrote: On Tue, Mar 25, 2008 at 5:13 AM, Bastien [EMAIL PROTECTED] wrote: I have some problems with GivenScenario, my scenario keeps on failing when I use GivenScenario, like if the database or the session was not in the same state at the beginning of the new scenario as it was at the end of the given one. If I try to group my two scenari in only one big scenario then it passes... Any clue of what I might do wrong there ? Hard to tell from plain text. Can you post the steps definitions? you can see here my story : Story: Filling a profile As a user I want to fill a profile So that I can see my score Scenario: Starting a new profile Given a company And a department And 2 questions And a number of replies And the logged in user [EMAIL PROTECTED] When the user starts a new profile Then there should be a new profile for this user And there should be a list of remaining questions ( ids stored in the session ) When the user answers a question Then there should be one more answer Then there should be one question less to answer Scenario: Ending a profile GivenScenario: Starting a new profile # if i remove these 2 lines it passes
[rspec-users] [Stories]Changes in the database not taken into account
I have these scenarios : Story: Filling a profile As a user I want to fill a profile So that I can see my score Scenario: Starting a new profile ...* And 3 questions ...* When the user answers a question Then there should be one more answer Then there should be one question less to answer Scenario: Ending a profile ...* And 1 question ...* When the user answers a question Then there should be one more answer Then there should be no more question to answer * code hidden for clarity If I run these two scenarios independently they both work, but when i run them one after the other, the second scenario fails. The problem appears in Given($amount questions?), even I create a new question in the database, it doesn't seem to be taken into account and keeps the 3 questions I created in the previous scenario. Here is what it looks like : Given($amount questions?) do |amount| Question.delete_all amount.to_i.times do Factory.create_valid_question end end class Factory def self.create_valid_question() Question.create!(:value = some question ) end end By adding outputs I observed that during the second scenario there are no questions in the database before the times loop, that they are created inside it, but after the loop I have the same questions in the database as the ones i had in the previous scenario and not the one i just created through the loop. This is really strange. (Sorry for this long question). Do you have any idea what I do wrong ? ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] [Stories] Login and subdomain
Thanks to all of you, I added the login as a part of the story and now it works smoothly. On Mar 7, 9:35 pm, Zach Dennis [EMAIL PROTECTED] wrote: In case it isn't clear... I agree with Ivo's statement: You should not stub the authentication method in a story. The story should test the whole application framework. emphasis on story Zach On Fri, Mar 7, 2008 at 11:13 AM, Zach Dennis [EMAIL PROTECTED] wrote: On Thu, Mar 6, 2008 at 10:38 AM, Pat Maddox [EMAIL PROTECTED] wrote: On Thu, Mar 6, 2008 at 7:27 AM, Ivo Dancet [EMAIL PROTECTED] wrote: You should not stub the authentication method in a story. The story should test the whole application framework, that way your story might look like this: Given a user from company x When logging in And requesting some page Then the application should do all the stuff it should In the given step you set your host, user name and password and you create that user. In the when steps you make the login request and then you can start doing the stuff you really want to test here as you'll have the session you want at that moment. That's a little too dogmatic for me. You needn't go through the entire stack every story, and you needn't go through the entire app path either. IMO you should be simulating as much as possible what the user is doing. If they have to go through path a, b, c ... to get to Z, then so be it. This involves keeping a well-factored set of helpers which can be used to navigate the app just like a user would. The only things you probably should be stubbing in a story are third party components your site may have to integrate with that aren't realistic to be run for every story (for the most part, there are other exceptions as well I know). I would avoid stubbing core functionality related to your site, -- Zach Dennis http://www.continuousthinking.com -- Zach Dennishttp://www.continuousthinking.com ___ rspec-users mailing list [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
[rspec-users] [Stories] Login and subdomain
I've just begin using rspec stories, and i m encountering some problems. In my application i have different subdomains in which specific users can log in, for example an admin will go to admin.myapp.com/authenticate/login, and an user belonging to a specific company will log in company.myapp.com/authenticate/login, and of course both have a different login process. To perform some actions the user has to be logged in, and this is where the problem comes, how to test these actions ? - Is there a way to set a user as logged in ? (that would definitely be very convenient) So far I have tried to do the following : post /authenticate/login, {:login = user_email, :password = password } but the problem is that it doesn't use the correct subdomain and the login, as expected in that case, fails, so how to define the correct subdomain ? Thank you in advance for your help. ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] [Stories] Login and subdomain
Thanks David, this works just fine. I would rather do some stubbing there if it's possible though. I tried : ApplicationController.stub! (:user_authentication_required).and_return(true) (which is the filter called before each action that checks whether the user is logged in or not) But it doesn't work. When I do this : class ApplicationController def user_authentication_required return true end end it works fine (but I find it quite dirty to redefine my method that way). Aren't this two solutions supposed to give me the same result ? Is something wrong with my stubbing ? On Mar 6, 3:33 pm, Ivo Dancet [EMAIL PROTECTED] wrote: I think you can also use: post /authentication/login, { :login = user_email, :password = password }, :host = company.example.com Op 5-mrt-08, om 23:30 heeft Bastien het volgende geschreven: I've just begin using rspec stories, and i m encountering some problems. In my application i have different subdomains in which specific users can log in, for example an admin will go to admin.myapp.com/authenticate/login, and an user belonging to a specific company will log in company.myapp.com/authenticate/login, and of course both have a different login process. To perform some actions the user has to be logged in, and this is where the problem comes, how to test these actions ? - Is there a way to set a user as logged in ? (that would definitely be very convenient) So far I have tried to do the following : post /authenticate/login, {:login = user_email, :password = password } but the problem is that it doesn't use the correct subdomain and the login, as expected in that case, fails, so how to define the correct subdomain ? Thank you in advance for your help. ___ rspec-users mailing list [EMAIL PROTECTED] http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] [Stories] Login and subdomain
Thanks for your help. I tried the controller.stub!(...) as well, and it doesn't work. Ivo I totally agree with you and I'll follow your recommendations, thanks. (Would still be nice to know if the stubbing could work or if it's intended not to) On Mar 6, 4:27 pm, Ivo Dancet [EMAIL PROTECTED] wrote: You should not stub the authentication method in a story. The story should test the whole application framework, that way your story might look like this: Given a user from company x When logging in And requesting some page Then the application should do all the stuff it should In the given step you set your host, user name and password and you create that user. In the when steps you make the login request and then you can start doing the stuff you really want to test here as you'll have the session you want at that moment. Regards Ivo Dancet Op 6-mrt-08, om 16:12 heeft Bastien het volgende geschreven: Thanks David, this works just fine. I would rather do some stubbing there if it's possible though. I tried : ApplicationController.stub! (:user_authentication_required).and_return(true) (which is the filter called before each action that checks whether the user is logged in or not) But it doesn't work. When I do this : class ApplicationController def user_authentication_required return true end end it works fine (but I find it quite dirty to redefine my method that way). Aren't this two solutions supposed to give me the same result ? Is something wrong with my stubbing ? On Mar 6, 3:33 pm, Ivo Dancet [EMAIL PROTECTED] wrote: I think you can also use: post /authentication/login, { :login = user_email, :password = password }, :host = company.example.com Op 5-mrt-08, om 23:30 heeft Bastien het volgende geschreven: I've just begin using rspec stories, and i m encountering some problems. In my application i have different subdomains in which specific users can log in, for example an admin will go to admin.myapp.com/authenticate/login, and an user belonging to a specific company will log in company.myapp.com/authenticate/login, and of course both have a different login process. To perform some actions the user has to be logged in, and this is where the problem comes, how to test these actions ? - Is there a way to set a user as logged in ? (that would definitely be very convenient) So far I have tried to do the following : post /authenticate/login, {:login = user_email, :password = password } but the problem is that it doesn't use the correct subdomain and the login, as expected in that case, fails, so how to define the correct subdomain ? Thank you in advance for your help. ___ rspec-users mailing list [EMAIL PROTECTED] http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list [EMAIL PROTECTED] http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users