Jay Levitt
2006-Nov-07 19:31 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
I can understand that it''s easier for rspec to set up a mock in advance of the controller call. But it makes it difficult to do something like: context "The HarkController, given Louie the logged-in user" do setup do post :login, :username => ''louie'', :password => ''atest'' end specify "should redirect Louie to the home page"... specify "should set Louie to be the current user"... end Instead, I have to break out the should-redirect into its own call, since the post is done at setup time, but that''s not an appropriate place for a spec. What''s the right solution? Jay Levitt
David Chelimsky
2006-Nov-07 20:02 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
On 11/7/06, Jay Levitt <lists-rspec at shopwatch.org> wrote:> I can understand that it''s easier for rspec to set up a mock in advance > of the controller call.This was a philosophical choice, not a cop-out to make it easier to implement. That sounds more defensive than it is meant to be. I just want to assure you that our goal is to create the right API.> But it makes it difficult to do something like: > > context "The HarkController, given Louie the logged-in user" do > setup do > post :login, :username => ''louie'', :password => ''atest'' > end > > specify "should redirect Louie to the home page"... > > specify "should set Louie to be the current user"... > > end > > Instead, I have to break out the should-redirect into its own call, > since the post is done at setup time, but that''s not an appropriate > place for a spec.The BDD way, at least as I see it, is rooted in the TDD way: 1. setup objects in a known starting state (setup - perhaps stubs) 2. set expectations of how the object should react to an action (mocks) 3. perform the action 4. verify that the object reacted as expected (verify mocks plus additional assert-like expectations) The setup/specify structure is intended to let you step 1 (setup) in the setup and do whatever combination of 2-4 that you like in specify. In my view, the post is the action, and it belongs in the specify block in this case. The problem there is that it doesn''t feel DRY. That''s a problem I''m interested in solving, but I''d prefer to do it in a way that helps to express the behaviour-driven nature of BDD. What that means yet I''m not sure. I have a couple of ideas that I''ll share as they become slightly more fully baked. I''d love to hear yours in the mean time. What I''m doing for examples like yours above is adding a method for the post and calling it from each of my specify blocks. Still not completely DRY, but it tells the story. And that is much more important to me than the risk of having to change something in more than one place in a spec. As for before or after the action, we did add controller.should_have_rendered for after. We could do something similar: controller.should_have_redirected_to. Or we could do what I originally had in there which was that should_render was smart enough to work on either side of the action. Looking at a few specs, I found that to be more confusing and, hence, split into ''before'' and ''after'' forms. Of these options, what do you like, and what not? Thanks for playing, David> > What''s the right solution? > > Jay Levitt > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Jay Levitt
2006-Nov-07 20:31 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
David Chelimsky wrote:> On 11/7/06, Jay Levitt <lists-rspec at shopwatch.org> wrote: >> I can understand that it''s easier for rspec to set up a mock in advance >> of the controller call. > > This was a philosophical choice, not a cop-out to make it easier to > implement. That sounds more defensive than it is meant to be. I just > want to assure you that our goal is to create the right API.No, I completely understand...> >> But it makes it difficult to do something like: >> >> context "The HarkController, given Louie the logged-in user" do >> setup do >> post :login, :username => ''louie'', :password => ''atest'' >> end > The BDD way, at least as I see it, is rooted in the TDD way: > > 1. setup objects in a known starting state (setup - perhaps stubs) > 2. set expectations of how the object should react to an action (mocks) > 3. perform the action > 4. verify that the object reacted as expected (verify mocks plus > additional assert-like expectations)I think the problem I''m having (and that David Lee is having as well) is that sometimes I''d like setup to involve an action. It seems the answer may be that "the BDD way, at the controller-spec level, is to stub the initial action so you''ve got a known state." I guess I''ve been writing semi-integration specs in that regard.> > The problem there is that it doesn''t feel DRY. That''s a problem I''m > interested in solving, but I''d prefer to do it in a way that helps to > express the behaviour-driven nature of BDD. What that means yet I''m > not sure. I have a couple of ideas that I''ll share as they become > slightly more fully baked. I''d love to hear yours in the mean time.I don''t suppose "It worked in 0.6.4!" counts as an idea? Seriously, I suspect that the arrival of integration specs may solve this, because it could be argued that I''ve really been writing integration specs if my specs involve two or more controller actions. I would intensely dislike the person who argued that, because they''d be making me write more thorough controller-level specs and dive into mocking, but I''d probably forgive them when this made my code more robust. Of course, the problem is that now I don''t have the integration-like functionality that 0.6.4 had, so while I can create stubs to do the right thing at the controller level, I''ve lost the ability to test "X works after logging in".> What I''m doing for examples like yours above is adding a method for > the post and calling it from each of my specify blocks. Still not > completely DRY, but it tells the story. And that is much more > important to me than the risk of having to change something in more > than one place in a spec.To me, that''s what "setup" was for - but, again, can setup legitimately be a controller action? Mmmmmaybe. In any case, as I just discovered, putting the login in a method call won''t work, because rspec no longer likes two controller actions in a single spec, period.> As for before or after the action, we did add > controller.should_have_rendered for after. We could do something > similar: controller.should_have_redirected_to. Or we could do what I > originally had in there which was that should_render was smart enough > to work on either side of the action. Looking at a few specs, I found > that to be more confusing and, hence, split into ''before'' and ''after'' > forms. > > Of these options, what do you like, and what not?I would like "should_render" to be smart; I think the past-tense thing is confusing. Ditto should_redirect_to. But I don''t have very strong feelings about that one. Jay
aslak hellesoy
2006-Nov-07 20:43 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
On 11/7/06, David Chelimsky <dchelimsky at gmail.com> wrote:> On 11/7/06, Jay Levitt <lists-rspec at shopwatch.org> wrote: > > I can understand that it''s easier for rspec to set up a mock in advance > > of the controller call. > > This was a philosophical choice, not a cop-out to make it easier to > implement. That sounds more defensive than it is meant to be. I just > want to assure you that our goal is to create the right API. > > > But it makes it difficult to do something like: > > > > context "The HarkController, given Louie the logged-in user" do > > setup do > > post :login, :username => ''louie'', :password => ''atest'' > > end > > > > specify "should redirect Louie to the home page"... > > > > specify "should set Louie to be the current user"... > > > > end > > > > Instead, I have to break out the should-redirect into its own call, > > since the post is done at setup time, but that''s not an appropriate > > place for a spec. > > The BDD way, at least as I see it, is rooted in the TDD way: > > 1. setup objects in a known starting state (setup - perhaps stubs) > 2. set expectations of how the object should react to an action (mocks) > 3. perform the action > 4. verify that the object reacted as expected (verify mocks plus > additional assert-like expectations) > > The setup/specify structure is intended to let you step 1 (setup) in > the setup and do whatever combination of 2-4 that you like in specify. > In my view, the post is the action, and it belongs in the specify > block in this case. >Agreed. Consider the GWT* format (which I encourage people to use). A typical acceptance criterion similar to your example could be: GIVEN A new HarkController AND Louie logged in WHEN Louie logs out THEN He is redirected to the frontpage context "A new HarkController and Louie logged in" do # GIVEN setup do # GIVEN controller.should_redirect_to :action => ''homepage'' post :login, :username => ''louie'', :password => ''atest'' end specify "Should redirect Louie to the homepage when he logs out" # THEN and WHEN controller.should_redirect_to :action => ''frontpage'' post :logout end end * http://www.dannorth.net/introducing-bdd * http://jayfields.blogspot.com/2006/11/story-card-format.html (My comment) Thinking in terms of GWT and knowing how to map them to RSpec will make spec writing much easier I think.> The problem there is that it doesn''t feel DRY. That''s a problem I''m > interested in solving, but I''d prefer to do it in a way that helps to > express the behaviour-driven nature of BDD. What that means yet I''m > not sure. I have a couple of ideas that I''ll share as they become > slightly more fully baked. I''d love to hear yours in the mean time. > > What I''m doing for examples like yours above is adding a method for > the post and calling it from each of my specify blocks. Still not > completely DRY, but it tells the story. And that is much more > important to me than the risk of having to change something in more > than one place in a spec. > > As for before or after the action, we did add > controller.should_have_rendered for after. We could do something > similar: controller.should_have_redirected_to. Or we could do what I > originally had in there which was that should_render was smart enough > to work on either side of the action. Looking at a few specs, I found > that to be more confusing and, hence, split into ''before'' and ''after'' > forms. > > Of these options, what do you like, and what not? > > Thanks for playing, > David > > > > > > What''s the right solution? > > > > Jay Levitt > > > > _______________________________________________ > > 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 >
aslak hellesoy
2006-Nov-07 20:46 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
On 11/7/06, aslak hellesoy <aslak.hellesoy at gmail.com> wrote:> On 11/7/06, David Chelimsky <dchelimsky at gmail.com> wrote: > > On 11/7/06, Jay Levitt <lists-rspec at shopwatch.org> wrote: > > > I can understand that it''s easier for rspec to set up a mock in advance > > > of the controller call. > > > > This was a philosophical choice, not a cop-out to make it easier to > > implement. That sounds more defensive than it is meant to be. I just > > want to assure you that our goal is to create the right API. > > > > > But it makes it difficult to do something like: > > > > > > context "The HarkController, given Louie the logged-in user" do > > > setup do > > > post :login, :username => ''louie'', :password => ''atest'' > > > end > > > > > > specify "should redirect Louie to the home page"... > > > > > > specify "should set Louie to be the current user"... > > > > > > end > > > > > > Instead, I have to break out the should-redirect into its own call, > > > since the post is done at setup time, but that''s not an appropriate > > > place for a spec. > > > > The BDD way, at least as I see it, is rooted in the TDD way: > > > > 1. setup objects in a known starting state (setup - perhaps stubs) > > 2. set expectations of how the object should react to an action (mocks) > > 3. perform the action > > 4. verify that the object reacted as expected (verify mocks plus > > additional assert-like expectations) > > > > The setup/specify structure is intended to let you step 1 (setup) in > > the setup and do whatever combination of 2-4 that you like in specify. > > In my view, the post is the action, and it belongs in the specify > > block in this case. > > > > Agreed. Consider the GWT* format (which I encourage people to use). A > typical acceptance criterion similar to your example could be: > > GIVEN A new HarkController > AND Louie logged in > WHEN Louie logs out > THEN He is redirected to the frontpage > > context "A new HarkController and Louie logged in" do # GIVEN > setup do # GIVEN > controller.should_redirect_to :action => ''homepage'' > post :login, :username => ''louie'', :password => ''atest''# Or better, since it doesn''t do the extra action: session[:user] = User.new> end > > specify "Should redirect Louie to the homepage when he logs out" # > THEN and WHEN > controller.should_redirect_to :action => ''frontpage'' > post :logout > end > end > > * http://www.dannorth.net/introducing-bdd > * http://jayfields.blogspot.com/2006/11/story-card-format.html (My comment) > > Thinking in terms of GWT and knowing how to map them to RSpec will > make spec writing much easier I think. > > > The problem there is that it doesn''t feel DRY. That''s a problem I''m > > interested in solving, but I''d prefer to do it in a way that helps to > > express the behaviour-driven nature of BDD. What that means yet I''m > > not sure. I have a couple of ideas that I''ll share as they become > > slightly more fully baked. I''d love to hear yours in the mean time. > > > > What I''m doing for examples like yours above is adding a method for > > the post and calling it from each of my specify blocks. Still not > > completely DRY, but it tells the story. And that is much more > > important to me than the risk of having to change something in more > > than one place in a spec. > > > > As for before or after the action, we did add > > controller.should_have_rendered for after. We could do something > > similar: controller.should_have_redirected_to. Or we could do what I > > originally had in there which was that should_render was smart enough > > to work on either side of the action. Looking at a few specs, I found > > that to be more confusing and, hence, split into ''before'' and ''after'' > > forms. > > > > Of these options, what do you like, and what not? > > > > Thanks for playing, > > David > > > > > > > > > > What''s the right solution? > > > > > > Jay Levitt > > > > > > _______________________________________________ > > > 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 > > >
David Chelimsky
2006-Nov-07 20:52 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
On 11/7/06, Jay Levitt <lists-rspec at shopwatch.org> wrote:> David Chelimsky wrote: > > On 11/7/06, Jay Levitt <lists-rspec at shopwatch.org> wrote: > >> I can understand that it''s easier for rspec to set up a mock in advance > >> of the controller call. > > > > This was a philosophical choice, not a cop-out to make it easier to > > implement. That sounds more defensive than it is meant to be. I just > > want to assure you that our goal is to create the right API. > > No, I completely understand... > > > > >> But it makes it difficult to do something like: > >> > >> context "The HarkController, given Louie the logged-in user" do > >> setup do > >> post :login, :username => ''louie'', :password => ''atest'' > >> end > > The BDD way, at least as I see it, is rooted in the TDD way: > > > > 1. setup objects in a known starting state (setup - perhaps stubs) > > 2. set expectations of how the object should react to an action (mocks) > > 3. perform the action > > 4. verify that the object reacted as expected (verify mocks plus > > additional assert-like expectations) > > I think the problem I''m having (and that David Lee is having as well) is > that sometimes I''d like setup to involve an action. It seems the answer > may be that "the BDD way, at the controller-spec level, is to stub the > initial action so you''ve got a known state." I guess I''ve been writing > semi-integration specs in that regard.I can see this if you need one action to get you to a state and another to set expectations about. I wonder if we can get the state correct a different way - like setting the user in the session. The problem becomes when the login breaks for some reason, under some conditions, and other specs fail because you''re using the login action everywhere. Make sense?> > > > The problem there is that it doesn''t feel DRY. That''s a problem I''m > > interested in solving, but I''d prefer to do it in a way that helps to > > express the behaviour-driven nature of BDD. What that means yet I''m > > not sure. I have a couple of ideas that I''ll share as they become > > slightly more fully baked. I''d love to hear yours in the mean time. > > I don''t suppose "It worked in 0.6.4!" counts as an idea?:) The original plugin was a great solution to the wrong problem. It was a way to get rails coverage in rspec as a test/unit substitute w/ sexy should_be_this_and_that syntax. Everyone (including me) was excited to be able to do SOMETHING vis a vis rails. It was not, however, considered very deeply in the context of a BDD framework. Until we get to 1.0, I think we all just need to live w/ some changes to the API. I''m confident that what is in place now will not change significantly, and that we''ll mostly be adding to it and not changing what''s there. That said, I feel, and I think I speak for the rest of the committers, that it''s more important to get the right API than to be constrained by the hacks that came before. If we start living within that constraint, we''ll have no choice but to stop adding new stuff at the rate at which we do. Make sense?> Seriously, I suspect that the arrival of integration specs may solve > this, because it could be argued that I''ve really been writing > integration specs if my specs involve two or more controller actions. I > would intensely dislike the person who argued that, because they''d be > making me write more thorough controller-level specs and dive into > mocking, but I''d probably forgive them when this made my code more robust. > > Of course, the problem is that now I don''t have the integration-like > functionality that 0.6.4 had, so while I can create stubs to do the > right thing at the controller level, I''ve lost the ability to test "X > works after logging in".That''s a problem - we''ll solve it.> > > What I''m doing for examples like yours above is adding a method for > > the post and calling it from each of my specify blocks. Still not > > completely DRY, but it tells the story. And that is much more > > important to me than the risk of having to change something in more > > than one place in a spec. > > To me, that''s what "setup" was for - but, again, can setup legitimately > be a controller action? Mmmmmaybe.Ditto what I was saying before. You could argue that you should be able to do anything you need to do in the setup to get you there. I''d agree with that argument. But I''d hate to have dependencies across two actions in what are supposed to be very granular specs.> > In any case, as I just discovered, putting the login in a method call > won''t work, because rspec no longer likes two controller actions in a > single spec, period.We''re going to have to solve that for integration specs. When we do, we''ll be able to support it in controller specs too.> > As for before or after the action, we did add > > controller.should_have_rendered for after. We could do something > > similar: controller.should_have_redirected_to. Or we could do what I > > originally had in there which was that should_render was smart enough > > to work on either side of the action. Looking at a few specs, I found > > that to be more confusing and, hence, split into ''before'' and ''after'' > > forms. > > > > Of these options, what do you like, and what not? > > I would like "should_render" to be smart; I think the past-tense thing > is confusing. Ditto should_redirect_to. But I don''t have very strong > feelings about that one.My thinking right now is that we''ll support definitely before and after one way or the other. The question then becomes whether we use the past tense or not. My inclination is to use it in order to expose the differences between before and after. I think it will help to understand failures when you go back to look at a spec you wrote some time ago. Other opinions?> > JayAgain, thanks for playing. This is the sort of feedback we need more of. Cheers, David> > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
David Chelimsky
2006-Nov-08 01:14 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
On 11/7/06, aslak hellesoy <aslak.hellesoy at gmail.com> wrote:> On 11/7/06, aslak hellesoy <aslak.hellesoy at gmail.com> wrote: > > On 11/7/06, David Chelimsky <dchelimsky at gmail.com> wrote: > > > On 11/7/06, Jay Levitt <lists-rspec at shopwatch.org> wrote: > > > > I can understand that it''s easier for rspec to set up a mock in advance > > > > of the controller call. > > > > > > This was a philosophical choice, not a cop-out to make it easier to > > > implement. That sounds more defensive than it is meant to be. I just > > > want to assure you that our goal is to create the right API. > > > > > > > But it makes it difficult to do something like: > > > > > > > > context "The HarkController, given Louie the logged-in user" do > > > > setup do > > > > post :login, :username => ''louie'', :password => ''atest'' > > > > end > > > > > > > > specify "should redirect Louie to the home page"... > > > > > > > > specify "should set Louie to be the current user"... > > > > > > > > end > > > > > > > > Instead, I have to break out the should-redirect into its own call, > > > > since the post is done at setup time, but that''s not an appropriate > > > > place for a spec. > > > > > > The BDD way, at least as I see it, is rooted in the TDD way: > > > > > > 1. setup objects in a known starting state (setup - perhaps stubs) > > > 2. set expectations of how the object should react to an action (mocks) > > > 3. perform the action > > > 4. verify that the object reacted as expected (verify mocks plus > > > additional assert-like expectations) > > > > > > The setup/specify structure is intended to let you step 1 (setup) in > > > the setup and do whatever combination of 2-4 that you like in specify. > > > In my view, the post is the action, and it belongs in the specify > > > block in this case. > > > > > > > Agreed. Consider the GWT* format (which I encourage people to use). A > > typical acceptance criterion similar to your example could be: > > > > GIVEN A new HarkController > > AND Louie logged in > > WHEN Louie logs out > > THEN He is redirected to the frontpage > > > > context "A new HarkController and Louie logged in" do # GIVEN > > setup do # GIVEN > > controller.should_redirect_to :action => ''homepage'' > > post :login, :username => ''louie'', :password => ''atest'' > > # Or better, since it doesn''t do the extra action: > session[:user] = User.newI like that a LOT better, because a failure in the login process won''t cause this spec to fail. Better isolation. Thanks, David> > > end > > > > specify "Should redirect Louie to the homepage when he logs out" # > > THEN and WHEN > > controller.should_redirect_to :action => ''frontpage'' > > post :logout > > end > > end > > > > * http://www.dannorth.net/introducing-bdd > > * http://jayfields.blogspot.com/2006/11/story-card-format.html (My comment) > > > > Thinking in terms of GWT and knowing how to map them to RSpec will > > make spec writing much easier I think. > > > > > The problem there is that it doesn''t feel DRY. That''s a problem I''m > > > interested in solving, but I''d prefer to do it in a way that helps to > > > express the behaviour-driven nature of BDD. What that means yet I''m > > > not sure. I have a couple of ideas that I''ll share as they become > > > slightly more fully baked. I''d love to hear yours in the mean time. > > > > > > What I''m doing for examples like yours above is adding a method for > > > the post and calling it from each of my specify blocks. Still not > > > completely DRY, but it tells the story. And that is much more > > > important to me than the risk of having to change something in more > > > than one place in a spec. > > > > > > As for before or after the action, we did add > > > controller.should_have_rendered for after. We could do something > > > similar: controller.should_have_redirected_to. Or we could do what I > > > originally had in there which was that should_render was smart enough > > > to work on either side of the action. Looking at a few specs, I found > > > that to be more confusing and, hence, split into ''before'' and ''after'' > > > forms. > > > > > > Of these options, what do you like, and what not? > > > > > > Thanks for playing, > > > David > > > > > > > > > > > > > > What''s the right solution? > > > > > > > > Jay Levitt > > > > > > > > _______________________________________________ > > > > 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 >
Bryan Helmkamp
2006-Nov-08 07:53 UTC
[rspec-users] should_redirect_to in advance - feels unnatural
On 11/7/06, David Chelimsky <dchelimsky at gmail.com> wrote:> On 11/7/06, aslak hellesoy <aslak.hellesoy at gmail.com> wrote: > > # Or better, since it doesn''t do the extra action: > > session[:user] = User.new > > I like that a LOT better, because a failure in the login process won''t > cause this spec to fail. Better isolation.On one of my projects, I do this in the setup method a lot: @controller.expects(:logged_in?).returns(true) That''s a one liner that made me love mocks. -Bryan -- http://www.MyCongress.org/ -- coming soon
Maybe Matching Threads
- Problems translating should_render from 0.8.2 to 1.0.5
- Some tips for testing respond_to block and making controller tests work with simply_helpful
- Collection proxies need to be stubbed ?
- should_redirect_to in rspec-0.8.0 / rspec_on_rails 1453
- I lost the RSpec fight