Hi, I''ve got trouble when describe infinite loop. code snippet: def start_loop while true data = self.server.handle_client if data self.manager.dispatch(data) end end end without the loop, it is easy to test the logic. but how can I describe it to tell the developer ( me :-) ) that there should be an infinite loop inside. thanks. Regards, Peng Zuo
On Thu, May 29, 2008 at 9:25 AM, zuo peng <cn.peng.zuo at gmail.com> wrote:> Hi, > > I''ve got trouble when describe infinite loop. > > code snippet: > > def start_loop > while trueNot a reply to your specific question, but hopefully even better. I stumbled into similar situation a while ago, when I was developing a daemon process using BDD. When writing the test, I came up naturally with the following kind of structure: def start_loop while loop_condition? do_the_magic end end the idea is to separate looping logic and the operations done inside. The whole method start_loop was very easy to test now: MyDaemon.stub!(:loop_condition?).and_return(true, false) # I didn''t use RSpec at the time, so this might not work ... outcome.should be_something_expected The trick is in stubbing the class/module method loop_condition? so that it returns true the first time and false the second time, thus looping only once. In the actual implementation loop_condition? was implemented as follows: class MyDaemon def loop_condition?; true; end ... end thus making the while loop indefinite. Any smart developer could have come up with similar structure without using TDD/BDD. However, that particular solution came to me naturally exactly because of the way BDD works: it forces you -- in a tender way -- to write code that is easy to test automatically. -- "One day, when he was naughty, Mr Bunnsy looked over the hedge into Farmer Fred''s field and it was full of fresh green lettuces. Mr Bunnsy, however, was not full of lettuces. This did not seem fair." -- Terry Pratchett, Mr. Bunnsy Has An Adventure
On May 29, 2008, at 2:25 AM, zuo peng wrote:> Hi, > > I''ve got trouble when describe infinite loop. > > code snippet: > > def start_loop > while true > data = self.server.handle_client > if data > self.manager.dispatch(data) > end > end > end > > without the loop, it is easy to test the logic. > but how can I describe it to tell the developer ( me :-) ) that there > should be an infinite loop inside.Here''s a tip which Aslak gave me several months ago, and I find myself repeating it in many different contexts on this mailing list: One way is with dependency injection: def start_loop(looping_infinitely = true) while looping_infinitely ... end end In your spec, you simply pass false (but production code can call the method as if there is no option). Scott
On May 29, 2008, at 12:31 AM, Scott Taylor wrote:> > On May 29, 2008, at 2:25 AM, zuo peng wrote: > >> Hi, >> >> I''ve got trouble when describe infinite loop. >> >> code snippet: >> >> def start_loop >> while true >> data = self.server.handle_client >> if data >> self.manager.dispatch(data) >> end >> end >> end >> >> without the loop, it is easy to test the logic. >> but how can I describe it to tell the developer ( me :-) ) that there >> should be an infinite loop inside. > > Here''s a tip which Aslak gave me several months ago, and I find > myself repeating it in many different contexts on this mailing list: > > One way is with dependency injection: > > def start_loop(looping_infinitely = true):) I think calling this dependency injection is a bit of a stretch. I agree with the approach of having a logical default that you can override in the example, but what exactly is the dependency on? true? Regardless of its name, this is a very good solution to the problem at hand.> > while looping_infinitely > ... > end > end > > In your spec, you simply pass false (but production code can call > the method as if there is no option). > > Scott > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On May 29, 2008, at 3:33 AM, David Chelimsky wrote:> On May 29, 2008, at 12:31 AM, Scott Taylor wrote: > >> >> On May 29, 2008, at 2:25 AM, zuo peng wrote: >> >>> Hi, >>> >>> I''ve got trouble when describe infinite loop. >>> >>> code snippet: >>> >>> def start_loop >>> while true >>> data = self.server.handle_client >>> if data >>> self.manager.dispatch(data) >>> end >>> end >>> end >>> >>> without the loop, it is easy to test the logic. >>> but how can I describe it to tell the developer ( me :-) ) that >>> there >>> should be an infinite loop inside. >> >> Here''s a tip which Aslak gave me several months ago, and I find >> myself repeating it in many different contexts on this mailing list: >> >> One way is with dependency injection: >> >> def start_loop(looping_infinitely = true) > > :) > > I think calling this dependency injection is a bit of a stretch. I > agree with the approach of having a logical default that you can > override in the example, but what exactly is the dependency on? true? > > Regardless of its name, this is a very good solution to the problem > at hand.Yeah, good point. It makes me laugh a bit too, now that I think about it. Also, shouldn''t the dependency occur in the constructor for it to be real DI? Scott
Thanks guys. Both ways work perfectly. Regards, Peng Zuo
On Thu, May 29, 2008 at 12:33 AM, David Chelimsky <dchelimsky at gmail.com> wrote:> On May 29, 2008, at 12:31 AM, Scott Taylor wrote: > >> >> On May 29, 2008, at 2:25 AM, zuo peng wrote: >> >>> Hi, >>> >>> I''ve got trouble when describe infinite loop. >>> >>> code snippet: >>> >>> def start_loop >>> while true >>> data = self.server.handle_client >>> if data >>> self.manager.dispatch(data) >>> end >>> end >>> end >>> >>> without the loop, it is easy to test the logic. >>> but how can I describe it to tell the developer ( me :-) ) that there >>> should be an infinite loop inside. >> >> Here''s a tip which Aslak gave me several months ago, and I find myself >> repeating it in many different contexts on this mailing list: >> >> One way is with dependency injection: >> >> def start_loop(looping_infinitely = true) > > :) > > I think calling this dependency injection is a bit of a stretch. I agree > with the approach of having a logical default that you can override in the > example, but what exactly is the dependency on? true? > > Regardless of its name, this is a very good solution to the problem at hand.If ever there were a time to drop Ruby and start using Java + Guice, this would be it. Pat
>> I''ve got trouble when describe infinite loop. >> >> code snippet: >> >> def start_loop >> while true >> data = self.server.handle_client >> if data >> self.manager.dispatch(data) >> end >> end >> end >> >> without the loop, it is easy to test the logic. >> but how can I describe it to tell the developer ( me :-) ) that there >> should be an infinite loop inside. > > Here''s a tip which Aslak gave me several months ago, and I find myself > repeating it in many different contexts on this mailing list: > > One way is with dependency injection: > > def start_loop(looping_infinitely = true) > while looping_infinitely > ... > end > end > > In your spec, you simply pass false (but production code can call the > method as if there is no option)."while true" is also known as "loop" in Ruby. Really, you do not want to test whether that ruby construct works, do you? (I can imagine it being in the test suite that is for RUby itself) What I think is interesting for you to test, is that your loop keeps running when the dispatcher dies, and possibly other bad-weather cases. I bet your loop is in another Thread, and checking whether a Thread still runs is easy enough (also interesting enough, since threads die by themselves in Ruby, by default, i.e. they do not raise exceptions in other threads unless you set Thread.abort_on_exception = true).