views:

127

answers:

3

I want to try to implement the Tetris Game using TDD.

From what I've come to understand when reading Growing Object-Oriented Software, Guided by Tests, I should start by defining what would be my Acceptance tests. If I am right, Acceptance tests when doing TDD are defined just like Use Cases.

It is of great importance to define a good first Acceptance Test that will work as "skeleton" of the App, so it should be kind of simple.

I've choosen the following 2 Acceptance Tests as my first to implement:

  1. The Game starts and the Player closes it.
  2. The Game starts and the Player does nothing. He eventually loses.

Are these 2 acceptance tests good starting tests? What would be good next acceptance tests? I could think of something like

  • The game starts and only square pieces drop. The player puts them all in such a way that the lines always "explode", making the Game after 100 game-steps still be not over.

but I feel this is kind of awkward, as in a real Tetris game you would always have different pieces falling, and that is what Acceptance Testing should be about.

Also, I feel kind of tempted to just try to implement everything in one go when doing (2), which I think is not one pretends when implementing the second Acceptance Test. I guess the idea would be to only have the game implemented after like 6-7 of them, not on the second. Am I right?

Thanks

A: 

Start out with a simple list of blocks. Assuming no player, the blocks will stack up in a certain way and then spill over. Your test fails if the blocks don't stack up right or the program does not detect spill over.

emory
How can I know they dont stack up right? Wouldn't I then have to implement code logic more complex than the one I'm trying to make? Or are you assuming I just land in the game a set of chosen pieces? Are you talking about Unit Tests or Acceptance Tests?
devoured elysium
I assumed a set of chosen pieces.
emory
+2  A: 

I would think first about the game field and what it looks like after a number of frames with some defined blocks dropped. For example using Cucumber:

Scenario: dropping the first square
  Given an empty 10x2 field

  When a square is dropped at column 4
  And 48 frames have passed

  Then the field should contain a square at (4, 1)

  When 48 frames have passed
  Then the field should contain a square at (4, 2)

Scenario: Dropping a square on a full stack
  Given an empty 10x2 field
  And a square at (4, 2)

  When a square is dropped at column 4
  And 48 frames have passed

  Then the game should be over

If you like the look of Cucumber feature specs, you might want to try Cuke4Nuke for .Net or Cuke4Duke for Java.

Bryan Ash
I'm unclear on where the number 48 is coming from. Also, for the second scenario, should the Given phrase be "Given a full 10x2 field" instead?
SCFrench
I looked at the Wikipedia page for Tetris to get the business language. That's where the 48 came from. "a full 10x2 field" could be a good given, but not very realistic, I've played a bit of Tetris in my time and have NEVER seen a full field.
Bryan Ash
I have a bit of trouble understanding how using TDD, that says that for each test we should the minimum amount of code possible to just make something run, should we implement the scenarios you gave. I mean, I could implement already the full tetris game, but is hard for me to conceive how to implement just what is needed without having to put it all there, already.
devoured elysium
Also, what you've shown me is an Acceptance of Unit Test?
devoured elysium
What I have shown would be an acceptance test. Start with an acceptance test. If you are confident that you can implement that much of the feature with no bugs, have at it. If the behavior is less than trivial, write the first lower level test and make that pass. Then the next. If you're still heading towards the acceptance criteria, keep moving, if not, DELETE the code and begin again. Sometimes, I will head down a unit test (low level spec) path a couple of times before I understand how the code wants to be written. Listen carefully, it will tell you.
Bryan Ash
What would be the difference between those Acceptance tests you made and Unit Tests to the Tetris class?
devoured elysium
+1  A: 

You will want to remove the randomness that belongs in your game from your tests. Yes, this means that the test doesn't perfectly duplicate the game, but it also means you have repeatable tests, and that's of greater value. Isolate the differences - pass a PieceProvider into your game; for the real game pass a RandomPieceProvider, but for the tests pass in a SpecifiedPieceProvider. Now you have just a tiny bit of difference between them, but the difference ought to be so small as not to matter; you can still test all other aspects of the game with confidence.

Carl Manaster
The `public Random(long seed)` constructor makes it easy to create a repeatable yet plausible test: http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/Random.html
trashgod
Yes, that is true. But what is bothering me more is how to implement the first scenario/use case. The question is how much should I implement of the game itself.
devoured elysium
@devoured I haven't read the book you mention, but most of the advice I've seen with respect to TDD is: just enough to pass the test. It has worked well for me.
Carl Manaster