So, I''ve been following the recommendations for controller specs here: http://blog.davidchelimsky.net/articles/2006/11/09/tutorial-rspec-stubs-and-mocks Most notably: a single expectation per specify block; the setup block contains only stubs; mock expectations each get their own specify block. (I''m still using 0.8, so I haven''t gotten the describe/it goodness yet.) I don''t really mind the stub/mock duplication (between setup and the specifications). What''s annoying me is the action duplication. "get ''create''" is called in each specify block, sometimes before the actual specification, sometimes afterward, depending on whether it''s a mock expectation or a state expectation. So I played around with creating the following module and then extending my context with it. module MockSpecHelpers def expect_that_it(msg) specify msg do yield action end end def then_it(msg) specify msg do action yield end end end in the context block, I would then "def action do get ''create'' end". And I would replace the following specify blocks specify "should create a new person on GET to create" do Person.should_receive(:new).and_return(@person) get ''create'' end specify "should assign new person to template on GET to create" do get ''create'' assigns[:person].should_be @person end with expect_that_it "should create a new person on GET to create" do Person.should_receive(:new).and_return(@person) end then_it "should assign new person to template on GET to create" do assigns[:person].should_be @person end The problem is that my weak Ruby metaprogramming fu has completely failed me. :-) I can''t figure out how to get the block to be evaluated in a context that has access to the appropriate context methods (assigns, response, session, etc). I get errors like the following: NameError in ''GET /controller/action/1234 should render the foobar template'' undefined local variable or method `response'' for #<Spec::Runner::ContextEvalModule:0xb6def95c> (Usually the "expect_that_it" blocks work fine, because they aren''t dependent on anything that is specific to their EvalContext.) Does someone know how I could get this working? I also thought about making an alias for setup called "given" and instead of "action" it could be "when_action" to more closely follow the "given/expect/when/then" pattern and naming conventions. Does this even look like a good idea, or is there a better way? Would it make more sense to open the EvalContext rather than trying to extend a module? -- Nick
Your''s is a good question. I too have been looking for ways to DRY up my controller tests. The more I am starting to obey a CRUD-only design, the more duplication I am encountering in these specs. Right now, I am combating this dilemma by making a bunch of methods in spec_helper that define _context_ and _specify_ statements, such as: def specify_should_handle_an_invalid_id_nicely(params) controller = "#{params[:controller].camelize}Controller" model = params[:controller].classify.constantize params[:redirect_to] ||= { :action => ''index'' } params[:actions] ||= [:edit, :update, :show, :destroy] params[:actions].to_a.each do |action| context "#{controller}##{action}, given an id" do controller_name params[:controller] specify "should call #{model}.find_by_id, instead of #{model}.find" do model.should_receive(:find_by_id).with("the id") send(:process, action, :id => "the id") end end context "#{controller}##{action}, not given a valid id" do controller_name params[:controller] setup do model.stub!(:find_by_id) end specify "should redirect_to #{params[:redirect_to]}" do send(:process, action) response.should_redirect_to params[:redirect_to] end specify "should populate the flash with a message indicating that the record wasn''t found" do send(:process, action) flash[:notice].should == "#{model} not found" end end end end This approach is obviously clunky, and I would myself like a better way to specify controller-wide contracts, as it were. Just as above, any action that requires an id as a parameter should behave a certain way, and I shouldn''t have to define this behavior in each controller''s specification; it should be application-wide. -Chris On 4/11/07, nicholas a. evans <nick at ekenosen.net> wrote:> So, I''ve been following the recommendations for controller specs here: > http://blog.davidchelimsky.net/articles/2006/11/09/tutorial-rspec-stubs-and-mocks > > Most notably: a single expectation per specify block; the setup block > contains only stubs; mock expectations each get their own specify > block. (I''m still using 0.8, so I haven''t gotten the describe/it > goodness yet.) > > I don''t really mind the stub/mock duplication (between setup and the > specifications). What''s annoying me is the action duplication. "get > ''create''" is called in each specify block, sometimes before the actual > specification, sometimes afterward, depending on whether it''s a mock > expectation or a state expectation. > > So I played around with creating the following module and then > extending my context with it. > > module MockSpecHelpers > def expect_that_it(msg) > specify msg do > yield > action > end > end > def then_it(msg) > specify msg do > action > yield > end > end > end > > in the context block, I would then "def action do get ''create'' end". > And I would replace the following specify blocks > > specify "should create a new person on GET to create" do > Person.should_receive(:new).and_return(@person) > get ''create'' > end > > specify "should assign new person to template on GET to create" do > get ''create'' > assigns[:person].should_be @person > end > > with > > expect_that_it "should create a new person on GET to create" do > Person.should_receive(:new).and_return(@person) > end > > then_it "should assign new person to template on GET to create" do > assigns[:person].should_be @person > end > > The problem is that my weak Ruby metaprogramming fu has completely > failed me. :-) I can''t figure out how to get the block to be > evaluated in a context that has access to the appropriate context > methods (assigns, response, session, etc). I get errors like the > following: > > NameError in ''GET /controller/action/1234 should render the foobar template'' > undefined local variable or method `response'' for > #<Spec::Runner::ContextEvalModule:0xb6def95c> > > (Usually the "expect_that_it" blocks work fine, because they aren''t > dependent on anything that is specific to their EvalContext.) > > Does someone know how I could get this working? > > I also thought about making an alias for setup called "given" and > instead of "action" it could be "when_action" to more closely follow > the "given/expect/when/then" pattern and naming conventions. > > Does this even look like a good idea, or is there a better way? Would > it make more sense to open the EvalContext rather than trying to > extend a module? > > -- > Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On 4/27/07, Chris Hoffman <bosshoff at gmail.com> wrote:> Your''s is a good question. I too have been looking for ways to DRY up > my controller tests. The more I am starting to obey a CRUD-only > design, the more duplication I am encountering in these specs. Right > now, I am combating this dilemma by making a bunch of methods in > spec_helper that define _context_ and _specify_ statements, such as: > > def specify_should_handle_an_invalid_id_nicely(params) > controller = "#{params[:controller].camelize}Controller" > model = params[:controller].classify.constantize > params[:redirect_to] ||= { :action => ''index'' } > params[:actions] ||= [:edit, :update, :show, :destroy] > > params[:actions].to_a.each do |action| > context "#{controller}##{action}, given an id" do > controller_name params[:controller] > > specify "should call #{model}.find_by_id, instead of #{model}.find" do > model.should_receive(:find_by_id).with("the id") > send(:process, action, :id => "the id") > end > end > > context "#{controller}##{action}, not given a valid id" do > controller_name params[:controller] > > setup do > model.stub!(:find_by_id) > end > > specify "should redirect_to #{params[:redirect_to]}" do > send(:process, action) > response.should_redirect_to params[:redirect_to] > end > > specify "should populate the flash with a message indicating > that the record wasn''t found" do > send(:process, action) > flash[:notice].should == "#{model} not found" > end > end > end > end > > This approach is obviously clunky, and I would myself like a better > way to specify controller-wide contracts, as it were. Just as above, > any action that requires an id as a parameter should behave a certain > way, and I shouldn''t have to define this behavior in each controller''s > specification; it should be application-wide.Would http://rubyforge.org/tracker/?func=detail&group_id=797&aid=9605&atid=3151 satisfy your needs?
That has some potential, indeed. Is there a URL you can point me to that will instruct me on how to install the HEAD of the RSpec repository? It looks like I require 0.9 to take advantage of this patch. Thanks. -Chris On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote:> On 4/27/07, Chris Hoffman <bosshoff at gmail.com> wrote: > > Your''s is a good question. I too have been looking for ways to DRY up > > my controller tests. The more I am starting to obey a CRUD-only > > design, the more duplication I am encountering in these specs. Right > > now, I am combating this dilemma by making a bunch of methods in > > spec_helper that define _context_ and _specify_ statements, such as: > > > > def specify_should_handle_an_invalid_id_nicely(params) > > controller = "#{params[:controller].camelize}Controller" > > model = params[:controller].classify.constantize > > params[:redirect_to] ||= { :action => ''index'' } > > params[:actions] ||= [:edit, :update, :show, :destroy] > > > > params[:actions].to_a.each do |action| > > context "#{controller}##{action}, given an id" do > > controller_name params[:controller] > > > > specify "should call #{model}.find_by_id, instead of #{model}.find" do > > model.should_receive(:find_by_id).with("the id") > > send(:process, action, :id => "the id") > > end > > end > > > > context "#{controller}##{action}, not given a valid id" do > > controller_name params[:controller] > > > > setup do > > model.stub!(:find_by_id) > > end > > > > specify "should redirect_to #{params[:redirect_to]}" do > > send(:process, action) > > response.should_redirect_to params[:redirect_to] > > end > > > > specify "should populate the flash with a message indicating > > that the record wasn''t found" do > > send(:process, action) > > flash[:notice].should == "#{model} not found" > > end > > end > > end > > end > > > > This approach is obviously clunky, and I would myself like a better > > way to specify controller-wide contracts, as it were. Just as above, > > any action that requires an id as a parameter should behave a certain > > way, and I shouldn''t have to define this behavior in each controller''s > > specification; it should be application-wide. > > Would http://rubyforge.org/tracker/?func=detail&group_id=797&aid=9605&atid=3151 > satisfy your needs? > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On 4/11/07, nicholas a. evans <nick at ekenosen.net> wrote:> So, I''ve been following the recommendations for controller specs here: > http://blog.davidchelimsky.net/articles/2006/11/09/tutorial-rspec-stubs-and-mocks > > Most notably: a single expectation per specify block; the setup block > contains only stubs; mock expectations each get their own specify > block. (I''m still using 0.8, so I haven''t gotten the describe/it > goodness yet.) > > I don''t really mind the stub/mock duplication (between setup and the > specifications). What''s annoying me is the action duplication. "get > ''create''" is called in each specify block, sometimes before the actual > specification, sometimes afterward, depending on whether it''s a mock > expectation or a state expectation. > > So I played around with creating the following module and then > extending my context with it. > > module MockSpecHelpers > def expect_that_it(msg) > specify msg do > yield > action > end > end > def then_it(msg) > specify msg do > action > yield > end > end > end > > in the context block, I would then "def action do get ''create'' end". > And I would replace the following specify blocks > > specify "should create a new person on GET to create" do > Person.should_receive(:new).and_return(@person) > get ''create'' > end > > specify "should assign new person to template on GET to create" do > get ''create'' > assigns[:person].should_be @person > end > > with > > expect_that_it "should create a new person on GET to create" do > Person.should_receive(:new).and_return(@person) > end > > then_it "should assign new person to template on GET to create" do > assigns[:person].should_be @person > endI like the idea of binding the examples to some method that gets run before or after the example. There is a similar RFE already in the tracker http://rubyforge.org/tracker/?func=detail&group_id=797&aid=10285&atid=3152. The problem is coming up with the right language. It think expect_that_it and then_it would encourage one to write all of the expect_that_its first and the then_its last. It also seems to indicate a relationship between the examples, even though no such relationship exists. In the RFE I mentioned, I proposed something like ... it "should do something", during_event do That seems to work well, but its counterpart ... it "should leave some state", after_event do leaves me cold. It especially fails to align w/ your example "should assign new person to template on GET to create", which seems like a great way to express the behaviour, but followed by "after_event" doesn''t really read correctly. Any other suggestions? In general, I''m much more inclined to favor an additional parameter passed to #it over a new method name. Cheers, David
On 4/27/07, Chris Hoffman <chris.c.hoffman at gmail.com> wrote:> That has some potential, indeed. Is there a URL you can point me to > that will instruct me on how to install the HEAD of the RSpec > repository? It looks like I require 0.9 to take advantage of this > patch. Thanks.Actually, the patch hasn''t been applied yet. I was just asking to get your opinion. As for using trunk in a rails project, take a look at http://rspec.rubyforge.org/documentation/rails/install.html. Cheers, David> > -Chris > > On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > On 4/27/07, Chris Hoffman <bosshoff at gmail.com> wrote: > > > Your''s is a good question. I too have been looking for ways to DRY up > > > my controller tests. The more I am starting to obey a CRUD-only > > > design, the more duplication I am encountering in these specs. Right > > > now, I am combating this dilemma by making a bunch of methods in > > > spec_helper that define _context_ and _specify_ statements, such as: > > > > > > def specify_should_handle_an_invalid_id_nicely(params) > > > controller = "#{params[:controller].camelize}Controller" > > > model = params[:controller].classify.constantize > > > params[:redirect_to] ||= { :action => ''index'' } > > > params[:actions] ||= [:edit, :update, :show, :destroy] > > > > > > params[:actions].to_a.each do |action| > > > context "#{controller}##{action}, given an id" do > > > controller_name params[:controller] > > > > > > specify "should call #{model}.find_by_id, instead of #{model}.find" do > > > model.should_receive(:find_by_id).with("the id") > > > send(:process, action, :id => "the id") > > > end > > > end > > > > > > context "#{controller}##{action}, not given a valid id" do > > > controller_name params[:controller] > > > > > > setup do > > > model.stub!(:find_by_id) > > > end > > > > > > specify "should redirect_to #{params[:redirect_to]}" do > > > send(:process, action) > > > response.should_redirect_to params[:redirect_to] > > > end > > > > > > specify "should populate the flash with a message indicating > > > that the record wasn''t found" do > > > send(:process, action) > > > flash[:notice].should == "#{model} not found" > > > end > > > end > > > end > > > end > > > > > > This approach is obviously clunky, and I would myself like a better > > > way to specify controller-wide contracts, as it were. Just as above, > > > any action that requires an id as a parameter should behave a certain > > > way, and I shouldn''t have to define this behavior in each controller''s > > > specification; it should be application-wide. > > > > Would http://rubyforge.org/tracker/?func=detail&group_id=797&aid=9605&atid=3151 > > satisfy your needs? > > _______________________________________________ > > 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 >
Oh, so I wouldn''t be able to take advantage of the patch if I applied it myself (e.g., lots of bugs )? I''m sure you can glean my opinion of the idea from the fact that I would like to start using it right away :) It seems like a generalized solution that wouldn''t be specific to rails, but easily amenable to it, which works for me. -Chris On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote:> On 4/27/07, Chris Hoffman <chris.c.hoffman at gmail.com> wrote: > > That has some potential, indeed. Is there a URL you can point me to > > that will instruct me on how to install the HEAD of the RSpec > > repository? It looks like I require 0.9 to take advantage of this > > patch. Thanks. > > Actually, the patch hasn''t been applied yet. I was just asking to get > your opinion. > > As for using trunk in a rails project, take a look at > http://rspec.rubyforge.org/documentation/rails/install.html. > > Cheers, > David > > > > > > > -Chris > > > > On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > > On 4/27/07, Chris Hoffman <bosshoff at gmail.com> wrote: > > > > Your''s is a good question. I too have been looking for ways to DRY up > > > > my controller tests. The more I am starting to obey a CRUD-only > > > > design, the more duplication I am encountering in these specs. Right > > > > now, I am combating this dilemma by making a bunch of methods in > > > > spec_helper that define _context_ and _specify_ statements, such as: > > > > > > > > def specify_should_handle_an_invalid_id_nicely(params) > > > > controller = "#{params[:controller].camelize}Controller" > > > > model = params[:controller].classify.constantize > > > > params[:redirect_to] ||= { :action => ''index'' } > > > > params[:actions] ||= [:edit, :update, :show, :destroy] > > > > > > > > params[:actions].to_a.each do |action| > > > > context "#{controller}##{action}, given an id" do > > > > controller_name params[:controller] > > > > > > > > specify "should call #{model}.find_by_id, instead of #{model}.find" do > > > > model.should_receive(:find_by_id).with("the id") > > > > send(:process, action, :id => "the id") > > > > end > > > > end > > > > > > > > context "#{controller}##{action}, not given a valid id" do > > > > controller_name params[:controller] > > > > > > > > setup do > > > > model.stub!(:find_by_id) > > > > end > > > > > > > > specify "should redirect_to #{params[:redirect_to]}" do > > > > send(:process, action) > > > > response.should_redirect_to params[:redirect_to] > > > > end > > > > > > > > specify "should populate the flash with a message indicating > > > > that the record wasn''t found" do > > > > send(:process, action) > > > > flash[:notice].should == "#{model} not found" > > > > end > > > > end > > > > end > > > > end > > > > > > > > This approach is obviously clunky, and I would myself like a better > > > > way to specify controller-wide contracts, as it were. Just as above, > > > > any action that requires an id as a parameter should behave a certain > > > > way, and I shouldn''t have to define this behavior in each controller''s > > > > specification; it should be application-wide. > > > > > > Would http://rubyforge.org/tracker/?func=detail&group_id=797&aid=9605&atid=3151 > > > satisfy your needs? > > > _______________________________________________ > > > 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 4/27/07, Chris Hoffman <chris.c.hoffman at gmail.com> wrote:> Oh, so I wouldn''t be able to take advantage of the patch if I applied > it myself (e.g., lots of bugs )?We haven''t tried to apply it. It might work just fine. Aslak and I need to take a closer look at it before we agree to apply it and there are other priorities for both of us both in and out of rspec at the moment. If you do apply it and it works, please report to this list about your experience. Cheers, David> I''m sure you can glean my opinion of > the idea from the fact that I would like to start using it right away > :) > > It seems like a generalized solution that wouldn''t be specific to > rails, but easily amenable to it, which works for me. > > -Chris > > On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > On 4/27/07, Chris Hoffman <chris.c.hoffman at gmail.com> wrote: > > > That has some potential, indeed. Is there a URL you can point me to > > > that will instruct me on how to install the HEAD of the RSpec > > > repository? It looks like I require 0.9 to take advantage of this > > > patch. Thanks. > > > > Actually, the patch hasn''t been applied yet. I was just asking to get > > your opinion. > > > > As for using trunk in a rails project, take a look at > > http://rspec.rubyforge.org/documentation/rails/install.html. > > > > Cheers, > > David > > > > > > > > > > > > -Chris > > > > > > On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > > > On 4/27/07, Chris Hoffman <bosshoff at gmail.com> wrote: > > > > > Your''s is a good question. I too have been looking for ways to DRY up > > > > > my controller tests. The more I am starting to obey a CRUD-only > > > > > design, the more duplication I am encountering in these specs. Right > > > > > now, I am combating this dilemma by making a bunch of methods in > > > > > spec_helper that define _context_ and _specify_ statements, such as: > > > > > > > > > > def specify_should_handle_an_invalid_id_nicely(params) > > > > > controller = "#{params[:controller].camelize}Controller" > > > > > model = params[:controller].classify.constantize > > > > > params[:redirect_to] ||= { :action => ''index'' } > > > > > params[:actions] ||= [:edit, :update, :show, :destroy] > > > > > > > > > > params[:actions].to_a.each do |action| > > > > > context "#{controller}##{action}, given an id" do > > > > > controller_name params[:controller] > > > > > > > > > > specify "should call #{model}.find_by_id, instead of #{model}.find" do > > > > > model.should_receive(:find_by_id).with("the id") > > > > > send(:process, action, :id => "the id") > > > > > end > > > > > end > > > > > > > > > > context "#{controller}##{action}, not given a valid id" do > > > > > controller_name params[:controller] > > > > > > > > > > setup do > > > > > model.stub!(:find_by_id) > > > > > end > > > > > > > > > > specify "should redirect_to #{params[:redirect_to]}" do > > > > > send(:process, action) > > > > > response.should_redirect_to params[:redirect_to] > > > > > end > > > > > > > > > > specify "should populate the flash with a message indicating > > > > > that the record wasn''t found" do > > > > > send(:process, action) > > > > > flash[:notice].should == "#{model} not found" > > > > > end > > > > > end > > > > > end > > > > > end > > > > > > > > > > This approach is obviously clunky, and I would myself like a better > > > > > way to specify controller-wide contracts, as it were. Just as above, > > > > > any action that requires an id as a parameter should behave a certain > > > > > way, and I shouldn''t have to define this behavior in each controller''s > > > > > specification; it should be application-wide. > > > > > > > > Would http://rubyforge.org/tracker/?func=detail&group_id=797&aid=9605&atid=3151 > > > > satisfy your needs? > > > > _______________________________________________ > > > > 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 > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote:> I like the idea of binding the examples to some method that gets run > before or after the example. There is a similar RFE already in the > tracker http://rubyforge.org/tracker/?func=detail&group_id=797&aid=10285&atid=3152.I hadn''t seen that one. I was originally also thinking about some sort of magic handling whereby mocks are automatically run before and state expectations are automatically run afterwards. But I agree with you: that magic comes at the cost of losing much clarity.> The problem is coming up with the right language.Yes.> In the RFE I mentioned, I proposed something like ... > > it "should do something", during_event doI like that a *lot*. :-)> That seems to work well, but its counterpart ... > > it "should leave some state", after_event do > > leaves me cold. It especially fails to align w/ your example "should > assign new person to template on GET to create", which seems like a > great way to express the behaviour, but followed by "after_event" > doesn''t really read correctly.Could during_event, before_event, after_event, when_event, by_end_of_event, on_event (and perhaps some number of other aliases with the same similar before/after behaviour, but different names for readability in different contexts) also be made to append text to the specification string? Likewise, the event itself could include a description. e.g. describe PeopleController do before do @person = mock_model(Person) Person.stub!(:new).and_return(@person) end event "GET to #create" do get "create", :foo => "bar" end it "should create a new person", during_event do Person.should_receive(:new).and_return(@person) end it "should assign new person to template", on_event do assigns[:person].should_be @person end end could generate the following sentences: PeopleController should create a new person during GET to #create PeopleController should assign new person to template on GET to #create What do you think of that? I''m still not sure that "on_event" clearly represents "event then expectation" as clearly as something else might... but it works for me, and it produces the nice string.> In general, I''m much more inclined to favor an additional parameter > passed to #it over a new method name.Yeah, I hadn''t even thought about something like that. I like it a *lot*. -- Nick
On 4/27/07, nicholas a. evans <nick at ekenosen.net> wrote:> On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote: > > I like the idea of binding the examples to some method that gets run > > before or after the example. There is a similar RFE already in the > > tracker http://rubyforge.org/tracker/?func=detail&group_id=797&aid=10285&atid=3152. > > I hadn''t seen that one. I was originally also thinking about some > sort of magic handling whereby mocks are automatically run before and > state expectations are automatically run afterwards. But I agree with > you: that magic comes at the cost of losing much clarity. > > > The problem is coming up with the right language. > > Yes. > > > In the RFE I mentioned, I proposed something like ... > > > > it "should do something", during_event do > > I like that a *lot*. :-) > > > That seems to work well, but its counterpart ... > > > > it "should leave some state", after_event do > > > > leaves me cold. It especially fails to align w/ your example "should > > assign new person to template on GET to create", which seems like a > > great way to express the behaviour, but followed by "after_event" > > doesn''t really read correctly. > > Could during_event, before_event, after_event, when_event, > by_end_of_event, on_event (and perhaps some number of other aliases > with the same similar before/after behaviour, but different names for > readability in different contexts) also be made to append text to the > specification string? Likewise, the event itself could include a > description. > > e.g. > > describe PeopleController do > before do > @person = mock_model(Person) > Person.stub!(:new).and_return(@person) > end > event "GET to #create" do > get "create", :foo => "bar" > end > it "should create a new person", during_event do > Person.should_receive(:new).and_return(@person) > end > it "should assign new person to template", on_event do > assigns[:person].should_be @person > end > end > > could generate the following sentences: > > PeopleController should create a new person during GET to #create > PeopleController should assign new person to template on GET to #create > > What do you think of that? I''m still not sure that "on_event" clearly > represents "event then expectation" as clearly as something else > might... but it works for me, and it produces the nice string.Very nice! The trick is that we''re merging to concepts here - trying to express the intent of the example and also have it execute the right things in the right order. Words like "during" or "on" are there to coerce rspec to execute things in the right order but they mean the same thing to me in terms of expressing the example - the "when" in GWT. I''d love to come up with words that serve both execution and expression equally. Any other ideas?> > > In general, I''m much more inclined to favor an additional parameter > > passed to #it over a new method name. > > Yeah, I hadn''t even thought about something like that. I like it a *lot*. > > -- > Nick > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On 4/27/07, David Chelimsky <dchelimsky at gmail.com> wrote:> Very nice! The trick is that we''re merging to concepts here - trying > to express the intent of the example and also have it execute the > right things in the right order. Words like "during" or "on" are there > to coerce rspec to execute things in the right order but they mean the > same thing to me in terms of expressing the example - the "when" in > GWT. I''d love to come up with words that serve both execution and > expression equally. Any other ideas?It seems to be a hard problem... Ideas for before_event: * during_event I really like that one, and I can''t come up with anything better... to me it communicates the execution order. Ideas for after_event: * with_event * by_the_end_of_event * by_event * upon_event PeopleController should assign new person to template with a GET to create PeopleController should assign new person to template by the end of a GET to create PeopleController should assign new person to template upon a GET to create (I added changed the event string to "a GET to create".) Both "upon" and "by_the_end_of it" seem evident to me that the expectations would need to run after the event. Is it getting closer to something good? -- Nick