Hello! I''m trying to spec a method, that has several chained calls. http://gist.github.com/78562 (spec) http://gist.github.com/78563 (model) In the first spec, I''m trying to focus on the method calls that have to be made, and the arguments they should receive. Is there a better way to spec the behaviour for these chained calls? It just seems too many lines to me :) Thanks a lot! Levy PS: I''m using my branch of the twitter gem, at http://github.com/levycarneiro/twitter, which just adds this method ''not_retweeted''. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090313/0a68960f/attachment.html>
You might want to look into using a null object, and breaking that first spec up into several examples (a null object returns itself when sent a message it doesn''t know how to handle) http://gist.github.com/78570 I''ve built more than a few named_scope chains using this pattern, and it seems to work out okay. This approach is somewhat less brittle, in that it''s not going to explode horribly if you change the order of the chain in the main method (if something else reads better, say) ... Downside is that it _won''t_ catch if you add new methods to the chain. If that''s a concern, you could complicate the setup a bit, to narrow the focus to _just_ the methods you want. @new_search = mock(Twitter::Search) new_search.stub!(:containing => new_search, :since => new_search, :not_retweeted => new_search, :fetch => new_search) On Fri, Mar 13, 2009 at 10:04 AM, Levy Carneiro Jr. <levy at levycarneiro.com>wrote:> Hello! > > I''m trying to spec a method, that has several chained calls. > > http://gist.github.com/78562 (spec) > http://gist.github.com/78563 (model) > > In the first spec, I''m trying to focus on the method calls that have to be > made, and the arguments they should receive. > > Is there a better way to spec the behaviour for these chained calls? It > just seems too many lines to me :) > > > Thanks a lot! > Levy > PS: I''m using my branch of the twitter gem, at > http://github.com/levycarneiro/twitter, which just adds this method > ''not_retweeted''. > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- // anything worth taking seriously is worth making fun of // http://blog.devcaffeine.com/ -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090313/37e54696/attachment.html>
Levy Carneiro Jr. wrote:> Hello! > > I''m trying to spec a method, that has several chained calls. > > http://gist.github.com/78562 (spec) > http://gist.github.com/78563 (model) > > In the first spec, I''m trying to focus on the method calls that have > to be made, and the arguments they should receive. > > Is there a better way to spec the behaviour for these chained calls? > It just seems too many lines to me :)http://c2.com/cgi/wiki?LawOfDemeter Specs are as much of a design tool as a testing tool, and the use of mocks in your specs show just how ugly the current design is. Either write a wrapper around the library which takes care of the method chaining, or write integration tests against it, stubbing out some low level detail of the library. Scott> > > Thanks a lot! > Levy > PS: I''m using my branch of the twitter gem, at > http://github.com/levycarneiro/twitter, which just adds this method > ''not_retweeted''. > > > ------------------------------------------------------------------------ > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
Hello Scott, On Fri, Mar 13, 2009 at 11:59 AM, Scott Taylor <scott at railsnewbie.com>wrote:> http://c2.com/cgi/wiki?LawOfDemeter > > Specs are as much of a design tool as a testing tool, and the use of mocks > in your specs show just how ugly the current design is. > > Either write a wrapper around the library which takes care of the method > chaining, or write integration tests against it, stubbing out some low level > detail of the library.Actually, the method ''fetch_new_tweets'' is the wrapper. There''s another method called ''process_new_tweets'', which calls some methods from the Tweet class, including fetch_new_tweets. But I see your point. Testing only the output from this wrapper (integration tests), and not testing the internal actions being done inside Twitter::Search, which Tweet shouldn''t know about. So, the ideal would be the Twitter::Search class to provide some ready-to-use wrappers for me, the way I want it. Like the postman and wallet example [1]. But, since it clearly doesn''t have all wrappers I need, shouldn''t my own class, Tweets, be doing the several wrappers and testing them on my own? Or, there is a better design pattern in this case? [1] http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf Regards, Levy -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090314/a8ff179a/attachment.html>
Thanks for your examples, Chris! regards, Levy On Fri, Mar 13, 2009 at 11:25 AM, Chris Flipse <cflipse at gmail.com> wrote:> You might want to look into using a null object, and breaking that first > spec up into several examples > (a null object returns itself when sent a message it doesn''t know how to > handle) > > > http://gist.github.com/78570 > > I''ve built more than a few named_scope chains using this pattern, and it > seems to work out okay. This approach is somewhat less brittle, in that > it''s not going to explode horribly if you change the order of the chain in > the main method (if something else reads better, say) ... > > Downside is that it _won''t_ catch if you add new methods to the chain. If > that''s a concern, you could complicate the setup a bit, to narrow the focus > to _just_ the methods you want. > > @new_search = mock(Twitter::Search) > > new_search.stub!(:containing => new_search, :since => new_search, :not_retweeted => new_search, :fetch => new_search) > > > On Fri, Mar 13, 2009 at 10:04 AM, Levy Carneiro Jr. <levy at levycarneiro.com > > wrote: > >> Hello! >> >> I''m trying to spec a method, that has several chained calls. >> >> http://gist.github.com/78562 (spec) >> http://gist.github.com/78563 (model) >> >> In the first spec, I''m trying to focus on the method calls that have to be >> made, and the arguments they should receive. >> >> Is there a better way to spec the behaviour for these chained calls? It >> just seems too many lines to me :) >> >> >> Thanks a lot! >> Levy >> PS: I''m using my branch of the twitter gem, at >> http://github.com/levycarneiro/twitter, which just adds this method >> ''not_retweeted''. >> >> >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > > > > -- > // anything worth taking seriously is worth making fun of > // http://blog.devcaffeine.com/ > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090317/c0a45071/attachment.html>