Friday, December 21, 2007

tests, specs and understanding code

Today, I was looking at a test. It read something like this:

def test_random_beans
beans = Beans.random(5)
assert_equal 5, beans.size
end


Simple, enough test right? Well, it was failing, beans.size returned 4. At first glance, I knew that a bean had been removed; so, probably it was safe to just change the assertion to

assert_equal 4, beans.size


This didn't really sit well with me though. Then later talking with a co-worker about the test. He was asking the question of why if we passed 5 to random it would only return 4 beans. Then later in the thread I asked for clarification:

so... Beans.random(5) should return 5 random beans?

That's when I realized, I had basically just written a spec for Beans.random. Had it been written that way from the beginning, it would have also made sense to have a spec to model the edge case of a user asking for more random beans then exist. This spec could read something like:

it "should return at most 4 beans from random" do
Beans.random(1000).should.return(4)
end


What I take away from this is the importance of specs go well beyond simple verification that the code is doing what you asked of it. It also, clearly documents in a human readable form what the code should be doing. This really improved the value of specs in my mind as more then just a pretty way of writing tests, but also a great way to document and understand the code.

1 comments:

gabe said...

rspec reminds me of Inform.

"It's literate; meaning equally readable, more or less, by the compiler and the author. It's still a formal language with all that wonderful lexical and BNF stuff, it's just a bit richer than a typical programming language." -- Tapestry + Hivemind

Reading list