Understanding TDD/BDD

slug: understanding-tddbdd

I finally get it. I have used
TDD on a few of my
past projects, but I have always struggled with determining which tests
I should write. In my head I could see the code for the feature I was
working on, but I could not see the code for the tests for that feature.
That brings me to some code I was working on last night. In my quest to
become an open source developer, I was spending some quality time
playing around with the RSpec testing framework for Ruby. I was
working through a tutorial from IBM developerWorks.While technically
RSpec is a BDD
framework, it still follows the TDD idea of writing tests before writing
code and letting the tests guide the design. Unlike most testing
frameworks, RSpec lets you write tests in a form that resembles how you
would write the requirements in English. That is what finally made the
pieces fall into place for me. I now understand that the tests are
supposed to define the details of the requirements in code. As you write
more tests and then write the code the makes those tests pass, you
uncover more things that you need to write tests for. It makes for a
really nice feedback loop.

Using my newly-discovered knowledge, I built a small class up using
RSpec and following the loop. I have included that code here with the
hope it may help somebody else out there better understand how all this
works.

First, I have the RSpec test suite:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require 'warehouse'

describe Warehouse do
before :each do
@warehouse = Warehouse.new
end

it "should be empty before items are stored in it" do
@warehouse.should be_empty()
end

it "initial item count should be zero" do
@warehouse.item_count("item number").should == 0
end

it "should receive items for inventory" do
@warehouse.receive_item("item number", 10)
@warehouse.item_count("item number").should == 10
end

it "should add items to count if they already exist" do
@warehouse.receive_item("item number", 10)
@warehouse.receive_item("item number", 40)
@warehouse.item_count("item number").should == 50
end
end

And here is the code for the class under test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Warehouse
attr_accessor :items

def initialize
@items = Hash.new
end

def empty?()
@items.length
end

def item_count(item_number)
@items[item_number] == nil ? 0 : @items[item_number]
end

def receive_item(item_number, count)
if (@items[item_number])
@items[item_number] += count
else
@items[item_number] = count
end
end
end

So now I am basking in my moment of enlightenment. I only wish I would
have figured all of this out sooner