TDD Tutorial TDD Tutorial
For information about Test-Driven Development, here are some links. It is recommendable to read them before doing this tutorial, so that you would know what TDD is about.
- http://en.wikipedia.org/wiki/Test-driven_development
- http://www.butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
- http://www.butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata
- http://www.agiledata.org/essays/tdd.html
- http://blog.briandicroce.com/2008/03/14/three-index-cards-to-easily-remember-the-essence-of-test-driven-development/
- http://agileinaflash.blogspot.com/2009/03/unclebobs-three-rules-of-tdd.html
- http://agileinaflash.blogspot.com/2009/02/red-green-refactor.html
- http://agileinaflash.blogspot.com/2009/02/first.html
The Steps of the Tutorial
Use the following tests to write a Tetris game. Copy them to your project one file at a time, in the same order as
they are listed below, starting with FallingBlocksTest.java
. First write code which passes the first
test (A_new_board.test_Is_empty
) and then uncomment the following test (A_new_board.test_Has_no_falling_blocks
).
When that test passes, uncomment the next one (When_a_block_is_dropped.test_The_block_is_falling
) until
finally you have written code which passes all tests in that class. Then copy the next test class to your project
and keep on continuing in the same fashion.
FallingBlocksTest.java
In Tetris, the most important feature is that there are blocks which fall down, so that is the first behaviour which we will specify by writing tests. It is good to start the writing of a program with a very trivial test. In this case, we will first make sure that we have an empty game board.
RotatingPiecesOfBlocksTest.java
Rotating the pieces in Tetris is also very important, so let's code that next. You might need pen and paper when figuring out how the shape coordinates change when the shape is rotated.
(I decided to go for a generic method of rotating any shapes. Another option would have been to hard-code the rotations of each shape. Both have their pros and cons. But even if this decision would prove to be bad when the game expands beyond this tutorial, good test coverage and decoupled code will make it possible to change it afterwards.)
RotatingTetrominoesTest.java
Tetrominoes can have 1, 2 or 4 different positions when they are rotated. Now we can take advantage of the shape rotation code which we wrote just a moment ago.
FallingPiecesTest.java
Next we will connect the falling blocks and the rotatable pieces. In order to make the first test pass, you will probably need to refactor your code quite much (for me it took 1½ hours). You need to build suitable abstractions, so that single-block pieces and multi-block pieces can be handled the same way (changing the test code should not be necessary). When refactoring, you must keep the tests passing between every small change, or you will end up in refactoring hell. If more than five minutes has passed since the last time all tests passed, revert your code to the last version from source control where all tests passed.
MovingAFallingPieceTest.java
Now it's your turn to write the tests. I've provided some TODO items which should hint you on what kind of tests to write.
RotatingAFallingPieceTest.java
Keep on writing your own tests. You're getting the hang of it!
- Next you should probably implement the following features in a suitable order: removing full rows, counting removed rows (maybe launch an event when a row is removed - Mockito might come in handly for testing that), counting score, choosing the next piece by random. Soon after that you should be able to create an user interface which is only a thin wrapper over the already implemented functionality. Automated testing of user interfaces is generally hard to do, but by separating the UI model from its view it is possible (see these articles).
Copyright (c) 2008-2009 Esko Luontola, www.orfjackal.net
You may use and modify this material freely for personal non-commercial use. This material may NOT be used as
course material without prior written agreement.