Learning Unit Testing I – The Basics

Right, so I’ve chosen my project and I’m ready to begin. I’ll skip past the introduction, straight to page 8 of the rulebook. The characteristics section. This is basically a class layout, nothing too heavy, so I’ll start off by creating Model.cs:

class Model
{
public string Name { get; set; }
public int WeaponSkill { get; set; }
public int BallisticSkill { get; set; }
public int Strength { get; set; }
public int Toughness { get; set; }
public int Wounds { get; set; }
public int Initiative { get; set; }
public int Attacks { get; set; }
public int Leadership { get; set; }
}

Nothing really testable here yet. No point in testing basic getters and setters.

Next up is a description of the turn structure – this calls for a game manager of some sort. How about GameManager.cs, with an enum (TurnPhase)?

class GameManager
{
    TurnPhase CurrentPhase { get; private set; }
    int _numberOfPlayers;
    int _currentPlayersTurn;
}
enum TurnPhase
{
Movement,
Shooting,
CloseCombat,
Recovery
}

I think I’ll also add in an integer to GameManager to determine the number of players, and the number of the player whose turn it is. That should be enough to track that for now. To increment the turn onwards, though I’m not sure how that will be triggered yet, I need to add some actual logic! This should have a unit test. In proper TDD fashion, the test will be written first.

[TestMethod]
public void IncrementTurnPhase_RollsBackToMovementPhaseAfterRecovery()
{
GameManager manager = new GameManager();
manager.IncrementPhase(); // Go to Shooting
manager.IncrementPhase(); // Go to Close Combat
manager.IncrementPhase(); // Go to Recovery
manager.IncrementPhase(); // Go back to Movement
Assert.AreEqual(TurnPhase.Movement, manager.CurrentPhase);
}

This looks about right – but I’ll need to give GameManager a bit of a tidy up and make things a little more accessible. Now the code to pass that test:

public void IncrementPhase()
{
if (CurrentPhase == TurnPhase.Recovery)
{
CurrentPhase = TurnPhase.Movement;
}
else
{
CurrentPhase++;
}
}

That’s nice and neat. But I found that without writing any code in that method, it still passes – since the turn phase is still Movement. Another test to make sure that it only increments one space will probably be in order.

[TestMethod]
public void IncrementTurnPhase_MovesForwardPhase()
{
GameManager manager = new GameManager();
TurnPhase firstPhase = manager.CurrentPhase;
manager.IncrementPhase(); // Go to Shooting
TurnPhase secondPhase = manager.CurrentPhase;
Assert.AreNotEqual(firstPhase, secondPhase);
}

This one does the trick. Makes sure that the phase has changed within the turn.

Finally, the last couple of paragraphs on page 9 say that control alternates between players. I know from experience that there could easily be multiple players, and I want to be ready for that. So the GameManager will increment _currentPlayersTurn every time the turn finishes (after the Recovery phase), and reset the _currentPlayersTurn integer back to 1 when it exceeds _numberOfPlayers.

Once more, write a test to check that it increments at the end of a turn:

[TestMethod]
public void IncrementTurnPhase_ChangesPlayerAtEndOfTurn()
{
GameManager manager = new GameManager();
int firstTurn = manager.CurrentPlayersTurn;
manager.IncrementPhase(); // Go to Shooting
manager.IncrementPhase(); // Go to Close Combat
manager.IncrementPhase(); // Go to Recovery
manager.IncrementPhase(); // Go back to Movement
int secondTurn = manager.CurrentPlayersTurn;
Assert.AreNotEqual(firstTurn, secondTurn);
}

Now to test the next bit, it’ll be necessary to add a proper constructor with a parameter – number of players. Here’s the test:

[TestMethod]
public void IncrementTurnPhase_ReturnsToFirstPlayerAfterAllHaveHadTurn()
{
GameManager manager = new GameManager(2);
manager.IncrementPhase(); // Go to Shooting
manager.IncrementPhase(); // Go to Close Combat
manager.IncrementPhase(); // Go to Recovery
manager.IncrementPhase(); // Go back to Movement
manager.IncrementPhase(); // Go to Shooting
manager.IncrementPhase(); // Go to Close Combat
manager.IncrementPhase(); // Go to Recovery
manager.IncrementPhase(); // Go back to Movement
Assert.AreEqual(1, manager.CurrentPlayersTurn);
}

And the code that passes both of those tests:

public GameManager(int numberOfPlayers)
{
NumberOfPlayers = numberOfPlayers;
CurrentPlayersTurn = 1;
}
public void IncrementPhase()
{
if (CurrentPhase == TurnPhase.Recovery)
{
CurrentPhase = TurnPhase.Movement;
if (CurrentPlayersTurn == NumberOfPlayers)
{
CurrentPlayersTurn = 1;
}
else
{
CurrentPlayersTurn++;
}
}
else
{
CurrentPhase++;
}
}

After adding the requirement for a number of players to the other tests, all the tests so far pass. There is, as I’ve been warned, more test code than real code (67 lines in GameManagerTests compared to 40 in GameManager) but seeing all those little green ticks is definitely a psychological boost. As I’ve neatly finished page 9 and the ‘Rules’ section, I will start the ‘Movement’ section next time. This will have a bit more design than the fairly sparse classes here, and a bit more deliberation over where to put particular bits of code. I know a big idea of TDD is to write, then refactor, but I don’t want to do too much refactoring. It could become quite a hassle, especially later in the day. We’ll see when we get there!

This is a learning project I am documenting in order to teach myself TDD and unit testing – as I publish this, I have already written many parts in advance but I want to know what I’m doing wrong! If you see improvements or corrections, either to the code or the process, please leave a comment and let me know! Introduction to this project can be found here.

Leave a comment

Your email address will not be published. Required fields are marked *