I''m stumped. How would I go about specing the "update_sandbox" method? # bids_controller: def new @bid = Bid.new respond_to do |wants| wants.html { redirect_to job_bids_path(@job) } wants.js { update_sandbox do render_to_string :partial => ''new'', :locals => {:bid => @bid, :job => @job} end } end end Here is my 4789th stab at it: # bids_controller_spec.rb it "should render new template" do sandbox = mock("Sandbox") controller.stub!(:update_sandbox).and_return(sandbox) sandbox.stub!(:render_to_string).with(:partial => ''new'', :locals => {:bid => @bid, :job => @job}) sandbox.should_receive(:render_to_string).with(:partial => ''new'', :locals => {:bid => @bid, :job => @job}) controller.should_receive(:update_sandbox) xhr :get, :new end # => Mock ''Sandbox'' expected :render_to_string with ({:partial=>"new", :locals=>{:job=>#<Job:0x2b497e8 @name="Job_1014">, :bid=>#<Bid:0x2b46f0c @name="Bid_1015">}}) once, but received it 0 times Any pointers would be greatly appreciated! Thanks! Matt Darby, M.S. Rails | PHP | Linux | MySQL | IT Email: matt /\at/\ matt-darby.com Skype: matt-darby Web: http://blog.matt-darby.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090106/d2eed459/attachment.html>
On Tue, Jan 6, 2009 at 9:53 AM, Matt Darby <matt at matt-darby.com> wrote:> I''m stumped. How would I go about specing the "update_sandbox" method? > # bids_controller: > def new > @bid = Bid.new > > respond_to do |wants| > wants.html { redirect_to job_bids_path(@job) } > wants.js { > update_sandbox do > render_to_string :partial => ''new'', :locals => {:bid => @bid, :job > => @job} > end > } > end > end > > Here is my 4789th stab at it: > # bids_controller_spec.rb > it "should render new template" do > sandbox = mock("Sandbox") > controller.stub!(:update_sandbox).and_return(sandbox) > sandbox.stub!(:render_to_string).with(:partial => ''new'', :locals => > {:bid => @bid, :job => @job}) > > sandbox.should_receive(:render_to_string).with(:partial => ''new'', > :locals => {:bid => @bid, :job => @job}) > controller.should_receive(:update_sandbox)I''m just guessing here, because I don''t know what #update_sandbox does, but you probably want this to yield the sandbox: controller.should_receive(:update_sandbox).and_yield(sandbox) Let us know if that works. Cheers, David> > xhr :get, :new > end > # => Mock ''Sandbox'' expected :render_to_string with ({:partial=>"new", > :locals=>{:job=>#<Job:0x2b497e8 @name="Job_1014">, :bid=>#<Bid:0x2b46f0c > @name="Bid_1015">}}) once, but received it 0 times > Any pointers would be greatly appreciated! > > > Thanks! > Matt Darby, M.S. > Rails | PHP | Linux | MySQL | IT > Email: matt /\at/\ matt-darby.com > Skype: matt-darby > Web: http://blog.matt-darby.com > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Jan 6, 2009, at 11:27 AM, David Chelimsky wrote:> On Tue, Jan 6, 2009 at 9:53 AM, Matt Darby <matt at matt-darby.com> > wrote: >> I''m stumped. How would I go about specing the "update_sandbox" >> method? >> # bids_controller: >> def new >> @bid = Bid.new >> >> respond_to do |wants| >> wants.html { redirect_to job_bids_path(@job) } >> wants.js { >> update_sandbox do >> render_to_string :partial => ''new'', :locals => {:bid => >> @bid, :job >> => @job} >> end >> } >> end >> end >> >> Here is my 4789th stab at it: >> # bids_controller_spec.rb >> it "should render new template" do >> sandbox = mock("Sandbox") >> controller.stub!(:update_sandbox).and_return(sandbox) >> sandbox.stub!(:render_to_string).with(:partial => >> ''new'', :locals => >> {:bid => @bid, :job => @job}) >> >> sandbox.should_receive(:render_to_string).with(:partial => >> ''new'', >> :locals => {:bid => @bid, :job => @job}) >> controller.should_receive(:update_sandbox) > > I''m just guessing here, because I don''t know what #update_sandbox > does, but you probably want this to yield the sandbox: > > controller.should_receive(:update_sandbox).and_yield(sandbox) > > Let us know if that works. > > Cheers, > David >Unfortunately, I get the same result. Here is the #update_sandbox method: # application.rb # RJS method to show new / edit partials def update_sandbox(obj = nil, &block) highlight_this_div = obj ? dom_id(obj) : :sandbox render :update do |page| page[:error_div].hide page.replace_html :sandbox, capture(&block) page.visual_effect :scroll_to, :sandbox page.visual_effect :highlight, highlight_this_div end end Thanks for your help David!>> >> xhr :get, :new >> end >> # => Mock ''Sandbox'' expected :render_to_string with >> ({:partial=>"new", >> :locals=>{:job=>#<Job:0x2b497e8 @name="Job_1014">, :bid=>#<Bid: >> 0x2b46f0c >> @name="Bid_1015">}}) once, but received it 0 times >> Any pointers would be greatly appreciated! >> >> >> Thanks! >> Matt Darby, M.S. >> Rails | PHP | Linux | MySQL | IT >> Email: matt /\at/\ matt-darby.com >> Skype: matt-darby >> Web: http://blog.matt-darby.com >> >> _______________________________________________ >> 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
On Tue, Jan 6, 2009 at 10:41 AM, Matt Darby <matt at matt-darby.com> wrote:> On Jan 6, 2009, at 11:27 AM, David Chelimsky wrote: > >> On Tue, Jan 6, 2009 at 9:53 AM, Matt Darby <matt at matt-darby.com> wrote: >>> >>> I''m stumped. How would I go about specing the "update_sandbox" method? >>> # bids_controller: >>> def new >>> @bid = Bid.new >>> >>> respond_to do |wants| >>> wants.html { redirect_to job_bids_path(@job) } >>> wants.js { >>> update_sandbox do >>> render_to_string :partial => ''new'', :locals => {:bid => @bid, >>> :job >>> => @job} >>> end >>> } >>> end >>> end >>> >>> Here is my 4789th stab at it: >>> # bids_controller_spec.rb >>> it "should render new template" do >>> sandbox = mock("Sandbox") >>> controller.stub!(:update_sandbox).and_return(sandbox) >>> sandbox.stub!(:render_to_string).with(:partial => ''new'', :locals => >>> {:bid => @bid, :job => @job}) >>> >>> sandbox.should_receive(:render_to_string).with(:partial => ''new'', >>> :locals => {:bid => @bid, :job => @job}) >>> controller.should_receive(:update_sandbox) >> >> I''m just guessing here, because I don''t know what #update_sandbox >> does, but you probably want this to yield the sandbox: >> >> controller.should_receive(:update_sandbox).and_yield(sandbox) >> >> Let us know if that works. >> >> Cheers, >> David >> > > Unfortunately, I get the same result. Here is the #update_sandbox method: > > # application.rb > # RJS method to show new / edit partials > def update_sandbox(obj = nil, &block) > highlight_this_div = obj ? dom_id(obj) : :sandbox > > render :update do |page| > page[:error_div].hide > page.replace_html :sandbox, capture(&block)This call to capture(&block) is what''s going to result in eval''ing the block w/ render_to_string in it. Since update_sandbox is being stubbed, it is never actually called, so it makes perfect sense that this call to capture which evals the &block is never called. I''d go for a higher level expectation here instead of specifying the internal behaviour of update_sandbox. Something like setting an expectation that specific stuff shows up in the output. HTH, David> page.visual_effect :scroll_to, :sandbox > page.visual_effect :highlight, highlight_this_div > end > end > > > Thanks for your help David! > > > >>> >>> xhr :get, :new >>> end >>> # => Mock ''Sandbox'' expected :render_to_string with ({:partial=>"new", >>> :locals=>{:job=>#<Job:0x2b497e8 @name="Job_1014">, :bid=>#<Bid:0x2b46f0c >>> @name="Bid_1015">}}) once, but received it 0 times >>> Any pointers would be greatly appreciated! >>> >>> >>> Thanks! >>> Matt Darby, M.S. >>> Rails | PHP | Linux | MySQL | IT >>> Email: matt /\at/\ matt-darby.com >>> Skype: matt-darby >>> Web: http://blog.matt-darby.com >>> >>> _______________________________________________ >>> 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 >
On Tue, Jan 6, 2009 at 10:53 AM, Matt Darby <matt at matt-darby.com> wrote:> I''m stumped. How would I go about specing the "update_sandbox" method?I couldn''t hope to compete with David''s answer when it comes to specifics, but more generally, it occurs to me that your question is a little imprecise and that could point to part of the cognitive disconnect. You ask how to spec the method, but you''re NOT specing the "update_sandbox" method in the example you posted. You''re specing a controller''s "new" action. Creating a stub or mock for a method isn''t the same as specing it. A spec tests something to see if it does what it''s supposed to. Mocking or stubbing is the opposite: instead of testing the method, you''re pretending the method doesn''t exist and replacing it with a cardboard cutout. Other things I noticed: 1.) There''s really no point in putting identical stub!() and should_receive() declarations in the same example. should_receive() does everything stub!() does and slightly more. It replaces the method AND says "Complain if this doesn''t get called." When you see them used in the same spec file, what you''re usually seeing is stub!() in the "before" blocks just to replace external interfaces and make sure nothing breaks, and then should_receive() in multiple individual examples to prove that things called when they should. 2.) On that note, it''s becoming more and more the accepted practice to have only one "should" per example. (Including "should_receives" or other mocks.) That way, if one of the expectations breaks, you''ll know which one from the "it should..." text and won''t have to look at individual lines. 3.) You _could_ probably make this spec work as it stands by changing the "update_sandbox" call to expect a Proc with the "render_to_string ..." block included; that''s what actually happens when you call a method with a "do" block, you''re passing it an anonymous Proc as a parameter. Tweak it enough and I''ll bet you could get this to work. 4.) BUT, I agree with David, there''s probably no point. At this level your spec becomes sort of trivial; you''re not even testing behavior any more, you''re testing for the existence of certain lines of code. Think big picture: WHY are you testing? What is it you want to prove? Your users don''t care whether render_to_string() ever gets called with certain parameters, and tomorrow you won''t care either. You DO care whether the controller''s "new" method responds with an appropriate block of Javascript when accessed via AJAX. You can find that out by making the request and checking the response, but if you stub out the part that actually generates the Javascript, all you''ll learn is "the controller get called and it responded." If that''s all you want to know, you could mock update_sandbox to return "neener neener" and test for THAT. (And make sure to spec the update_sandbox() method thoroughly elsewhere.) 5.) OR... You might gain some good food for thought by going to the MerbCamp videos (http://merbcamp.com/video) and watching Yehuda Katz''s video on testing (http://merbcamp.com/video/katz1.mp4). Don''t worry about the Merb stuff; what he''s describing is a general approach and it''s just as applicable to Rails. The philosophy is somewhat contrary to the "unit test everything in isolation" philosophy that many others espouse, but it doesn''t hurt to learn both and decide which style suits you best. I personally found Yehuda''s approach to be a slap of cold water and then a breath of fresh air; since I started it, I''ve almost entirely stopped mocking things, and I no longer have the frustrating feeling that I''m spending 10x longer on tests (and testing my tests, and debugging my tests) than I am on my application features. But again: think for yourself, and decide what suits your goals and learning path. -- Have Fun, Steve Eley (sfeley at gmail.com) ESCAPE POD - The Science Fiction Podcast Magazine http://www.escapepod.org
On Tue, Jan 6, 2009 at 12:16 PM, Stephen Eley <sfeley at gmail.com> wrote:> On Tue, Jan 6, 2009 at 10:53 AM, Matt Darby <matt at matt-darby.com> wrote: >> I''m stumped. How would I go about specing the "update_sandbox" method? > > I couldn''t hope to compete with David''s answer when it comes to > specifics, but more generally, it occurs to me that your question is a > little imprecise and that could point to part of the cognitive > disconnect. You ask how to spec the method, but you''re NOT specing > the "update_sandbox" method in the example you posted. You''re specing > a controller''s "new" action. Creating a stub or mock for a method > isn''t the same as specing it. A spec tests something to see if it > does what it''s supposed to. Mocking or stubbing is the opposite: > instead of testing the method, you''re pretending the method doesn''t > exist and replacing it with a cardboard cutout. > > Other things I noticed: > > 1.) There''s really no point in putting identical stub!() and > should_receive() declarations in the same example. should_receive() > does everything stub!() does and slightly more. It replaces the > method AND says "Complain if this doesn''t get called." When you see > them used in the same spec file, what you''re usually seeing is stub!() > in the "before" blocks just to replace external interfaces and make > sure nothing breaks, and then should_receive() in multiple individual > examples to prove that things called when they should. > > 2.) On that note, it''s becoming more and more the accepted practice to > have only one "should" per example. (Including "should_receives" or > other mocks.) That way, if one of the expectations breaks, you''ll > know which one from the "it should..." text and won''t have to look at > individual lines. > > 3.) You _could_ probably make this spec work as it stands by changing > the "update_sandbox" call to expect a Proc with the "render_to_string > ..." block included; that''s what actually happens when you call a > method with a "do" block, you''re passing it an anonymous Proc as a > parameter. Tweak it enough and I''ll bet you could get this to work. > > 4.) BUT, I agree with David, there''s probably no point. At this level > your spec becomes sort of trivial; you''re not even testing behavior > any more, you''re testing for the existence of certain lines of code. > Think big picture: WHY are you testing? What is it you want to prove? > Your users don''t care whether render_to_string() ever gets called > with certain parameters, and tomorrow you won''t care either. You DO > care whether the controller''s "new" method responds with an > appropriate block of Javascript when accessed via AJAX. You can find > that out by making the request and checking the response, but if you > stub out the part that actually generates the Javascript, all you''ll > learn is "the controller get called and it responded." If that''s all > you want to know, you could mock update_sandbox to return "neener > neener" and test for THAT. (And make sure to spec the > update_sandbox() method thoroughly elsewhere.) > > 5.) OR... You might gain some good food for thought by going to the > MerbCamp videos (http://merbcamp.com/video) and watching Yehuda Katz''s > video on testing (http://merbcamp.com/video/katz1.mp4). Don''t worry > about the Merb stuff; what he''s describing is a general approach and > it''s just as applicable to Rails. The philosophy is somewhat contrary > to the "unit test everything in isolation" philosophy that many others > espouse, but it doesn''t hurt to learn both and decide which style > suits you best.I''d refine that a bit: learn both and decide *when to apply each*. Choosing one style over the other limits your toolbox and consequently your ability to operate in different contexts. FWiW, David> > I personally found Yehuda''s approach to be a slap of cold water and > then a breath of fresh air; since I started it, I''ve almost entirely > stopped mocking things, and I no longer have the frustrating feeling > that I''m spending 10x longer on tests (and testing my tests, and > debugging my tests) than I am on my application features. But again: > think for yourself, and decide what suits your goals and learning > path. > > > -- > Have Fun, > Steve Eley (sfeley at gmail.com) > ESCAPE POD - The Science Fiction Podcast Magazine > http://www.escapepod.org > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Tue, Jan 6, 2009 at 1:24 PM, David Chelimsky <dchelimsky at gmail.com> wrote:> > I''d refine that a bit: learn both and decide *when to apply each*. > > Choosing one style over the other limits your toolbox and consequently > your ability to operate in different contexts.True, and good point. -- Have Fun, Steve Eley (sfeley at gmail.com) ESCAPE POD - The Science Fiction Podcast Magazine http://www.escapepod.org
On Jan 6, 2009, at 1:16 PM, Stephen Eley wrote:> On Tue, Jan 6, 2009 at 10:53 AM, Matt Darby <matt at matt-darby.com> > wrote: >> I''m stumped. How would I go about specing the "update_sandbox" >> method? > > I couldn''t hope to compete with David''s answer when it comes to > specifics, but more generally, it occurs to me that your question is a > little imprecise and that could point to part of the cognitive > disconnect. You ask how to spec the method, but you''re NOT specing > the "update_sandbox" method in the example you posted. You''re specing > a controller''s "new" action. Creating a stub or mock for a method > isn''t the same as specing it. A spec tests something to see if it > does what it''s supposed to. Mocking or stubbing is the opposite: > instead of testing the method, you''re pretending the method doesn''t > exist and replacing it with a cardboard cutout. >Hi Stephen! My aim is to spec the Bid::new action; all it really does is call the #update_sandbox method with a particular block. If I am to test strictly the behavior of the action, I would really just be testing the View as it''s based on RJS. The View is spec''d, but I need to simulate the actual updating of the View via the returned Javascript.> Other things I noticed: > > 1.) There''s really no point in putting identical stub!() and > should_receive() declarations in the same example. should_receive() > does everything stub!() does and slightly more. It replaces the > method AND says "Complain if this doesn''t get called." When you see > them used in the same spec file, what you''re usually seeing is stub!() > in the "before" blocks just to replace external interfaces and make > sure nothing breaks, and then should_receive() in multiple individual > examples to prove that things called when they should. >Good to know! That will really clean up my specs (and save me a ton of typing!)> 2.) On that note, it''s becoming more and more the accepted practice to > have only one "should" per example. (Including "should_receives" or > other mocks.) That way, if one of the expectations breaks, you''ll > know which one from the "it should..." text and won''t have to look at > individual lines. >Agreed, however, I wasn''t sure how to approach this case as I''m testing a method and a block at the same time. By the time I''d arrived at the spec I originally posted I was well into the "Grasping At Straws" phase.> 3.) You _could_ probably make this spec work as it stands by changing > the "update_sandbox" call to expect a Proc with the "render_to_string > ..." block included; that''s what actually happens when you call a > method with a "do" block, you''re passing it an anonymous Proc as a > parameter. Tweak it enough and I''ll bet you could get this to work. >Duly noted.> 4.) BUT, I agree with David, there''s probably no point. At this level > your spec becomes sort of trivial; you''re not even testing behavior > any more, you''re testing for the existence of certain lines of code. > Think big picture: WHY are you testing? What is it you want to prove? > Your users don''t care whether render_to_string() ever gets called > with certain parameters, and tomorrow you won''t care either. You DO > care whether the controller''s "new" method responds with an > appropriate block of Javascript when accessed via AJAX. You can find > that out by making the request and checking the response, but if you > stub out the part that actually generates the Javascript, all you''ll > learn is "the controller get called and it responded." If that''s all > you want to know, you could mock update_sandbox to return "neener > neener" and test for THAT. (And make sure to spec the > update_sandbox() method thoroughly elsewhere.) >I don''t necessarily care what #update_sandbox actually produces, I just want to make sure that it is called with the expected "render_to_string" call. Can you clarify "making the request and checking the response"? Is it possible to just check the "xhr :get, :index" call for a standard hunk of Javascript? If so, problem solved -- again, I don''t yet have a super firm grip on controller specing when AJAX/RJS is concerned. I''m eagerly awaiting David''s book!> 5.) OR... You might gain some good food for thought by going to the > MerbCamp videos (http://merbcamp.com/video) and watching Yehuda Katz''s > video on testing (http://merbcamp.com/video/katz1.mp4). Don''t worry > about the Merb stuff; what he''s describing is a general approach and > it''s just as applicable to Rails. The philosophy is somewhat contrary > to the "unit test everything in isolation" philosophy that many others > espouse, but it doesn''t hurt to learn both and decide which style > suits you best. >I shall, thanks for the pointer.> I personally found Yehuda''s approach to be a slap of cold water and > then a breath of fresh air; since I started it, I''ve almost entirely > stopped mocking things, and I no longer have the frustrating feeling > that I''m spending 10x longer on tests (and testing my tests, and > debugging my tests) than I am on my application features. But again: > think for yourself, and decide what suits your goals and learning > path. >Thank you for your reply, it was really very insightful and I''m sure others will learn from it as well!> > -- > Have Fun, > Steve Eley (sfeley at gmail.com) > ESCAPE POD - The Science Fiction Podcast Magazine > http://www.escapepod.org > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users