[rspec-users] Varying test data

Pat Maddox pergesu at gmail.com
Fri Jan 11 05:48:15 EST 2008


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


More information about the rspec-users mailing list