Start with a high level description of what you want to implement.
- A square board with rows and columns.
- Each board position should have a
color.
- A board user should be able to
set the color of a specific board
position (pixel).
- A board user should
be able to get the color of a
specific board position.
- etc.
Next, use small tests to drive out the implementation. Sometimes it is easier to start with boundary conditions.
When asked to get the color at a specific board position
- given a default board, and
- the row value is less than zero
- should throw argument exception
When asked to get the color at a specific board position
- given a default board, and
- the row value is greater than the highest board row
- should throw argument exception
"the row value is greater than the highest board row" forces you to have some way to set the highest board row. The test doesn't care whether you set it via the constructor or a property setter.
When constructed with board dimensions
- should set the highest board row
"should set the highest board row" forces you to have some way to access the value that was set. Perhaps a property getter.
When asked to get the color at a specific board position
- given a default board, and
- the column value is less than zero
- should throw argument exception
When asked to get the color at a specific board position
- given a default board, and
- the column value is greater than the highest board column
- should throw argument exception
"the column value is greater than the highest board column" forces you to duplicate the highest row solution for the highest column.
When constructed with board dimensions
- should set the highest board column
etc.
When asked to get the color at a specific board position
- given a default board, and
- the row value is within the board space, and
- the column is within the board space
- should return the default color
"should return the default color" forces you to expose the default color somewhere. This shouldn't be a magic value that only the test knows about. Expose it as a const or read only value on Board.
When asked to get the color at a specific board position
- given a default board, and
- the row value is within the board space, and
- the column is within the board space, and
- the requested position has a known color
- should return the color of the board at the requested position
"the requested position has a known color" forces you to build out the ability to set the color of a board position. You can do that now because you have a failing test for getting the color at a position. So set that aside and build out the setter.
When asked to SET the color at a specific board position
- given a default board, and
- the row value is less than zero
- should throw argument exception
When asked to set the color at a specific board position
- given a default board, and
- the row value is greater than the highest board row
- should throw argument exception
When asked to set the color at a specific board position
- given a default board, and
- the column value is less than zero
- should throw argument exception
When asked to set the color at a specific board position
- given a default board, and
- the column value is greater than the highest board column
- should throw argument exception
When asked to set the color at a specific board position
- given a default board, and
- the row value is within the board space, and
- the column is within the board space
- should set the color at the given position to the requested color
"should set the color at the given position to the requested color" uses your get implementation to verify the value was set correctly. Once you've implemented it correctly all your tests will be green again.
Just continue to build out additional functionality one small piece at a time.
When you approach the tests in implementation-agnostic terms like this you can change the implementation to use IBoard or Ruby or whatever and the test descriptions don't have to change. You'll have to change some test implementation details but the stated goals of the tests don't have to change.