Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have started to write card game applications. Some model classes:

  • CardSuit, CardValue, Card
  • Deck, IDeckCreator, RegularDeckCreator, DoubleDeckCreator
  • Board
  • Hand

and some game classes:

  • Turn, TurnHandler
  • IPlayer, ComputerPlayer, HumanPlayer
  • IAttackStrategy, SimpleAttachStrategy, IDefenceStrategy, SimpleDefenceStrategy
  • GameData, Game

are already written. My idea is to create engine, where two computer players could play game and then later I could add UI part.

Already for some time I'm reading about Test Driven Development (TDD) and I have idea to start writing application from scratch, as currently I have tendency to write not needed code, which seems usable in future. Also code doesn't have any tests and it is hard to add them now.

Seems that TDD could improve all these issue - minimum of needed code, good test coverage and also could help to come to right application design.

But I have one issue - I can't decide from where to start TDD? Should I start from bottom - Card related classes or somewhere on top - Game, TurnHandler, ... ?

With which class you would start? And what would be the next 5 to 7 tests? (use the card game you know the best)

I would like to start TDD with your help and then continue on my own!

share|improve this question
    
start by reading what TDD is - "In test-driven development, each new feature begins with writing a test..." - and distinguish it from mere unit testing. en.wikipedia.org/wiki/Test-driven_development –  Steven A. Lowe Jun 4 '12 at 22:36
    
In general I know what is TDD, but as it's something new form me, it's hard to start - find the right place to start. –  Maxis Jun 5 '12 at 6:15
1  
you start with features and test descriptions, not classes and code –  Steven A. Lowe Jun 5 '12 at 13:41

5 Answers 5

up vote 6 down vote accepted

How about the below. The {} is the hints for the next step and after that I would get into specific attributes too.

  1. A pack of cards exists {Pack}
  2. The pack has 52 cards {Card and Pack - number of cards}
  3. The cards have 4 suits {Card attribute}
  4. Each suit has A,2-10,J,Q,K {Card attribute}
  5. A game is selected. {Game instance}
  6. Players are selected {Player instances}
  7. Cards are shuffled. {Shuffle method(s)}
  8. Cards are dealt. {Deal method(s)}
  9. Each person plays. {Play method(s)}
  10. One person wins. {Part of Play method, maybe call to Win method}
  11. End Game. {EndGame method}
share|improve this answer
    
All other answers are very helpful, but I was looking where to start in my example and what could be the next steps. This answer provides exactly what I was looking for! I will follow these steps and hopefully will get feeling how TDD works! –  Maxis Jun 5 '12 at 20:10

I would start with the lowest-level objects, those objects that you may need to write few tests for anyway because they mostly return properties like Suit and Color.

Once you have the basic objects, you can start adding tests for behavioral methods, and for methods that cause those basic objects to interact with one another.

share|improve this answer
    
Do you always start TDD from bottom? In my case, when classes are already partly designed it seems logical. But what if I forget about already written code and start from scratch and just know the game rules? In what cases would you start TDD from top? –  Maxis Jun 5 '12 at 6:22

If you truly want to embrace test-driven development, then you can start by forgetting that you've written any code. (Don't throw it away, just set it aside in your mind.) Then ask yourself which test you would write if you hadn't written any code yet. What is that you would want to assert first? Answer that question then start the TDD cycle:

  1. Write a failing test.
  2. Change your code to make it succeed.
  3. Repeat.

It doesn't really matter where you start, as long as it makes sense to you. It seems like you already have a solid understanding of how you want the application to be designed. That's great, so don't be afraid to write crappy tests. Over time you'll get the hang of it and can improve them.

Remember the tests are there to keep you (and others) from negatively altering your code. They are a "contract" you're defining so that you not only have an executable test, but a reference to how you anticipated your code would work. So start by writing tests that describe to you what your code should be doing. If you're still not sure how something will work, play with ideas (by writing tests) until it makes sense.

share|improve this answer
1  
Putting already written code aside was exactly my idea. Now I want to see how I could get to it by using TDD approach - how TDD dictates design. –  Maxis Jun 5 '12 at 6:38

Technically you cannot do TDD on already existing code. In TDD, tests are the basis for your design, here, the design is already made and then you want to refactor.

My recommendation is:

  1. Write the tests based on the already implemented design (look for test-cases on each method) so you get code coverage
  2. Make sure all your tests pass
  3. Start doing some refactoring and/or new implementations, whenever you are about to implement a new feature or make a design change (adding methods, changing an algoritm, make additional checks, etc.) first write a test that fails
  4. Change your code to pass the failing test
  5. Go to 3

The class doesn't matter, the question is: how do you get into the process?

share|improve this answer

Fitting tests into already existing application can be rather difficult and you might end up restructuring your code significantly. You might restructure it so much that the restructuring might feel as if you're 'starting from scratch' anyway.

Since it seems that you're just 'having fun' you might benefit more, at least from the design perspective, by starting from scratch.

I think that you should definitely test your models. Start with the 'smallest' models, like the Card objects for example. Your tests will verify these work. You can then move onto the Hand models. Then the Board.

In this way you build a hierarchy of tests that start with simple behaviors then build up to more complex behaviors.

For example, say you have a method named getHandValue that calculates a hand value based on the value of the cards in the hand. Well, you probably want to test the getCardValue method before testing the hand method because the hand method uses the card method anyway.

Also, you can use mock objects to get rid of unnecessary setup work.

For example, say you have a 'board' with a method getBoardValue. Let's say that this method uses all the hands currently in play to calculate its value. Instead of creating a hand and then creating cards to add to the hand you can simply create a mock hand object that returns a predetermined value. Now you don't have to do all this setup and remember what cards you added to the hands.

Some things are harder to test and that's where design decisions come into play.

Also, don't test the interfaces directly ( just in case you thought about it ). Only test the implementations since it's the implementations that actually do the work.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.