[LRUG] A question on DRYness on testing methods that get / set state

Tim Cowlishaw tim at timcowlishaw.co.uk
Tue Nov 22 03:23:59 PST 2011


Hi there LRUG,

I've got a question about testing that's been bugging me for a while,
and I'd like to get your collective opinion on it, if that's ok. To
illustrate:

Let's say I have a class called 'Box' that exists solely to take a
value and store it in the box:

class Box
  def put(item)
    @item = item
  end

  def get
    return item
  end
end

Now, being a good, responsible developer, I decide to write specs for
my box (In fact, i probably even did this first if i was being
especially virtuous, but you get the idea):

describe Box do
  describe "put" do
    it "puts the item in the box" do
      b = Box.new
      b.put(:hello)
      b.get.should == :hello
    end
  end

  describe "get" do
    "it gives me the item in the box" do
      #oh shit! this is exactly the same as the spec for 'put'
      b = Box.new
      b.put(:hello)
      b.get.should == :hello
    end
  end
end

So, my specs for get and put are identical, which, for a start isn't
very DRY, but also (and more importantly to my mind) is pretty
brittle. For instance, if a malicious person snuck into my codebase
and changed the implementation of 'get' to eg:
def get
  return "I'm all up in your codebase, messing with your shit"
end
then the spec for 'get' would fail, as expected, but also the spec for
'put' would fail, even though there's nothing wrong with the
implementation of 'put' itself.

Of course, I could use instance_variable_get and instance_variable_set
to setup the object in the get spec, and inspect its state in the put
spec, but this ties my specs to that specific implementation of Box,
rather than simply the external interface / behaviour.

I guess this is a bit of a tradeoff, but I'd be curious to know - how
do you guys write tests for methods that get or set state? is there a
better way than the above?

Thanks,

Tim



More information about the Chat mailing list