Michael Schuerig
2010-Jun-20 12:30 UTC
[rspec-users] RSpec 2 view example: render_template
On http://github.com/rspec/rspec-rails under "View specs" there''s an example describe "events/index.html.erb" do it "renders _event partial for each event" do assign(:events, [stub_model(Event), stub_model(Event)]) render view.should render_template(:partial => "_event", :count => 2) end end Is this indeed correct? From the outset, it looks wrong because it sets an expectation (view.should ...) after the call to render. Then, no matter if I leave that line where it is or put it before the render, I get an exception undefined method `render_template'' for #<RSpec::Core::ExampleGroup::Nested_1:0x7f6c0632fea0> Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote:> On http://github.com/rspec/rspec-rails under "View specs" there''s an > example > > describe "events/index.html.erb" do > it "renders _event partial for each event" do > assign(:events, [stub_model(Event), stub_model(Event)]) > render > view.should render_template(:partial => "_event", :count => 2) > end > end > > Is this indeed correct? From the outset, it looks wrong because it sets > an expectation (view.should ...) after the call to render. > > Then, no matter if I leave that line where it is or put it before the > render, I get an exception > > undefined method `render_template'' for > #<RSpec::Core::ExampleGroup::Nested_1:0x7f6c0632fea0>The README you''re looking at is stored in git with git HEAD, and aligns with that code. This feature was added after the last release, and works as advertised if you''re working with git HEAD, and will be part of the next release. If you''re using an earlier release, then you should follow the README for that release: http://github.com/rspec/rspec-rails/tree/v2.0.0.beta.12 HTH, David
On Jun 20, 2010, at 8:03 AM, David Chelimsky wrote:> > On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: > >> On http://github.com/rspec/rspec-rails under "View specs" there''s an >> example >> >> describe "events/index.html.erb" do >> it "renders _event partial for each event" do >> assign(:events, [stub_model(Event), stub_model(Event)]) >> render >> view.should render_template(:partial => "_event", :count => 2) >> end >> end >> >> Is this indeed correct? From the outset, it looks wrong because it sets >> an expectation (view.should ...) after the call to render.Yeah - I see that this is confusing. Maybe we should change that to view.should have_rendered("..."). If so, we should also change response.should render_tempate("...") and response.should redirect_to("....") in controller specs. WDTY?>> >> Then, no matter if I leave that line where it is or put it before the >> render, I get an exception >> >> undefined method `render_template'' for >> #<RSpec::Core::ExampleGroup::Nested_1:0x7f6c0632fea0> > > The README you''re looking at is stored in git with git HEAD, and aligns with that code. This feature was added after the last release, and works as advertised if you''re working with git HEAD, and will be part of the next release. > > If you''re using an earlier release, then you should follow the README for that release: http://github.com/rspec/rspec-rails/tree/v2.0.0.beta.12 > > HTH, > David > >
On Jun 20, 2010, at 8:06 AM, David Chelimsky wrote:> On Jun 20, 2010, at 8:03 AM, David Chelimsky wrote: > >> >> On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: >> >>> On http://github.com/rspec/rspec-rails under "View specs" there''s an >>> example >>> >>> describe "events/index.html.erb" do >>> it "renders _event partial for each event" do >>> assign(:events, [stub_model(Event), stub_model(Event)]) >>> render >>> view.should render_template(:partial => "_event", :count => 2) >>> end >>> end >>> >>> Is this indeed correct? From the outset, it looks wrong because it sets >>> an expectation (view.should ...) after the call to render. > > Yeah - I see that this is confusing. Maybe we should change that to view.should have_rendered("..."). If so, we should also change response.should render_tempate("...") and response.should redirect_to("....") in controller specs. > > WDTY?I''m also toying with an idea that would allow you to set an expectation before and have it evaluate at the end. Kind of like message expectations from the outside, but the underlying implementation would be different. Not sure if it would work, and I''m not sure if it would help (might just make things more confusing). WDYT?> >>> >>> Then, no matter if I leave that line where it is or put it before the >>> render, I get an exception >>> >>> undefined method `render_template'' for >>> #<RSpec::Core::ExampleGroup::Nested_1:0x7f6c0632fea0> >> >> The README you''re looking at is stored in git with git HEAD, and aligns with that code. This feature was added after the last release, and works as advertised if you''re working with git HEAD, and will be part of the next release. >> >> If you''re using an earlier release, then you should follow the README for that release: http://github.com/rspec/rspec-rails/tree/v2.0.0.beta.12 >> >> HTH, >> David >> >> >
Michael Schuerig
2010-Jun-20 14:35 UTC
[rspec-users] RSpec 2 view example: render_template
On Sunday 20 June 2010, David Chelimsky wrote:> On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: > > On http://github.com/rspec/rspec-rails under "View specs" there''s > > an example > > > > describe "events/index.html.erb" do > > > > it "renders _event partial for each event" do > > > > assign(:events, [stub_model(Event), stub_model(Event)]) > > render > > view.should render_template(:partial => "_event", :count => 2) > > > > end > > > > end > > > > Is this indeed correct? From the outset, it looks wrong because it > > sets an expectation (view.should ...) after the call to render. > > > > Then, no matter if I leave that line where it is or put it before > > the render, I get an exception > > > > undefined method `render_template'' for > > #<RSpec::Core::ExampleGroup::Nested_1:0x7f6c0632fea0> > > The README you''re looking at is stored in git with git HEAD, and > aligns with that code. This feature was added after the last > release, and works as advertised if you''re working with git HEAD, > and will be part of the next release.Oops, you''re completely right, of course.> If you''re using an earlier release, then you should follow the README > for that release: > http://github.com/rspec/rspec-rails/tree/v2.0.0.beta.12That README doesn''t say anything on the topic. This probably means that I have to wait for the next beta. I already found out, that I can set expectations with view.should_receive(:render) like I did in pre-2.0 with template.should_receive(:render). Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
Michael Schuerig
2010-Jun-20 14:38 UTC
[rspec-users] RSpec 2 view example: render_template
On Sunday 20 June 2010, David Chelimsky wrote:> On Jun 20, 2010, at 8:03 AM, David Chelimsky wrote: > > On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: > >> On http://github.com/rspec/rspec-rails under "View specs" there''s > >> an example > >> > >> describe "events/index.html.erb" do > >> it "renders _event partial for each event" do > >> > >> assign(:events, [stub_model(Event), stub_model(Event)]) > >> render > >> view.should render_template(:partial => "_event", :count => 2) > >> > >> end > >> end > >> > >> Is this indeed correct? From the outset, it looks wrong because it > >> sets an expectation (view.should ...) after the call to render. > > Yeah - I see that this is confusing. Maybe we should change that to > view.should have_rendered("..."). If so, we should also change > response.should render_tempate("...") and response.should > redirect_to("....") in controller specs.That behavior would be more useful, in my opinion. In view and controller specs I like to put the render or get/post/... at the end of a begin block and then do the checks in the actual examples. Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Jun 20, 2010, at 9:35 AM, Michael Schuerig wrote:> On Sunday 20 June 2010, David Chelimsky wrote: >> On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: >>> On http://github.com/rspec/rspec-rails under "View specs" there''s >>> an example >>> >>> describe "events/index.html.erb" do >>> >>> it "renders _event partial for each event" do >>> >>> assign(:events, [stub_model(Event), stub_model(Event)]) >>> render >>> view.should render_template(:partial => "_event", :count => 2) >>> >>> end >>> >>> end >>> >>> Is this indeed correct? From the outset, it looks wrong because it >>> sets an expectation (view.should ...) after the call to render. >>> >>> Then, no matter if I leave that line where it is or put it before >>> the render, I get an exception >>> >>> undefined method `render_template'' for >>> #<RSpec::Core::ExampleGroup::Nested_1:0x7f6c0632fea0> >> >> The README you''re looking at is stored in git with git HEAD, and >> aligns with that code. This feature was added after the last >> release, and works as advertised if you''re working with git HEAD, >> and will be part of the next release. > > Oops, you''re completely right, of course. > >> If you''re using an earlier release, then you should follow the README >> for that release: >> http://github.com/rspec/rspec-rails/tree/v2.0.0.beta.12 > > That README doesn''t say anything on the topic. This probably means that > I have to wait for the next beta. I already found out, that I can set > expectations with view.should_receive(:render) like I did in pre-2.0 > with template.should_receive(:render).That doesn''t actually work like it did in 1.x, because the rails internals have changed: it "renders the edit gadget form" do view.should_receive(:render).with(:partial => "_form") render end $ rspec spec/views/gadgets/edit.html.erb_spec.rb F 1) gadgets/edit.html.erb renders the edit gadget form Failure/Error: render #<ActionView::Base:0x103696f28> received :render with unexpected arguments expected: ({:partial=>"_form"}) got: ({:template=>"gadgets/edit.html.erb"}, {}) You have to say this instead: it "renders the edit gadget form" do view.should_receive(:_render_partial).with(hash_including(:partial => "form")) render end ... which is a bit of a kludge and subject to changes in rails'' internals. That''s why I want to use "render_template", which delegates to "assert_template", which is a rails API and less likely to break. Make sense?> > Michael > > -- > Michael Schuerig > mailto:michael at schuerig.de > http://www.schuerig.de/michael/ > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
Wincent Colaiuta
2010-Jun-20 15:34 UTC
[rspec-users] RSpec 2 view example: render_template
El 20/06/2010, a las 15:09, David Chelimsky escribi?:> > On Jun 20, 2010, at 8:06 AM, David Chelimsky wrote: > >> On Jun 20, 2010, at 8:03 AM, David Chelimsky wrote: >> >>> >>> On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: >>> >>>> On http://github.com/rspec/rspec-rails under "View specs" there''s an >>>> example >>>> >>>> describe "events/index.html.erb" do >>>> it "renders _event partial for each event" do >>>> assign(:events, [stub_model(Event), stub_model(Event)]) >>>> render >>>> view.should render_template(:partial => "_event", :count => 2) >>>> end >>>> end >>>> >>>> Is this indeed correct? From the outset, it looks wrong because it sets >>>> an expectation (view.should ...) after the call to render. >> >> Yeah - I see that this is confusing. Maybe we should change that to view.should have_rendered("..."). If so, we should also change response.should render_tempate("...") and response.should redirect_to("....") in controller specs. >> >> WDTY? > > I''m also toying with an idea that would allow you to set an expectation before and have it evaluate at the end. Kind of like message expectations from the outside, but the underlying implementation would be different.Was going to suggest exactly that. Although the implementation would be different from normal message expectations, I wonder if it could be built on top of them.> Not sure if it would work, and I''m not sure if it would help (might just make things more confusing). WDYT?I''m not sure either, but I suspect it would be more consistent with the way we set up our other expectations. ie. - when we are testing interactions, we usually use message expectations that are set up beforehand - when we are testing state, we perform some action and then inspect the state (usually expressed using present tense eg. "should be") The "should have_rendered" (past tense) idea doesn''t really fit in, with those two styles either conceptually or grammatically. Cheers, Wincent
Michael Schuerig
2010-Jun-20 16:21 UTC
[rspec-users] RSpec 2 view example: render_template
On Sunday 20 June 2010, David Chelimsky wrote:> On Jun 20, 2010, at 9:35 AM, Michael Schuerig wrote: > > I already found out, that I > > can set expectations with view.should_receive(:render) like I did > > in pre-2.0 with template.should_receive(:render). > > That doesn''t actually work like it did in 1.x, because the rails > internals have changed:Yes, I mis-typed. It should have been "can''t". Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Jun 20, 2010, at 10:34 AM, Wincent Colaiuta wrote:> El 20/06/2010, a las 15:09, David Chelimsky escribi?: > >> >> On Jun 20, 2010, at 8:06 AM, David Chelimsky wrote: >> >>> On Jun 20, 2010, at 8:03 AM, David Chelimsky wrote: >>> >>>> >>>> On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: >>>> >>>>> On http://github.com/rspec/rspec-rails under "View specs" there''s an >>>>> example >>>>> >>>>> describe "events/index.html.erb" do >>>>> it "renders _event partial for each event" do >>>>> assign(:events, [stub_model(Event), stub_model(Event)]) >>>>> render >>>>> view.should render_template(:partial => "_event", :count => 2) >>>>> end >>>>> end >>>>> >>>>> Is this indeed correct? From the outset, it looks wrong because it sets >>>>> an expectation (view.should ...) after the call to render. >>> >>> Yeah - I see that this is confusing. Maybe we should change that to view.should have_rendered("..."). If so, we should also change response.should render_tempate("...") and response.should redirect_to("....") in controller specs. >>> >>> WDTY? >> >> I''m also toying with an idea that would allow you to set an expectation before and have it evaluate at the end. Kind of like message expectations from the outside, but the underlying implementation would be different. > > Was going to suggest exactly that. > > Although the implementation would be different from normal message expectations, I wonder if it could be built on top of them.That''s the idea. I''m working on a pub/sub API for events like example_started, example_initialized, example_executed, example_finished (do those names make sense to you?). You can see that work on the events branch of rspec-core: http://github.com/rspec/rspec-core/tree/events. Please feel free to provide any feedback on the direction - just note that it is preliminary and incomplete :) I''m pretty sure I''ll be able to use that to write matchers that pause evaluation until they receive the example_executed message.>> Not sure if it would work, and I''m not sure if it would help (might just make things more confusing). WDYT? > > I''m not sure either, but I suspect it would be more consistent with the way we set up our other expectations. > > ie. - when we are testing interactions, we usually use message expectations that are set up beforehand > > - when we are testing state, we perform some action and then inspect the state (usually expressed using present tense eg. "should be") > > The "should have_rendered" (past tense) idea doesn''t really fit in, with those two styles either conceptually or grammatically.This is an odd bird because it''s delegating to a rails method named assert_template, which is intended to be evaluated after the action. The underlying implementation looks at a hash that AC::TestCase::Behavior builds up during the test, so it''s not quite a message expectation (verifying upon receipt of the message). So I think have_rendered is more accurate, but you have to understand the implementation to understand that :) The other thing is that message expectations on real objects don''t typically invoke the expected methods. In this case, the partial is actually being rendered, so putting "view.should render_template(''...'')" before the action could be confusing. One thought is to add a custom resolver that finds the first requested template for real, but then stubs out the remaining templates (a la the NullResolver used in controller specs). That would make controller specs and view specs work the same way, maybe with a render_partials method in view specs to tell it to render the partials (like render_views in view specs). An alternative would be to make the "view.should render_template" stub out the suggested template if called before the action? Then it would work a lot more like real message expectations. Thoughts?> > Cheers, > Wincent > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
Wincent Colaiuta
2010-Jun-20 19:08 UTC
[rspec-users] RSpec 2 view example: render_template
El 20/06/2010, a las 19:59, David Chelimsky escribi?:> On Jun 20, 2010, at 10:34 AM, Wincent Colaiuta wrote: > >> El 20/06/2010, a las 15:09, David Chelimsky escribi?: >> >>> >>> On Jun 20, 2010, at 8:06 AM, David Chelimsky wrote: >>> >>>> On Jun 20, 2010, at 8:03 AM, David Chelimsky wrote: >>>> >>>>> >>>>> On Jun 20, 2010, at 7:30 AM, Michael Schuerig wrote: >>>>> >>>>>> On http://github.com/rspec/rspec-rails under "View specs" there''s an >>>>>> example >>>>>> >>>>>> describe "events/index.html.erb" do >>>>>> it "renders _event partial for each event" do >>>>>> assign(:events, [stub_model(Event), stub_model(Event)]) >>>>>> render >>>>>> view.should render_template(:partial => "_event", :count => 2) >>>>>> end >>>>>> end >>>>>> >>>>>> Is this indeed correct? From the outset, it looks wrong because it sets >>>>>> an expectation (view.should ...) after the call to render. >>>> >>>> Yeah - I see that this is confusing. Maybe we should change that to view.should have_rendered("..."). If so, we should also change response.should render_tempate("...") and response.should redirect_to("....") in controller specs. >>>> >>>> WDTY? >>> >>> I''m also toying with an idea that would allow you to set an expectation before and have it evaluate at the end. Kind of like message expectations from the outside, but the underlying implementation would be different. >> >> Was going to suggest exactly that. >> >> Although the implementation would be different from normal message expectations, I wonder if it could be built on top of them. > > That''s the idea. I''m working on a pub/sub API for events like example_started, example_initialized, example_executed, example_finished (do those names make sense to you?). You can see that work on the events branch of rspec-core: http://github.com/rspec/rspec-core/tree/events. Please feel free to provide any feedback on the direction - just note that it is preliminary and incomplete :) > > I''m pretty sure I''ll be able to use that to write matchers that pause evaluation until they receive the example_executed message. > >>> Not sure if it would work, and I''m not sure if it would help (might just make things more confusing). WDYT? >> >> I''m not sure either, but I suspect it would be more consistent with the way we set up our other expectations. >> >> ie. - when we are testing interactions, we usually use message expectations that are set up beforehand >> >> - when we are testing state, we perform some action and then inspect the state (usually expressed using present tense eg. "should be") >> >> The "should have_rendered" (past tense) idea doesn''t really fit in, with those two styles either conceptually or grammatically. > > This is an odd bird because it''s delegating to a rails method named assert_template, which is intended to be evaluated after the action. The underlying implementation looks at a hash that AC::TestCase::Behavior builds up during the test, so it''s not quite a message expectation (verifying upon receipt of the message). So I think have_rendered is more accurate, but you have to understand the implementation to understand that :)Yes, and being an implementation detail, you shouldn''t really be worrying about whether the "language" used by RSpec is "true" to the underlying mechanism or not. I think it''s more important for you to design your language first, keeping it consistent with the philosophy behind the design of the rest of RSpec (a philosophy which you probably know better than anyone).> The other thing is that message expectations on real objects don''t typically invoke the expected methods. In this case, the partial is actually being rendered, so putting "view.should render_template(''...'')" before the action could be confusing. > > One thought is to add a custom resolver that finds the first requested template for real, but then stubs out the remaining templates (a la the NullResolver used in controller specs). That would make controller specs and view specs work the same way, maybe with a render_partials method in view specs to tell it to render the partials (like render_views in view specs). > > An alternative would be to make the "view.should render_template" stub out the suggested template if called before the action? Then it would work a lot more like real message expectations. > > Thoughts?I don''t know enough about this to speak with much authority, but from my fairly ignorant perspective as a mere "consumer" of the Rails and testing machinery, that last option you suggest immediately sounds like the simplest one, and in general I think simple solutions often end up being the best ones (or at least the ones worth investigating first)... Wincent