This isn''t specific to RSpec, but is hopefully on-topic for this list. I like (especially when "ping pong pairing") to write a spec, then write the smallest amount of code I can to pass it (especially when "ping pong pairing"). Sometimes this means hard-coding a return value, which means another spec is needed to prove that the code is really behaving as it should. Trivial example: ---------- describe Adder do it "should add two numbers" do Adder.add(2, 2).should == 4 end end class Adder def add a, b 4 end end ---------- describe Adder do it "should add 2 and 2" do Adder.add(2, 2).should == 4 end it "should add 3 and 4" do Adder.add(3, 4).should == 7 end end class Adder def add a, b a + b end end ---------- It doesn''t seem right though to have all those duplicate specs. An alternative is to generate random test data, but I''m not really comfortable doing that because it means the tests aren''t strictly repeatable. I guess this is more of a problem with classic state-based testing, but even using BDD you still have to test state at the leaf nodes. Does anyone have an opinion about whether this is a problem, and whether there''s a clean way of dealing with it? Thanks, Kerry
On Jan 11, 2008 2:33 AM, Kerry Buckley <kerry at kerrybuckley.com> wrote:> This isn''t specific to RSpec, but is hopefully on-topic for this list. > > I like (especially when "ping pong pairing") to write a spec, then > write the smallest amount of code I can to pass it (especially when > "ping pong pairing"). Sometimes this means hard-coding a return value, > which means another spec is needed to prove that the code is really > behaving as it should. Trivial example: > > ---------- > describe Adder do > it "should add two numbers" do > Adder.add(2, 2).should == 4 > end > end > > class Adder > def add a, b > 4 > end > end > ---------- > describe Adder do > it "should add 2 and 2" do > Adder.add(2, 2).should == 4 > end > it "should add 3 and 4" do > Adder.add(3, 4).should == 7 > end > end > > class Adder > def add a, b > a + b > end > end > ---------- > > It doesn''t seem right though to have all those duplicate specs. An > alternative is to generate random test data, but I''m not really > comfortable doing that because it means the tests aren''t strictly > repeatable. I guess this is more of a problem with classic state-based > testing, but even using BDD you still have to test state at the leaf > nodes. > > Does anyone have an opinion about whether this is a problem, and > whether there''s a clean way of dealing with it?If I were your pair, I would smack you if you hard-coded 4 and moved on to the next test :) You forgot the third step in BDD - refactoring! At the simplest level, that means removing duplication. The duplication in this case is between the test and production code. In your adder example, the red/green/refactor cycle ought to go like: red - write the spec green - make it pass by returning 4 refactor - generalize the method by returning the sum of the two variables Okay, I wouldn''t smack you necessarily. What you''re describing here is a TDD technique called Triangulation. Basically you keep writing tests until you have enough info to drive a useful generalization. With such a simple example, Triangulation probably isn''t necessary. You can use Obvious Implementation (where you would just type out a + b to begin with - after being red first, of course), or you Fake It (by first returning 4 to get to green, then generalizing). Specs should give you confidence that the code works as expected. If it takes you two specs to Triangulate on a solution, and the two specs are redundant, feel free to delete one of them. Delete a spec if it doesn''t add value, and keep it around if deleting it would reduce your confidence. I recommend reading Kent Beck''s "TDD By Example" for a more in-depth discussion of these (and plenty other) techniques. Pat
On Jan 11, 2008 4:33 AM, Kerry Buckley <kerry at kerrybuckley.com> wrote:> This isn''t specific to RSpec, but is hopefully on-topic for this list. > > I like (especially when "ping pong pairing") to write a spec, then > write the smallest amount of code I can to pass it (especially when > "ping pong pairing"). Sometimes this means hard-coding a return value, > which means another spec is needed to prove that the code is really > behaving as it should. Trivial example: > > ---------- > describe Adder do > it "should add two numbers" do > Adder.add(2, 2).should == 4 > end > end > > class Adder > def add a, b > 4 > end > end > ---------- > describe Adder do > it "should add 2 and 2" do > Adder.add(2, 2).should == 4 > end > it "should add 3 and 4" do > Adder.add(3, 4).should == 7 > end > end > > class Adder > def add a, b > a + b > end > end > ---------- > > It doesn''t seem right though to have all those duplicate specs. An > alternative is to generate random test data, but I''m not really > comfortable doing that because it means the tests aren''t strictly > repeatable. I guess this is more of a problem with classic state-based > testing, but even using BDD you still have to test state at the leaf > nodes. > > Does anyone have an opinion about whether this is a problem, and > whether there''s a clean way of dealing with it?The approach you are taking (writing the second example) is called triangulation. An other approach is to recognize in the first example that there is duplication between the example and the code being described. In this case, the number 4. From a duplication-removing perspective, that is sufficient motivation to make the change during the refactoring phase in THIS particular example. If you were describing an object that behaved fundamentally differently depending on input values, then you''d want the different examples. In this case, returning the sum is not fundamentally different in my view. That said, if you were REALLY building a calculator and not relying on the addition facilities of the language you were using, you would naturally have additional examples to cover edge cases. Double digits, for example. You might also want to run this by the testdrivendevelopment list (http://tech.groups.yahoo.com/group/testdrivendevelopment/). Cheers, David> > Thanks, > > Kerry > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Jan 11, 2008 4:48 AM, Pat Maddox <pergesu at gmail.com> wrote:> > On Jan 11, 2008 2:33 AM, Kerry Buckley <kerry at kerrybuckley.com> wrote: > > This isn''t specific to RSpec, but is hopefully on-topic for this list. > > > > I like (especially when "ping pong pairing") to write a spec, then > > write the smallest amount of code I can to pass it (especially when > > "ping pong pairing"). Sometimes this means hard-coding a return value, > > which means another spec is needed to prove that the code is really > > behaving as it should. Trivial example: > > > > ---------- > > describe Adder do > > it "should add two numbers" do > > Adder.add(2, 2).should == 4 > > end > > end > > > > class Adder > > def add a, b > > 4 > > end > > end > > ---------- > > describe Adder do > > it "should add 2 and 2" do > > Adder.add(2, 2).should == 4 > > end > > it "should add 3 and 4" do > > Adder.add(3, 4).should == 7 > > end > > end > > > > class Adder > > def add a, b > > a + b > > end > > end > > ---------- > > > > It doesn''t seem right though to have all those duplicate specs. An > > alternative is to generate random test data, but I''m not really > > comfortable doing that because it means the tests aren''t strictly > > repeatable. I guess this is more of a problem with classic state-based > > testing, but even using BDD you still have to test state at the leaf > > nodes. > > > > Does anyone have an opinion about whether this is a problem, and > > whether there''s a clean way of dealing with it? > > If I were your pair, I would smack you if you hard-coded 4 and moved > on to the next test :) You forgot the third step in BDD - > refactoring! At the simplest level, that means removing duplication. > The duplication in this case is between the test and production code. > In your adder example, the red/green/refactor cycle ought to go like: > > red - write the spec > green - make it pass by returning 4 > refactor - generalize the method by returning the sum of the two variables > > Okay, I wouldn''t smack you necessarily. What you''re describing here > is a TDD technique called Triangulation. Basically you keep writing > tests until you have enough info to drive a useful generalization. > > With such a simple example, Triangulation probably isn''t necessary. > You can use Obvious Implementation (where you would just type out a + > b to begin with - after being red first, of course), or you Fake It > (by first returning 4 to get to green, then generalizing). > > Specs should give you confidence that the code works as expected. If > it takes you two specs to Triangulate on a solution, and the two specs > are redundant, feel free to delete one of them. Delete a spec if it > doesn''t add value, and keep it around if deleting it would reduce your > confidence. > > I recommend reading Kent Beck''s "TDD By Example" for a more in-depth > discussion of these (and plenty other) techniques.Apparently, Pat and I are twins separated at birth.> > Pat > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Jan 11, 2008 2:50 AM, David Chelimsky <dchelimsky at gmail.com> wrote:> > On Jan 11, 2008 4:48 AM, Pat Maddox <pergesu at gmail.com> wrote: > > > > On Jan 11, 2008 2:33 AM, Kerry Buckley <kerry at kerrybuckley.com> wrote: > > > This isn''t specific to RSpec, but is hopefully on-topic for this list. > > > > > > I like (especially when "ping pong pairing") to write a spec, then > > > write the smallest amount of code I can to pass it (especially when > > > "ping pong pairing"). Sometimes this means hard-coding a return value, > > > which means another spec is needed to prove that the code is really > > > behaving as it should. Trivial example: > > > > > > ---------- > > > describe Adder do > > > it "should add two numbers" do > > > Adder.add(2, 2).should == 4 > > > end > > > end > > > > > > class Adder > > > def add a, b > > > 4 > > > end > > > end > > > ---------- > > > describe Adder do > > > it "should add 2 and 2" do > > > Adder.add(2, 2).should == 4 > > > end > > > it "should add 3 and 4" do > > > Adder.add(3, 4).should == 7 > > > end > > > end > > > > > > class Adder > > > def add a, b > > > a + b > > > end > > > end > > > ---------- > > > > > > It doesn''t seem right though to have all those duplicate specs. An > > > alternative is to generate random test data, but I''m not really > > > comfortable doing that because it means the tests aren''t strictly > > > repeatable. I guess this is more of a problem with classic state-based > > > testing, but even using BDD you still have to test state at the leaf > > > nodes. > > > > > > Does anyone have an opinion about whether this is a problem, and > > > whether there''s a clean way of dealing with it? > > > > If I were your pair, I would smack you if you hard-coded 4 and moved > > on to the next test :) You forgot the third step in BDD - > > refactoring! At the simplest level, that means removing duplication. > > The duplication in this case is between the test and production code. > > In your adder example, the red/green/refactor cycle ought to go like: > > > > red - write the spec > > green - make it pass by returning 4 > > refactor - generalize the method by returning the sum of the two variables > > > > Okay, I wouldn''t smack you necessarily. What you''re describing here > > is a TDD technique called Triangulation. Basically you keep writing > > tests until you have enough info to drive a useful generalization. > > > > With such a simple example, Triangulation probably isn''t necessary. > > You can use Obvious Implementation (where you would just type out a + > > b to begin with - after being red first, of course), or you Fake It > > (by first returning 4 to get to green, then generalizing). > > > > Specs should give you confidence that the code works as expected. If > > it takes you two specs to Triangulate on a solution, and the two specs > > are redundant, feel free to delete one of them. Delete a spec if it > > doesn''t add value, and keep it around if deleting it would reduce your > > confidence. > > > > I recommend reading Kent Beck''s "TDD By Example" for a more in-depth > > discussion of these (and plenty other) techniques. > > Apparently, Pat and I are twins separated at birth.Have I ever told you what a smart guy you are? :)
On 11 Jan 2008, at 10:50, David Chelimsky wrote:> On Jan 11, 2008 4:48 AM, Pat Maddox <pergesu at gmail.com> wrote: >> >> <lots of sensible advice> > > Apparently, Pat and I are twins separated at birth.Thanks both! Kerry
On Jan 11, 2008, at 5:50 AM, David Chelimsky wrote:> Apparently, Pat and I are twins separated at birth.Would it then be correct to refactor and eliminate one of them?? :))
We''re clearly at green! Nathan Sutton fowlduck at gmail.com rspec 1.1 rspec_on_rails 1.1 rails 2.0.2 On Jan 11, 2008, at 10:19 AM, Jonathan Linowes wrote:> > On Jan 11, 2008, at 5:50 AM, David Chelimsky wrote: > >> Apparently, Pat and I are twins separated at birth. > > > Would it then be correct to refactor and eliminate one of them?? > > :)) > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On Jan 11, 2008 10:19 AM, Jonathan Linowes <jonathan at parkerhill.com> wrote:> > On Jan 11, 2008, at 5:50 AM, David Chelimsky wrote: > > > Apparently, Pat and I are twins separated at birth. > > Would it then be correct to refactor and eliminate one of them??If you could argue that we were ultimately composed of 1s and 0s, perhaps.
On Jan 11, 2008 11:33 AM, Kerry Buckley <kerry at kerrybuckley.com> wrote:> This isn''t specific to RSpec, but is hopefully on-topic for this list. > > I like (especially when "ping pong pairing") to write a spec, then > write the smallest amount of code I can to pass it (especially when > "ping pong pairing"). Sometimes this means hard-coding a return value, > which means another spec is needed to prove that the code is really > behaving as it should. Trivial example: > > ---------- > describe Adder do > it "should add two numbers" do > Adder.add(2, 2).should == 4 > end > end > > class Adder > def add a, b > 4 > end > end > ---------- > describe Adder do > it "should add 2 and 2" do > Adder.add(2, 2).should == 4 > end > it "should add 3 and 4" do > Adder.add(3, 4).should == 7 > end > end > > class Adder > def add a, b > a + b > end > end > ---------- > > It doesn''t seem right though to have all those duplicate specs. An > alternative is to generate random test data, but I''m not really > comfortable doing that because it means the tests aren''t strictly > repeatable. I guess this is more of a problem with classic state-based > testing, but even using BDD you still have to test state at the leaf > nodes. >It may not be applicable in your trivial context, but "pair-wise" testing (has nothing to do with pair programming) is a really powerful technique you could consider. It''s a mini method that generates input combinations based on a set of possible values, dramatically reducing the number of combinations while still giving you the most important combinations. It''s based on a theory that bugs often occur when a pair of data changes, and it tries to generate data that covers as many pairs as possible without going overboard. It''s the most interesting test-related practice I have learned in several years (there are separate conferences on the topic!). I haven''t tried it myself, but I know several colleagues who''ve had great success with it. There is also a tool (perl script) you can use to generate input values for you (you figure out the expected results yourself - it doesn''t do that for you). And best of all - it looks really easy to use, both as a technique and a tool. http://www.testingeducation.org/wtst5/PairwisePNSQC2004.pdf http://www.pairwise.org/ http://en.wikipedia.org/wiki/All-pairs_testing http://www.developsense.com/2007/11/pairwise-testing.html http://www.developsense.com/testing/PairwiseTesting.html Aslak> Does anyone have an opinion about whether this is a problem, and > whether there''s a clean way of dealing with it? > > Thanks, > > Kerry > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >