[rspec-users] Data-wise context combination for controller speccing

Matt Wynne matt at mattwynne.net
Mon Jul 19 04:58:50 EDT 2010


On 18 Jul 2010, at 00:10, David Chelimsky wrote:

> On Jul 17, 2010, at 1:18 PM, Costa Shapiro wrote:
> 
>> Hello,
>> 
>> I've been thinking of how to express my idea in code, but since I've never been involved in RSpec development, I'd better have some feedback here first.
>> The feature suggestion below applies to any controller-like code under spec, i.e. a stateless module producing output or just altering its data store (it doesn't necessarily have to be a C of the MVC, but I suppose merb/rails developers will particularly appreciate it).
>> 
>> Here is a skimmed sample to illustrate the pain:
>> 
>>     describe BookController do
>>     
>>       context "registering a book" do
>>     
>>         specify "from a new author on a new subject" do
>>           auth = mock(:name => 'John Doe')
>>           Author.should_receive(:find_
>> by_name).and_return(nil)
>>           Author.should_receive(:new).and_return(auth)
>>           auth.should_receive(:save).and_return(true)
>>     
>>           subj = mock(:short => 'Mockery')
>>           Subject.should_receive(:find_by_short).and_return(nil)
>>           Subject.should_receive(:new).and_return(subj)
>>           subj.should_receive(:save).and_return(true)
>>     
>>           title = 'Specs on Steroids'
>>     
>>           book = mock
>>           Book.should_receive(:new).and_return(book)
>>           book.should_receive(:save).and_return(true)
>>     
>>           post :register :author => auth.name, :title => title, :subject => subj.short
>>           response.should be_success
>>         end
>>     
>>         specify "from a known author on a new subject" do
>>           auth = mock(:name => 'Joe Dohn')
>>           Author.should_receive(:find_by_name).and_return(auth)
>>     
>>           subj = mock(:short => 'Mockery')
>>           Subject.should_receive(:find_by_short).and_return(nil)
>>           Subject.should_receive(:new).and_return(subj)
>>           subj.should_receive(:save).and_return(true)
>>     
>>           title = 'Specs on Steroids II'
>>     
>>           book = mock
>>           Book.should_receive(:new).and_return(book)
>>           book.should_receive(:save).and_return(true)
>>     
>>           post :register :author => auth.name, :title => title, :subject => subj.short
>>           response.should be_success
>>         end
>>     
>>         specify "from a known author on a known subject" do
>>           auth = mock(:name => 'Joe Dohn')
>>           Author.should_receive(:find_by_name).and_return(auth)
>>     
>>           subj = mock(:short => 'Forgery')
>>           Subject.should_receive(:find_by_short).and_return(subj)
>>     
>>           #...
>>         end
>>     
>>         specify "from a new author on a known subject" do
>>           #...
>>         end
>>       end
>>     end
>> 
>> 
>> And this is what I have in mind for doing exactly the same job:
>> 
>>     describe BookController do
>>     
>>       context "registering a book" do
>>     
>>         before :any, "from a new author", :author do
>>           @auth = mock(:name => 'John Doe')
>>           Author.should_receive(:find_by_name).and_return(nil)
>>           Author.should_receive(:new).and_return(@auth)
>>           @auth.should_receive(:save).and_return(true)
>>         end
>>     
>>         before :any, "from a known author", :author do
>>           @auth = mock(:name => 'Joe Dohn')
>>           Author.should_receive(:find_by_name).and_return(@auth)
>>         end
>>     
>>         before :any, "on a new subject", :subject do
>>           @subj = mock(:short => 'Mockery')
>>           Subject.should_receive(:find_by_short).and_return(nil)
>>           Subject.should_receive(:new).and_return(@subj)
>>           @subj.should_receive(:save).and_return(true)
>>         end
>>     
>>         before :any, "on a known subject", :subject do
>>             @subj = mock(:name => 'Joe Dohn')
>>             Subject.should_receive(:find_by_name).and_return(@subj)
>>         end
>>     
>>         it "should succeed", :with => [:author, :subject] do
>>           title = 'Specs on Steroids X'
>>     
>>           post :register :author => @auth.name, :title => title, :subject => @subj.short
>>           response.should be_success
>>         end
>>       end
>>     end
>> 
>> A run of such specs will effectively multiply the tests — automatically — choosing before and after blocks as specified.
>> I'm sorry, I haven't thought the DSL through, but I hope the main idea can be seen: contexts do not have to be hierarchical.
>> In my opinion, adding some sort of context selection+combination capabilities (AOP-style) will contribute greatly to the expressiveness of the spec language.
> 
> I think the idea of mixing/matching sub-contexts is very interesting, but it definitely needs from fleshing out. It would have to be easy to read/understand in the spec file as well as the output.
> 
> Also, this only works if every combination should behave the same way. I think we'd need a means of saying "given these combinations of data, expect these outcomes".
> 
> Anybody else have thoughts on this?

It's a nice idea.

I'm not sure whether I'd use it though. I think this idea comes from the desire to write specs that are *complete*, which I can perfectly understand but I don't think I subscribe to anymore. I prefer to really craft the examples so there's 'just enough' tests but no more than that. I'd be worried this might offer a temptation to think less about why you're writing each example, and I'd be worried how that would help me to do TDD.

It should be possible to do something like this using macros now, right? Can I suggest that the OP has a go at refactoring his code using macros and we can see how it looks?

> 
> Cheers,
> David
> 
> 
>> Thank you for your attention,
>> Costa.
> 
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

cheers,
Matt

http://blog.mattwynne.net
+44(0)7974 430184

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20100719/b5d6f188/attachment.html>


More information about the rspec-users mailing list