Wincent Colaiuta
2007-May-24 07:00 UTC
[rspec-users] Specs for ApplicationController, where to put them?
The Rails ApplicationController (app/controllers/application.rb) serves as an abstract superclass for all other controllers in a Rails application and is a good place to put methods and filters which you want all of your controllers to use. In my case I''m using it to provide methods such as "current_user" and "logged_in?" etc. By default, RSpec doesn''t produce a corresponding spec file for this controller. I''ve made a spec file (spec/controllers/application_spec.rb) so that I can test these methods, but I''m not sure if this is the right thing to do. Should I be testing only the non-abstract subclasses instead? Cheers, Wincent
Tim Lucas
2007-May-24 07:18 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 24/05/2007, at 5:00 PM, Wincent Colaiuta wrote:> The Rails ApplicationController (app/controllers/application.rb) > serves as an abstract superclass for all other controllers in a Rails > application and is a good place to put methods and filters which you > want all of your controllers to use. In my case I''m using it to > provide methods such as "current_user" and "logged_in?" etc. > > By default, RSpec doesn''t produce a corresponding spec file for this > controller. > > I''ve made a spec file (spec/controllers/application_spec.rb) so that > I can test these methods, but I''m not sure if this is the right thing > to do. Should I be testing only the non-abstract subclasses instead?I did it a slighty dodgy way (spec/controllers/ application_controller_spec.rb): http://pastie.caboo.se/64123 but nowadays you can probably use a shared spec, like so (require''d from your spec helper): describe "All controllers", :shared => true do it "should redirect to HQ if no subdomains specified" do ... end end and then: describe EventController do it_should_behave_like "All controllers" ... end Not sure how you''d deal with something like skip_before_filter though... -- tim
Wincent Colaiuta
2007-May-24 08:27 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 24/5/2007, a las 9:18, Tim Lucas escribi?:> I did it a slighty dodgy way (spec/controllers/ > application_controller_spec.rb): > http://pastie.caboo.se/64123First, thanks for the advice! Why do you say "dodgy"?> but nowadays you can probably use a shared spec, like so (require''d > from your spec helper):Probably not a bad idea. In that way you''d get confirmation that no subclass is overriding the behaviour of the superclass in unexpected ways. Cheers, Wincent
Joe Van Dyk
2007-May-24 14:31 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 5/24/07, Wincent Colaiuta <win at wincent.com> wrote:> El 24/5/2007, a las 9:18, Tim Lucas escribi?: > > > I did it a slighty dodgy way (spec/controllers/ > > application_controller_spec.rb): > > http://pastie.caboo.se/64123 > > First, thanks for the advice! > > Why do you say "dodgy"? > > > but nowadays you can probably use a shared spec, like so (require''d > > from your spec helper): > > Probably not a bad idea. In that way you''d get confirmation that no > subclass is overriding the behaviour of the superclass in unexpected > ways.I''d vote for shared spec (i.e. CaresAboutLoggingIn) and have that spec test that the controller does the right things. Joe
Anthony Carlos
2007-May-24 19:16 UTC
[rspec-users] Specs for ApplicationController, where to put them?
Tim: I''m sorry, but I''m a newbie and I don''t fully understand. Could you please give me more details? 1. Is the slightly dodgy way completely separate from using a shared spec? 2. What is the appropriate file path and name for your first example regarding a shared spec? Is it RAILS_ROOT/spec/controllers/ all_controllers_spec.rb? 3. Does the event controller spec belong in RAILS_ROOT/spec/ controllers/event_controller_spec.rb? 4. How do you actually fire off the test? Do I have to call get or post inside a do-end block that is attached to it_should_behave_like "All controllers"? e.g., describe EventController do it_should_behave_like "All controllers" do get ''event1'' # just an example action end end 5. Is there any further documentation on it_should_behave_like other than the RDoc? It doesn''t really say too much. Thanks for your help! -Anthony On May 24, 2007, at 3:18 AM, Tim Lucas wrote:> On 24/05/2007, at 5:00 PM, Wincent Colaiuta wrote: > >> The Rails ApplicationController (app/controllers/application.rb) >> serves as an abstract superclass for all other controllers in a Rails >> application and is a good place to put methods and filters which you >> want all of your controllers to use. In my case I''m using it to >> provide methods such as "current_user" and "logged_in?" etc. >> >> By default, RSpec doesn''t produce a corresponding spec file for this >> controller. >> >> I''ve made a spec file (spec/controllers/application_spec.rb) so that >> I can test these methods, but I''m not sure if this is the right thing >> to do. Should I be testing only the non-abstract subclasses instead? > > I did it a slighty dodgy way (spec/controllers/ > application_controller_spec.rb): > http://pastie.caboo.se/64123 > > but nowadays you can probably use a shared spec, like so (require''d > from your spec helper): > > describe "All controllers", :shared => true do > it "should redirect to HQ if no subdomains specified" do > ... > end > end > > and then: > > describe EventController do > it_should_behave_like "All controllers" > ... > end > > Not sure how you''d deal with something like skip_before_filter > though... > > -- tim > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
Anthony Carlos
2007-May-25 15:54 UTC
[rspec-users] Specs for ApplicationController, where to put them?
Hey everyone: I found more information about its_should_behave_like on the documentation index page (duh!). The example shows how a behavior is factored out and put into its own describe block. However, that behavior is still within the same file. I think my problems stem from the fact that I''m using Rails and the ApplicationController is its own separate file. I want to figure out where specs for ApplicationController are supposed to live, and how to call them. Here''s what I''ve tried: Created /spec/controllers/application_controller_spec.rb: require File.dirname(__FILE__) + ''/../spec_helper'' describe "All controllers", :shared => true do it "should respond to authenticate" do controller.should respond_to(:authenticate) end it "should respond to current_user" do controller.should respond_to(:current_user) end end Created /spec/controllers/concrete_controller_spec.rb: require File.dirname(__FILE__) + ''/../spec_helper'' describe ConcreteController do it_should_behave_like "All controllers" end Then, I ran rake spec:autotest, and got the following output: ConcreteController - should respond to current_user - should respond to authenticate But, if I update and save concrete_controller_spec.rb, autotest tries to run that spec on its own and I get "Shared Behaviour ''All controllers'' can not be found (RuntimeError)". So, I added a conditional require statement at the top of concrete_controller_spec.rb: require File.dirname(__FILE__) + ''/application_controller_spec'' unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") That got rid of the Shared Behaviour can not be found error. Is this a suitable workaround, or is it too dodgy? So, things are peachy except that I''m only checking that all controllers respond to certain methods. I want to test the logic of these methods, so I added the following example to my All Controllers behavior: it "should flash notice when session[:current_user_id] does not exist" do session[:current_user_id] = nil controller.authenticate flash[:notice].should == ''Please login.'' end My problem now, is that I get a nil object error. Specifically, in application.rb, I''m trying to call request.parameters and request is nil. It seems that request is not part of the context anymore since I moved the behavior out to a separate file. How do I regain access to request, response, assigns, flash, and session? Thanks for your help! -Anthony On May 24, 2007, at 3:16 PM, Anthony Carlos wrote:> Tim: > > I''m sorry, but I''m a newbie and I don''t fully understand. Could you > please give me more details? > > 1. Is the slightly dodgy way completely separate from using a shared > spec? > 2. What is the appropriate file path and name for your first example > regarding a shared spec? Is it RAILS_ROOT/spec/controllers/ > all_controllers_spec.rb? > 3. Does the event controller spec belong in RAILS_ROOT/spec/ > controllers/event_controller_spec.rb? > 4. How do you actually fire off the test? Do I have to call get or > post inside a do-end block that is attached to it_should_behave_like > "All controllers"? > > e.g., > > describe EventController do > it_should_behave_like "All controllers" do > get ''event1'' # just an example action > end > end > > 5. Is there any further documentation on it_should_behave_like other > than the RDoc? It doesn''t really say too much. > > Thanks for your help! > > -Anthony > > On May 24, 2007, at 3:18 AM, Tim Lucas wrote: > >> On 24/05/2007, at 5:00 PM, Wincent Colaiuta wrote: >> >>> The Rails ApplicationController (app/controllers/application.rb) >>> serves as an abstract superclass for all other controllers in a >>> Rails >>> application and is a good place to put methods and filters which you >>> want all of your controllers to use. In my case I''m using it to >>> provide methods such as "current_user" and "logged_in?" etc. >>> >>> By default, RSpec doesn''t produce a corresponding spec file for this >>> controller. >>> >>> I''ve made a spec file (spec/controllers/application_spec.rb) so that >>> I can test these methods, but I''m not sure if this is the right >>> thing >>> to do. Should I be testing only the non-abstract subclasses instead? >> >> I did it a slighty dodgy way (spec/controllers/ >> application_controller_spec.rb): >> http://pastie.caboo.se/64123 >> >> but nowadays you can probably use a shared spec, like so (require''d >> from your spec helper): >> >> describe "All controllers", :shared => true do >> it "should redirect to HQ if no subdomains specified" do >> ... >> end >> end >> >> and then: >> >> describe EventController do >> it_should_behave_like "All controllers" >> ... >> end >> >> Not sure how you''d deal with something like skip_before_filter >> though... >> >> -- tim >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
Wincent Colaiuta
2007-May-29 14:50 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 25/5/2007, a las 17:54, Anthony Carlos escribi?:> I found more information about its_should_behave_like on the > documentation index page (duh!). The example shows how a behavior is > factored out and put into its own describe block. However, that > behavior is still within the same file. I think my problems stem from > the fact that I''m using Rails and the ApplicationController is its > own separate file. > > But, if I update and save concrete_controller_spec.rb, autotest tries > to run that spec on its own and I get "Shared Behaviour ''All > controllers'' can not be found (RuntimeError)". So, I added a > conditional require statement at the top of > concrete_controller_spec.rb: > > require File.dirname(__FILE__) + ''/application_controller_spec'' > unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") > > That got rid of the Shared Behaviour can not be found error. Is this > a suitable workaround, or is it too dodgy?I faced a similar issue with shared behaviours. If you stick your shared behaviour at the top of a file and only use it within that same file then there are no problems, but if you want to put a shared behaviour in your spec_helper.rb or some other shared file so that it can be used from other files, then you run into the problem that you describe. As a temporary workaround I''m bracketing the shared behaviour to make sure that it only gets evaluated once, similar to how you''ve done, but it does indeed feel dodgy (reminds me of conditionally including C header files). What do you think about the following as possible solutions? 1. Change spec/dsl/behaviour.rb to simply skip duplicate definitions rather than raising an exception. Obviously, the risk here is that someone would accidentally name two shared behaviours the same way without realizing it, and only the first encountered one would be evaluated. 2. Add a ":global" option for shared behaviours which are intended to be included globally; only these behaviours would be skipped when evaluated multiple times, and normal shared behaviours would continue to exhibit the existing behaviour: describe ''All controllers'', :global => true do .. end 3. A variation on the previous suggestion: instead of using ":global" and ":shared" as alternatives, continue to use ":shared" in all cases, but allow ":global" to be passed as an additional option: describe ''All controllers'', :shared => true, :global => true do .. end Of these solutions, I think I like the second one the best. Any other suggestions? Cheers, Wincent
Tim Lucas
2007-May-29 23:13 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 25/05/2007, at 5:16 AM, Anthony Carlos wrote:> I''m sorry, but I''m a newbie and I don''t fully understand. Could you > please give me more details? > > 1. Is the slightly dodgy way completely separate from using a shared > spec?Yeah, it''s completely separate. The pastie[1] is the complete spec. This only tests your ApplicationController though.> 2. What is the appropriate file path and name for your first example > regarding a shared spec? Is it RAILS_ROOT/spec/controllers/ > all_controllers_spec.rb? > 3. Does the event controller spec belong in RAILS_ROOT/spec/ > controllers/event_controller_spec.rb? > 4. How do you actually fire off the test? Do I have to call get or > post inside a do-end block that is attached to it_should_behave_like > "All controllers"? > > e.g., > > describe EventController do > it_should_behave_like "All controllers" do > get ''event1'' # just an example action > end > end > > 5. Is there any further documentation on it_should_behave_like other > than the RDoc? It doesn''t really say too much.I haven''t actually used shared specs... so if you figure out please do share! -- tim [1] http://pastie.caboo.se/64123
Luis Lavena
2007-May-29 23:37 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 5/29/07, Wincent Colaiuta <win at wincent.com> wrote: [...]> > 2. Add a ":global" option for shared behaviours which are intended to > be included globally; only these behaviours would be skipped when > evaluated multiple times, and normal shared behaviours would continue > to exhibit the existing behaviour: > > describe ''All controllers'', :global => true do .. end > > 3. A variation on the previous suggestion: instead of using ":global" > and ":shared" as alternatives, continue to use ":shared" in all > cases, but allow ":global" to be passed as an additional option: > > describe ''All controllers'', :shared => true, :global => true do .. end > > Of these solutions, I think I like the second one the best. Any other > suggestions? >describe ''All controllers'', :shared => :global do ... end Since that will be shared anyway, what change is "context" (no pun intended). -- Luis Lavena Multimedia systems - Leaders are made, they are not born. They are made by hard effort, which is the price which all of us must pay to achieve any goal that is worthwhile. Vince Lombardi
David Chelimsky
2007-May-29 23:52 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 5/25/07, Anthony Carlos <anthony at digitalphenom.com> wrote:> Hey everyone: > > I found more information about its_should_behave_like on the > documentation index page (duh!). The example shows how a behavior is > factored out and put into its own describe block. However, that > behavior is still within the same file. I think my problems stem from > the fact that I''m using Rails and the ApplicationController is its > own separate file. > > I want to figure out where specs for ApplicationController are > supposed to live, and how to call them. > > Here''s what I''ve tried: > > Created /spec/controllers/application_controller_spec.rb: > > require File.dirname(__FILE__) + ''/../spec_helper'' > describe "All controllers", :shared => true do > it "should respond to authenticate" do > controller.should respond_to(:authenticate) > end > it "should respond to current_user" do > controller.should respond_to(:current_user) > end > end > > Created /spec/controllers/concrete_controller_spec.rb: > > require File.dirname(__FILE__) + ''/../spec_helper'' > describe ConcreteController do > it_should_behave_like "All controllers" > end > > Then, I ran rake spec:autotest, and got the following output: > ConcreteController > - should respond to current_user > - should respond to authenticate > > But, if I update and save concrete_controller_spec.rb, autotest tries > to run that spec on its own and I get "Shared Behaviour ''All > controllers'' can not be found (RuntimeError)". So, I added a > conditional require statement at the top of concrete_controller_spec.rb: > > require File.dirname(__FILE__) + ''/application_controller_spec'' > unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") > > That got rid of the Shared Behaviour can not be found error. Is this > a suitable workaround, or is it too dodgy?I don''t view that as a workaround at all. You should always be able to run any example file by itself. If such a file relies on other files, then it should require them. Another thing you could do is to put shared behaviours in spec/shared/ and require everything in spec/shared from spec/spec_helper.> > So, things are peachy except that I''m only checking that all > controllers respond to certain methods. I want to test the logic of > these methods, so I added the following example to my All Controllers > behavior: > > it "should flash notice when session[:current_user_id] does not > exist" do > session[:current_user_id] = nil > controller.authenticate > flash[:notice].should == ''Please login.'' > end > > My problem now, is that I get a nil object error. Specifically, in > application.rb, I''m trying to call request.parameters and request is > nil. It seems that request is not part of the context anymore since I > moved the behavior out to a separate file. How do I regain access to > request, response, assigns, flash, and session?The fact that the shared examples are in another file should have no bearing on whether they have runtime access to whatever is in the behaviours that include them. This all sounds odd to me. Can you post a backtrace please?> > Thanks for your help! > > -Anthony > > > On May 24, 2007, at 3:16 PM, Anthony Carlos wrote: > > > Tim: > > > > I''m sorry, but I''m a newbie and I don''t fully understand. Could you > > please give me more details? > > > > 1. Is the slightly dodgy way completely separate from using a shared > > spec? > > 2. What is the appropriate file path and name for your first example > > regarding a shared spec? Is it RAILS_ROOT/spec/controllers/ > > all_controllers_spec.rb? > > 3. Does the event controller spec belong in RAILS_ROOT/spec/ > > controllers/event_controller_spec.rb? > > 4. How do you actually fire off the test? Do I have to call get or > > post inside a do-end block that is attached to it_should_behave_like > > "All controllers"? > > > > e.g., > > > > describe EventController do > > it_should_behave_like "All controllers" do > > get ''event1'' # just an example action > > end > > end > > > > 5. Is there any further documentation on it_should_behave_like other > > than the RDoc? It doesn''t really say too much. > > > > Thanks for your help! > > > > -Anthony > > > > On May 24, 2007, at 3:18 AM, Tim Lucas wrote: > > > >> On 24/05/2007, at 5:00 PM, Wincent Colaiuta wrote: > >> > >>> The Rails ApplicationController (app/controllers/application.rb) > >>> serves as an abstract superclass for all other controllers in a > >>> Rails > >>> application and is a good place to put methods and filters which you > >>> want all of your controllers to use. In my case I''m using it to > >>> provide methods such as "current_user" and "logged_in?" etc. > >>> > >>> By default, RSpec doesn''t produce a corresponding spec file for this > >>> controller. > >>> > >>> I''ve made a spec file (spec/controllers/application_spec.rb) so that > >>> I can test these methods, but I''m not sure if this is the right > >>> thing > >>> to do. Should I be testing only the non-abstract subclasses instead? > >> > >> I did it a slighty dodgy way (spec/controllers/ > >> application_controller_spec.rb): > >> http://pastie.caboo.se/64123 > >> > >> but nowadays you can probably use a shared spec, like so (require''d > >> from your spec helper): > >> > >> describe "All controllers", :shared => true do > >> it "should redirect to HQ if no subdomains specified" do > >> ... > >> end > >> end > >> > >> and then: > >> > >> describe EventController do > >> it_should_behave_like "All controllers" > >> ... > >> end > >> > >> Not sure how you''d deal with something like skip_before_filter > >> though... > >> > >> -- tim > >> > >> _______________________________________________ > >> rspec-users mailing list > >> rspec-users at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/rspec-users > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Wincent Colaiuta
2007-May-30 18:36 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 30/5/2007, a las 1:52, David Chelimsky escribi?:> I don''t view that as a workaround at all. You should always be able to > run any example file by itself. If such a file relies on other files, > then it should require them. > > Another thing you could do is to put shared behaviours in spec/shared/ > and require everything in spec/shared from spec/spec_helper. > > The fact that the shared examples are in another file should have no > bearing on whether they have runtime access to whatever is in the > behaviours that include them. This all sounds odd to me. Can you post > a backtrace please?I''ve been looking at the code for this and was a bit puzzled by the following in lib/spec/dsl/behaviour.rb def add_shared_behaviour(behaviour) return if behaviour.equal?(found_behaviour = find_shared_behaviour(behaviour.description)) ... The intent is evidently to skip over previously instantiated shared behaviours, but I can''t think of too many real-world cases where the object identity test (equal?) will succeed. About the only place it will succeed is in the spec (spec/spec/dsl/shared_behaviour_spec.rb): it "should NOT complain when adding a the same shared behaviour again (i.e. file gets reloaded)" do behaviour = behaviour_class.new("shared behaviour") {} behaviour_class.add_shared_behaviour(behaviour) behaviour_class.add_shared_behaviour(behaviour) end Here the exact same instance is being added and it is naturally skipped. But try adding something like the following to your spec_helper.rb file and watch the exceptions being raised when you do a "rake spec": describe "foobar", :shared => true do end Here every spec which includes the spec_helper.rb file will trigger an ArgumentError because the same shared behaviour gets re-evaluated over and over again and "found_behaviour" is set each time: def add_shared_behaviour(behaviour) return if behaviour.equal?(found_behaviour = find_shared_behaviour(behaviour.description)) raise ArgumentError.new("Shared Behaviour ''# {behaviour.description}'' already exists") if found_behaviour I think the solution here is to relax the equality comparison, use "==" instead of "equal?": Index: rspec/lib/spec/dsl/behaviour.rb ==================================================================--- rspec/lib/spec/dsl/behaviour.rb (revision 2060) +++ rspec/lib/spec/dsl/behaviour.rb (working copy) @@ -6,7 +6,7 @@ class << self def add_shared_behaviour(behaviour) - return if behaviour.equal?(found_behaviour = find_shared_behaviour(behaviour.description)) + return if behaviour == (found_behaviour = find_shared_behaviour(behaviour.description)) raise ArgumentError.new("Shared Behaviour ''# {behaviour.description}'' already exists") if found_behaviour shared_behaviours << behaviour end I''ve made this change against the RSpec trunk and "rake pre_commit" passes all specs. But I actually think that there might be some mistakes in the specs themselves: it "should NOT complain when adding a the same shared behaviour again (i.e. file gets reloaded)" do behaviour = behaviour_class.new("shared behaviour") {} behaviour_class.add_shared_behaviour(behaviour) behaviour_class.add_shared_behaviour(behaviour) end The two problems I see here are: - behaviour isn''t actually a shared behaviour; you''d need to use "make_shared_behaviour" for that - adding the exact same instance as in the spec is not the same as what happens when the file gets reloaded, because when you reload a file, the "describe" block is actually going to instantiate a new (different) Behaviour instance very time I could change this spec to make it correct but then the following spec will no longer pass: it "should complain when adding a second shared behaviour with the same description" do make_shared_behaviour("shared behaviour") {} lambda { make_shared_behaviour("shared behaviour") {} }.should raise_error(ArgumentError) end It seems to me that to get the correct behaviour this spec will have to be jettisoned... It''s not possible to have shared behaviours in reloaded files without relaxing the requirement above... Thoughts? Cheers, Wincent
Anthony Carlos
2007-May-30 20:15 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On May 29, 2007, at 7:52 PM, David Chelimsky wrote:> I don''t view that as a workaround at all. You should always be able to > run any example file by itself. If such a file relies on other files, > then it should require them. > > Another thing you could do is to put shared behaviours in spec/shared/ > and require everything in spec/shared from spec/spec_helper.Thanks for the but of wisdom. It really helps to understand your intent!> The fact that the shared examples are in another file should have no > bearing on whether they have runtime access to whatever is in the > behaviours that include them. This all sounds odd to me. Can you post > a backtrace please?I''ll see if I can reconstruct the situation and post something tonight or tomorrow. Thanks! -Anthony
David Chelimsky
2007-May-30 21:11 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 5/30/07, Wincent Colaiuta <win at wincent.com> wrote:> El 30/5/2007, a las 1:52, David Chelimsky escribi?: > > > I don''t view that as a workaround at all. You should always be able to > > run any example file by itself. If such a file relies on other files, > > then it should require them. > > > > Another thing you could do is to put shared behaviours in spec/shared/ > > and require everything in spec/shared from spec/spec_helper. > > > > The fact that the shared examples are in another file should have no > > bearing on whether they have runtime access to whatever is in the > > behaviours that include them. This all sounds odd to me. Can you post > > a backtrace please? > > I''ve been looking at the code for this and was a bit puzzled by the > following in lib/spec/dsl/behaviour.rb > > def add_shared_behaviour(behaviour) > return if behaviour.equal?(found_behaviour > find_shared_behaviour(behaviour.description)) > ... > > The intent is evidently to skip over previously instantiated shared > behaviours, but I can''t think of too many real-world cases where the > object identity test (equal?) will succeed. About the only place it > will succeed is in the spec (spec/spec/dsl/shared_behaviour_spec.rb): > > it "should NOT complain when adding a the same shared > behaviour again (i.e. file gets reloaded)" do > behaviour = behaviour_class.new("shared behaviour") {} > behaviour_class.add_shared_behaviour(behaviour) > behaviour_class.add_shared_behaviour(behaviour) > end > > Here the exact same instance is being added and it is naturally > skipped. But try adding something like the following to your > spec_helper.rb file and watch the exceptions being raised when you do > a "rake spec": > > describe "foobar", :shared => true do > end > > Here every spec which includes the spec_helper.rb file will trigger > an ArgumentError because the same shared behaviour gets re-evaluated > over and over again and "found_behaviour" is set each time: > > def add_shared_behaviour(behaviour) > return if behaviour.equal?(found_behaviour > find_shared_behaviour(behaviour.description)) > raise ArgumentError.new("Shared Behaviour ''# > {behaviour.description}'' already exists") if found_behaviour > > I think the solution here is to relax the equality comparison, use > "==" instead of "equal?": > > Index: rspec/lib/spec/dsl/behaviour.rb > ==================================================================> --- rspec/lib/spec/dsl/behaviour.rb (revision 2060) > +++ rspec/lib/spec/dsl/behaviour.rb (working copy) > @@ -6,7 +6,7 @@ > class << self > def add_shared_behaviour(behaviour) > - return if behaviour.equal?(found_behaviour > find_shared_behaviour(behaviour.description)) > + return if behaviour == (found_behaviour > find_shared_behaviour(behaviour.description)) > raise ArgumentError.new("Shared Behaviour ''# > {behaviour.description}'' already exists") if found_behaviour > shared_behaviours << behaviour > end > > I''ve made this change against the RSpec trunk and "rake pre_commit" > passes all specs. But I actually think that there might be some > mistakes in the specs themselves: > > it "should NOT complain when adding a the same shared > behaviour again (i.e. file gets reloaded)" do > behaviour = behaviour_class.new("shared behaviour") {} > behaviour_class.add_shared_behaviour(behaviour) > behaviour_class.add_shared_behaviour(behaviour) > end > > The two problems I see here are: > > - behaviour isn''t actually a shared behaviour; you''d need to use > "make_shared_behaviour" for that > > - adding the exact same instance as in the spec is not the same as > what happens when the file gets reloaded, because when you reload a > file, the "describe" block is actually going to instantiate a new > (different) Behaviour instance very time > > I could change this spec to make it correct but then the following > spec will no longer pass: > > it "should complain when adding a second shared behaviour with > the same description" do > make_shared_behaviour("shared behaviour") {} > lambda { make_shared_behaviour("shared behaviour") > {} }.should raise_error(ArgumentError) > end > > It seems to me that to get the correct behaviour this spec will have > to be jettisoned... It''s not possible to have shared behaviours in > reloaded files without relaxing the requirement above... > > Thoughts?I think you''re spot on about all of this. I''m thinking that a simple solution would be that each time a shared behaviour is registered, the location of its definition can be registered as well. Then we can ignore the ones defined in the same place when a file gets reloaded, but still complain when another one is defined with the same name from a different location. WDYT?> > Cheers, > Wincent > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Wincent Colaiuta
2007-May-30 22:35 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 30/5/2007, a las 23:11, David Chelimsky escribi?:> I think you''re spot on about all of this. I''m thinking that a simple > solution would be that each time a shared behaviour is registered, the > location of its definition can be registered as well. Then we can > ignore the ones defined in the same place when a file gets reloaded, > but still complain when another one is defined with the same name from > a different location. > > WDYT?Would be great -- it would basically capture the intent of your current implementation -- but how would you get the location of its definition? Cheers, Wincent
David Chelimsky
2007-May-30 22:51 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 5/30/07, Wincent Colaiuta <win at wincent.com> wrote:> El 30/5/2007, a las 23:11, David Chelimsky escribi?: > > > I think you''re spot on about all of this. I''m thinking that a simple > > solution would be that each time a shared behaviour is registered, the > > location of its definition can be registered as well. Then we can > > ignore the ones defined in the same place when a file gets reloaded, > > but still complain when another one is defined with the same name from > > a different location. > > > > WDYT? > > Would be great -- it would basically capture the intent of your > current implementation -- but how would you get the location of its > definition?By inspecting caller. We do this already in building up the backtrace. I''ll pursue this soon. Cheers, David> > Cheers, > Wincent > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Wincent Colaiuta
2007-May-31 05:27 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 31/5/2007, a las 0:51, David Chelimsky escribi?:> On 5/30/07, Wincent Colaiuta <win at wincent.com> wrote: >> El 30/5/2007, a las 23:11, David Chelimsky escribi?: >> >>> I think you''re spot on about all of this. I''m thinking that a simple >>> solution would be that each time a shared behaviour is >>> registered, the >>> location of its definition can be registered as well. Then we can >>> ignore the ones defined in the same place when a file gets reloaded, >>> but still complain when another one is defined with the same name >>> from >>> a different location. >>> >>> WDYT? >> >> Would be great -- it would basically capture the intent of your >> current implementation -- but how would you get the location of its >> definition? > > By inspecting caller. We do this already in building up the backtrace. > I''ll pursue this soon.Ah, of course... I didn''t even realize that Kernel#caller was in the Ruby core... That will definitely work then. Cheers, Wincent
Wincent Colaiuta
2007-May-31 07:25 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 31/5/2007, a las 7:27, Wincent Colaiuta escribi?:> El 31/5/2007, a las 0:51, David Chelimsky escribi?: > >> On 5/30/07, Wincent Colaiuta <win at wincent.com> wrote: >>> El 30/5/2007, a las 23:11, David Chelimsky escribi?: >>> >>>> I think you''re spot on about all of this. I''m thinking that a >>>> simple >>>> solution would be that each time a shared behaviour is >>>> registered, the >>>> location of its definition can be registered as well. Then we can >>>> ignore the ones defined in the same place when a file gets >>>> reloaded, >>>> but still complain when another one is defined with the same name >>>> from >>>> a different location. >>>> >>>> WDYT? >>> >>> Would be great -- it would basically capture the intent of your >>> current implementation -- but how would you get the location of its >>> definition? >> >> By inspecting caller. We do this already in building up the >> backtrace. >> I''ll pursue this soon. > > Ah, of course... I didn''t even realize that Kernel#caller was in the > Ruby core... That will definitely work then.The following seems to work. Some things to note: - the code in the trunk (as at r2061) allows "found_behaviour" to be nil and adds it to the shared_behaviours array, which seems wrong; this patch fixes that - the patch uses the already-present :spec_path info (extracted using Kernel#caller in the "describe" method) as this seems the cleanest way of geting location info - I''ve added some specs to confirm that things work... note that because the :spec_path info gets put in place only when using "describe" a couple of the specs have to directly use the "describe" method rather than the "make_shared_behaviour" helper method - fixed a typo in one of the examples ("when adding a the same") Is this something like what you had in mind? Cheers, Wincent Index: rspec/lib/spec/dsl/behaviour.rb ==================================================================--- rspec/lib/spec/dsl/behaviour.rb (revision 2061) +++ rspec/lib/spec/dsl/behaviour.rb (working copy) @@ -7,6 +7,7 @@ class << self def add_shared_behaviour(behaviour) return if behaviour.equal?(found_behaviour = find_shared_behaviour(behaviour.description)) + return if found_behaviour and behaviour.description [:spec_path] == found_behaviour.description[:spec_path] raise ArgumentError.new("Shared Behaviour ''# {behaviour.description}'' already exists") if found_behaviour shared_behaviours << behaviour end Index: rspec/spec/spec/dsl/shared_behaviour_spec.rb ==================================================================--- rspec/spec/spec/dsl/shared_behaviour_spec.rb (revision 2061) +++ rspec/spec/spec/dsl/shared_behaviour_spec.rb (working copy) @@ -74,16 +74,23 @@ end it "should complain when adding a second shared behaviour with the same description" do - make_shared_behaviour("shared behaviour") {} - lambda { make_shared_behaviour("shared behaviour") {} }.should raise_error(ArgumentError) + describe "shared behaviour", :shared => true do + end + lambda { describe "shared behaviour", :shared => true do + end }.should raise_error(ArgumentError) end - it "should NOT complain when adding a the same shared behaviour again (i.e. file gets reloaded)" do - behaviour = behaviour_class.new("shared behaviour") {} - behaviour_class.add_shared_behaviour(behaviour) - behaviour_class.add_shared_behaviour(behaviour) + it "should NOT complain when adding the same shared behaviour instance again" do + shared_behaviour = make_shared_behaviour("shared behaviour") {} + behaviour_class.add_shared_behaviour(shared_behaviour) + behaviour_class.add_shared_behaviour(shared_behaviour) end + it "should NOT complain when adding the same shared behaviour again (i.e. file gets reloaded)" do + lambda { 2.times { describe "shared behaviour", :shared => true do + end } }.should_not raise_error(ArgumentError) + end + it "should add examples to current behaviour when calling it_should_behave_like" do shared_behaviour = make_shared_behaviour("shared behaviour") {} shared_behaviour.it("shared example") {}
Wincent Colaiuta
2007-May-31 07:35 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 31/5/2007, a las 9:25, Wincent Colaiuta escribi?:> - the code in the trunk (as at r2061) allows "found_behaviour" to be > nil and adds it to the shared_behaviours array, which seems wrong; > this patch fixes thatForget I said that! I was thinking about something else. W
Wincent Colaiuta
2007-May-31 08:59 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 30/5/2007, a las 1:52, David Chelimsky escribi?:> Another thing you could do is to put shared behaviours in spec/shared/ > and require everything in spec/shared from spec/spec_helper.Do you think it''s worth updating the test mappings in rspec_on_rails/ lib/autotest/rails_rspec.rb to reflect this convention (ie. run all specs whenever anything in spec/shared gets touched)? I also wonder if this is enough of a convention, perhaps rspec/lib/ autotest/rspec.rb should be updated as well. Speaking of which, I see that currently it only has one-to-one test mappings set up but it should probably run all the specs whenever spec_helper.rb is updated. Let me know if you want a patch for that. Cheers, Wincent
David Chelimsky
2007-May-31 10:46 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 5/31/07, Wincent Colaiuta <win at wincent.com> wrote:> El 31/5/2007, a las 7:27, Wincent Colaiuta escribi?: > > > El 31/5/2007, a las 0:51, David Chelimsky escribi?: > > > >> On 5/30/07, Wincent Colaiuta <win at wincent.com> wrote: > >>> El 30/5/2007, a las 23:11, David Chelimsky escribi?: > >>> > >>>> I think you''re spot on about all of this. I''m thinking that a > >>>> simple > >>>> solution would be that each time a shared behaviour is > >>>> registered, the > >>>> location of its definition can be registered as well. Then we can > >>>> ignore the ones defined in the same place when a file gets > >>>> reloaded, > >>>> but still complain when another one is defined with the same name > >>>> from > >>>> a different location. > >>>> > >>>> WDYT? > >>> > >>> Would be great -- it would basically capture the intent of your > >>> current implementation -- but how would you get the location of its > >>> definition? > >> > >> By inspecting caller. We do this already in building up the > >> backtrace. > >> I''ll pursue this soon. > > > > Ah, of course... I didn''t even realize that Kernel#caller was in the > > Ruby core... That will definitely work then. > > The following seems to work. Some things to note: > > - the code in the trunk (as at r2061) allows "found_behaviour" to be > nil and adds it to the shared_behaviours array, which seems wrong; > this patch fixes that > > - the patch uses the already-present :spec_path info (extracted using > Kernel#caller in the "describe" method) as this seems the cleanest > way of geting location info > > - I''ve added some specs to confirm that things work... note that > because the :spec_path info gets put in place only when using > "describe" a couple of the specs have to directly use the "describe" > method rather than the "make_shared_behaviour" helper method > > - fixed a typo in one of the examples ("when adding a the same") > > Is this something like what you had in mind? > > Cheers, > Wincent > > Index: rspec/lib/spec/dsl/behaviour.rb > ==================================================================> --- rspec/lib/spec/dsl/behaviour.rb (revision 2061) > +++ rspec/lib/spec/dsl/behaviour.rb (working copy) > @@ -7,6 +7,7 @@ > class << self > def add_shared_behaviour(behaviour) > return if behaviour.equal?(found_behaviour > find_shared_behaviour(behaviour.description)) > + return if found_behaviour and behaviour.description > [:spec_path] == found_behaviour.description[:spec_path] > raise ArgumentError.new("Shared Behaviour ''# > {behaviour.description}'' already exists") if found_behaviour > shared_behaviours << behaviour > end > Index: rspec/spec/spec/dsl/shared_behaviour_spec.rb > ==================================================================> --- rspec/spec/spec/dsl/shared_behaviour_spec.rb (revision 2061) > +++ rspec/spec/spec/dsl/shared_behaviour_spec.rb (working copy) > @@ -74,16 +74,23 @@ > end > it "should complain when adding a second shared behaviour > with the same description" do > - make_shared_behaviour("shared behaviour") {} > - lambda { make_shared_behaviour("shared behaviour") > {} }.should raise_error(ArgumentError) > + describe "shared behaviour", :shared => true do > + end > + lambda { describe "shared behaviour", :shared => true do > + end }.should raise_error(ArgumentError) > end > - it "should NOT complain when adding a the same shared > behaviour again (i.e. file gets reloaded)" do > - behaviour = behaviour_class.new("shared behaviour") {} > - behaviour_class.add_shared_behaviour(behaviour) > - behaviour_class.add_shared_behaviour(behaviour) > + it "should NOT complain when adding the same shared behaviour > instance again" do > + shared_behaviour = make_shared_behaviour("shared behaviour") {} > + behaviour_class.add_shared_behaviour(shared_behaviour) > + behaviour_class.add_shared_behaviour(shared_behaviour) > end > + it "should NOT complain when adding the same shared behaviour > again (i.e. file gets reloaded)" do > + lambda { 2.times { describe "shared behaviour", :shared => > true do > + end } }.should_not raise_error(ArgumentError) > + end > + > it "should add examples to current behaviour when calling > it_should_behave_like" do > shared_behaviour = make_shared_behaviour("shared > behaviour") {} > shared_behaviour.it("shared example") {}Please post this in the tracker: http://rubyforge.org/tracker/?atid=3151&group_id=797&func=browse.> > > > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
David Chelimsky
2007-May-31 10:47 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 5/31/07, Wincent Colaiuta <win at wincent.com> wrote:> El 30/5/2007, a las 1:52, David Chelimsky escribi?: > > > Another thing you could do is to put shared behaviours in spec/shared/ > > and require everything in spec/shared from spec/spec_helper. > > Do you think it''s worth updating the test mappings in rspec_on_rails/ > lib/autotest/rails_rspec.rb to reflect this convention (ie. run all > specs whenever anything in spec/shared gets touched)? > > I also wonder if this is enough of a convention, perhaps rspec/lib/ > autotest/rspec.rb should be updated as well. Speaking of which, I see > that currently it only has one-to-one test mappings set up but it > should probably run all the specs whenever spec_helper.rb is updated. > Let me know if you want a patch for that.Sounds like a good idea - please post to the tracker: http://rubyforge.org/tracker/?atid=3151&group_id=797&func=browse> > Cheers, > Wincent > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Wincent Colaiuta
2007-May-31 14:42 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 31/5/2007, a las 12:46, David Chelimsky escribi?:>> Index: rspec/lib/spec/dsl/behaviour.rb >> ==================================================================>> --- rspec/lib/spec/dsl/behaviour.rb (revision 2061) >> +++ rspec/lib/spec/dsl/behaviour.rb (working copy) >> @@ -7,6 +7,7 @@ >> class << self >> def add_shared_behaviour(behaviour) >> return if behaviour.equal?(found_behaviour >> find_shared_behaviour(behaviour.description)) >> + return if found_behaviour and behaviour.description >> [:spec_path] == found_behaviour.description[:spec_path] >> raise ArgumentError.new("Shared Behaviour ''# >> {behaviour.description}'' already exists") if found_behaviour >> shared_behaviours << behaviour >> end >> Index: rspec/spec/spec/dsl/shared_behaviour_spec.rb >> ==================================================================>> --- rspec/spec/spec/dsl/shared_behaviour_spec.rb (revision >> 2061) >> +++ rspec/spec/spec/dsl/shared_behaviour_spec.rb (working >> copy) >> @@ -74,16 +74,23 @@ >> end >> it "should complain when adding a second shared behaviour >> with the same description" do >> - make_shared_behaviour("shared behaviour") {} >> - lambda { make_shared_behaviour("shared behaviour") >> {} }.should raise_error(ArgumentError) >> + describe "shared behaviour", :shared => true do >> + end >> + lambda { describe "shared behaviour", :shared => true do >> + end }.should raise_error(ArgumentError) >> end >> - it "should NOT complain when adding a the same shared >> behaviour again (i.e. file gets reloaded)" do >> - behaviour = behaviour_class.new("shared behaviour") {} >> - behaviour_class.add_shared_behaviour(behaviour) >> - behaviour_class.add_shared_behaviour(behaviour) >> + it "should NOT complain when adding the same shared behaviour >> instance again" do >> + shared_behaviour = make_shared_behaviour("shared >> behaviour") {} >> + behaviour_class.add_shared_behaviour(shared_behaviour) >> + behaviour_class.add_shared_behaviour(shared_behaviour) >> end >> + it "should NOT complain when adding the same shared behaviour >> again (i.e. file gets reloaded)" do >> + lambda { 2.times { describe "shared behaviour", :shared => >> true do >> + end } }.should_not raise_error(ArgumentError) >> + end >> + >> it "should add examples to current behaviour when calling >> it_should_behave_like" do >> shared_behaviour = make_shared_behaviour("shared >> behaviour") {} >> shared_behaviour.it("shared example") {} > > Please post this in the tracker: > http://rubyforge.org/tracker/?atid=3151&group_id=797&func=browse.Ok, done: http://rubyforge.org/tracker/index.php? func=detail&aid=11252&group_id=797&atid=3151 Cheers, Wincent
Wincent Colaiuta
2007-May-31 14:42 UTC
[rspec-users] Specs for ApplicationController, where to put them?
El 31/5/2007, a las 12:47, David Chelimsky escribi?:> On 5/31/07, Wincent Colaiuta <win at wincent.com> wrote: >> El 30/5/2007, a las 1:52, David Chelimsky escribi?: >> >>> Another thing you could do is to put shared behaviours in spec/ >>> shared/ >>> and require everything in spec/shared from spec/spec_helper. >> >> Do you think it''s worth updating the test mappings in rspec_on_rails/ >> lib/autotest/rails_rspec.rb to reflect this convention (ie. run all >> specs whenever anything in spec/shared gets touched)? >> >> I also wonder if this is enough of a convention, perhaps rspec/lib/ >> autotest/rspec.rb should be updated as well. Speaking of which, I see >> that currently it only has one-to-one test mappings set up but it >> should probably run all the specs whenever spec_helper.rb is updated. >> Let me know if you want a patch for that. > > Sounds like a good idea - please post to the tracker: > http://rubyforge.org/tracker/?atid=3151&group_id=797&func=browseOk, done: http://rubyforge.org/tracker/index.php? func=detail&aid=11253&group_id=797&atid=3151 Cheers, Wincent
Anthony Carlos
2007-Jun-01 22:20 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On May 29, 2007, at 7:52 PM, David Chelimsky wrote:>> My problem now, is that I get a nil object error. Specifically, in >> application.rb, I''m trying to call request.parameters and request is >> nil. It seems that request is not part of the context anymore since I >> moved the behavior out to a separate file. How do I regain access to >> request, response, assigns, flash, and session? > > The fact that the shared examples are in another file should have no > bearing on whether they have runtime access to whatever is in the > behaviours that include them. This all sounds odd to me. Can you post > a backtrace please?David: Here''s the output from rake spec:autotest: : QuestionnairesController - should flash notice when session[:current_user_id] does not exist (ERROR - 1) - should return true when session[:current_user_id] exists - should respond to current_user - should respond to authenticate 1) NoMethodError in ''QuestionnairesController should flash notice when session[:current_user_id] does not exist'' You have a nil object when you didn''t expect it! The error occurred while evaluating nil.parameters /Users/aec/ror/aca/aca_trunk/config/../app/controllers/application.rb: 11:in `authenticate'' ./spec/controllers/application_controller_spec.rb:24: ====Here''s application_controller_spec.rb: require File.dirname(__FILE__) + ''/../spec_helper'' unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") describe "All controllers", :shared => true do it "should respond to authenticate" do controller.should respond_to(:authenticate) end it "should respond to current_user" do controller.should respond_to(:current_user) end it "should return true when session[:current_user_id] exists" do session[:current_user_id] = 12345 controller.authenticate.should == true end it "should flash notice when session[:current_user_id] does not exist" do session[:current_user_id] = nil controller.authenticate # <===== This is line 24 where the error occurs! flash[:notice].should == ''Please login.'' end end end ====Here''s application.rb: class ApplicationController < ActionController::Base # Pick a unique cookie name to distinguish our session data from others'' session :session_key => ''_unique_session_id'' def authenticate unless session[:current_user_id] flash[:notice] = ''Please login.'' session[:jumpto] = request.parameters # <===== This is line 11 where nil.parameters is called! redirect_to(:controller => ''ums'', :action => ''login'') end true end def current_user @current_user = User.find(session[:current_user_id]) end end ====Finally, here''s questionnaires_controller_spec.rb: require File.dirname(__FILE__) + ''/../spec_helper'' require File.dirname(__FILE__) + ''/application_controller_spec'' unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") describe QuestionnairesController do it_should_behave_like "All controllers" end : ====So as far as I can tell, my QuestionnairesController should behave like "All controllers" which puts us at application_controller_spec.rb. The first 3 examples pass, but the fourth, which calls ApplicationController.authenticate, gives me the nil object. But, isn''t request an object that is always available to controllers? Wait a second... There''s no get or post command here! Maybe thats why request is nil? I think so. Never mind! Sorry about the false alarm. I don''t want to be the boy who cried wolf. On the other hand, I think I avoided using get or post because this is an abstract action that gets called by other concrete classes. So how does one test logic in an abstract class? Smells like a job for a mock, of course?!? I''ll look over the list archive-- I think other people have asked this question before. Thanks for helping out the slow learners, -Anthony
David Chelimsky
2007-Jun-03 19:55 UTC
[rspec-users] Specs for ApplicationController, where to put them?
On 6/1/07, Anthony Carlos <anthony at digitalphenom.com> wrote:> > On May 29, 2007, at 7:52 PM, David Chelimsky wrote: > > >> My problem now, is that I get a nil object error. Specifically, in > >> application.rb, I''m trying to call request.parameters and request is > >> nil. It seems that request is not part of the context anymore since I > >> moved the behavior out to a separate file. How do I regain access to > >> request, response, assigns, flash, and session? > > > > The fact that the shared examples are in another file should have no > > bearing on whether they have runtime access to whatever is in the > > behaviours that include them. This all sounds odd to me. Can you post > > a backtrace please? > > David: > > Here''s the output from rake spec:autotest: > > : > QuestionnairesController > - should flash notice when session[:current_user_id] does not exist > (ERROR - 1) > - should return true when session[:current_user_id] exists > - should respond to current_user > - should respond to authenticate > > 1) > NoMethodError in ''QuestionnairesController should flash notice when > session[:current_user_id] does not exist'' > You have a nil object when you didn''t expect it! > The error occurred while evaluating nil.parameters > /Users/aec/ror/aca/aca_trunk/config/../app/controllers/application.rb: > 11:in `authenticate'' > ./spec/controllers/application_controller_spec.rb:24: > > ====> Here''s application_controller_spec.rb: > require File.dirname(__FILE__) + ''/../spec_helper'' > > unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") > describe "All controllers", :shared => true do > it "should respond to authenticate" do > controller.should respond_to(:authenticate) > end > it "should respond to current_user" do > controller.should respond_to(:current_user) > end > it "should return true when session[:current_user_id] exists" do > session[:current_user_id] = 12345 > controller.authenticate.should == true > end > it "should flash notice when session[:current_user_id] does not > exist" do > session[:current_user_id] = nil > controller.authenticate # <===== This is line 24 where the > error occurs! > flash[:notice].should == ''Please login.'' > end > end > end > > ====> Here''s application.rb: > class ApplicationController < ActionController::Base > # Pick a unique cookie name to distinguish our session data from > others'' > session :session_key => ''_unique_session_id'' > > def authenticate > unless session[:current_user_id] > flash[:notice] = ''Please login.'' > session[:jumpto] = request.parameters # <===== This is line 11 > where nil.parameters is called! > redirect_to(:controller => ''ums'', :action => ''login'') > end > true > end > > def current_user > @current_user = User.find(session[:current_user_id]) > end > end > > ====> Finally, here''s questionnaires_controller_spec.rb: > require File.dirname(__FILE__) + ''/../spec_helper'' > require File.dirname(__FILE__) + ''/application_controller_spec'' > unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") > > describe QuestionnairesController do > it_should_behave_like "All controllers" > end > : > > ====> So as far as I can tell, my QuestionnairesController should behave > like "All controllers" which puts us at > application_controller_spec.rb. The first 3 examples pass, but the > fourth, which calls ApplicationController.authenticate, gives me the > nil object. But, isn''t request an object that is always available to > controllers? > > Wait a second... > > There''s no get or post command here! Maybe thats why request is nil? > I think so. Never mind! Sorry about the false alarm. I don''t want to > be the boy who cried wolf. > > On the other hand, I think I avoided using get or post because this > is an abstract action that gets called by other concrete classes. So > how does one test logic in an abstract class?This question inspired me to write this blog post: http://blog.davidchelimsky.net/articles/2007/06/03/oxymoron-testing-behaviour-of-abstractions Feel free to comment directly on the blog. Cheers, David> Smells like a job for a > mock, of course?!? I''ll look over the list archive-- I think other > people have asked this question before. > > Thanks for helping out the slow learners, > > -Anthony > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Anthony Carlos
2007-Jun-04 04:10 UTC
[rspec-users] Specs for ApplicationController, where to put them?
David: I could have had a V8?!?! (For the young, that''s a reference to the commercial for V8 fruit and vegetable juice where the actor slaps himself in the forehead wishing he drank the delicious and nutritious beverage instead of some other more stupid beverage choice). Thanks for the unbelievably clear explanation. I will comment on your blog. -Anthony On Jun 3, 2007, at 3:55 PM, David Chelimsky wrote:> On 6/1/07, Anthony Carlos <anthony at digitalphenom.com> wrote: >> >> On May 29, 2007, at 7:52 PM, David Chelimsky wrote: >> >>>> My problem now, is that I get a nil object error. Specifically, in >>>> application.rb, I''m trying to call request.parameters and >>>> request is >>>> nil. It seems that request is not part of the context anymore >>>> since I >>>> moved the behavior out to a separate file. How do I regain >>>> access to >>>> request, response, assigns, flash, and session? >>> >>> The fact that the shared examples are in another file should have no >>> bearing on whether they have runtime access to whatever is in the >>> behaviours that include them. This all sounds odd to me. Can you >>> post >>> a backtrace please? >> >> David: >> >> Here''s the output from rake spec:autotest: >> >> : >> QuestionnairesController >> - should flash notice when session[:current_user_id] does not exist >> (ERROR - 1) >> - should return true when session[:current_user_id] exists >> - should respond to current_user >> - should respond to authenticate >> >> 1) >> NoMethodError in ''QuestionnairesController should flash notice when >> session[:current_user_id] does not exist'' >> You have a nil object when you didn''t expect it! >> The error occurred while evaluating nil.parameters >> /Users/aec/ror/aca/aca_trunk/config/../app/controllers/ >> application.rb: >> 11:in `authenticate'' >> ./spec/controllers/application_controller_spec.rb:24: >> >> ====>> Here''s application_controller_spec.rb: >> require File.dirname(__FILE__) + ''/../spec_helper'' >> >> unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") >> describe "All controllers", :shared => true do >> it "should respond to authenticate" do >> controller.should respond_to(:authenticate) >> end >> it "should respond to current_user" do >> controller.should respond_to(:current_user) >> end >> it "should return true when session[:current_user_id] exists" do >> session[:current_user_id] = 12345 >> controller.authenticate.should == true >> end >> it "should flash notice when session[:current_user_id] does not >> exist" do >> session[:current_user_id] = nil >> controller.authenticate # <===== This is line 24 where the >> error occurs! >> flash[:notice].should == ''Please login.'' >> end >> end >> end >> >> ====>> Here''s application.rb: >> class ApplicationController < ActionController::Base >> # Pick a unique cookie name to distinguish our session data from >> others'' >> session :session_key => ''_unique_session_id'' >> >> def authenticate >> unless session[:current_user_id] >> flash[:notice] = ''Please login.'' >> session[:jumpto] = request.parameters # <===== This is line 11 >> where nil.parameters is called! >> redirect_to(:controller => ''ums'', :action => ''login'') >> end >> true >> end >> >> def current_user >> @current_user = User.find(session[:current_user_id]) >> end >> end >> >> ====>> Finally, here''s questionnaires_controller_spec.rb: >> require File.dirname(__FILE__) + ''/../spec_helper'' >> require File.dirname(__FILE__) + ''/application_controller_spec'' >> unless Spec::DSL::Behaviour.find_shared_behaviour("All controllers") >> >> describe QuestionnairesController do >> it_should_behave_like "All controllers" >> end >> : >> >> ====>> So as far as I can tell, my QuestionnairesController should behave >> like "All controllers" which puts us at >> application_controller_spec.rb. The first 3 examples pass, but the >> fourth, which calls ApplicationController.authenticate, gives me the >> nil object. But, isn''t request an object that is always available to >> controllers? >> >> Wait a second... >> >> There''s no get or post command here! Maybe thats why request is nil? >> I think so. Never mind! Sorry about the false alarm. I don''t want to >> be the boy who cried wolf. >> >> On the other hand, I think I avoided using get or post because this >> is an abstract action that gets called by other concrete classes. So >> how does one test logic in an abstract class? > > This question inspired me to write this blog post: > > http://blog.davidchelimsky.net/articles/2007/06/03/oxymoron-testing- > behaviour-of-abstractions > > Feel free to comment directly on the blog. > > Cheers, > David > >> Smells like a job for a >> mock, of course?!? I''ll look over the list archive-- I think other >> people have asked this question before. >> >> Thanks for helping out the slow learners, >> >> -Anthony >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users