Learning Unit Testing VII – Running and Redesigning

I can see this page 10 being a pretty big thorn in my side. After stating fairly clearly

models can move up to their move rate

under the ‘Moving’ heading, it then says

A running fighter can move at double speed: 8″ rather than 4″, for example.

This is going to have a fairly large impact on the tests involved. The test for exceeding total movement (both in one and two moves) will only throw an exception if the total movement is double the model’s Movement rate now. In addition, a new test is going to have to be added to ensure that moving over the Movement rate sets an ‘IsRunning’ flag to true. The first test to add would be one that allows a model to move more than it’s Movement rate, but sets the IsRunning flag.

[TestMethod]
public void MoveModel_MovesDistanceOverMovementRateAndSetsIsRunningFlag()
{
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
testModel.MoveModel(newX, newY, newZ);
Assert.IsTrue(testModel.IsRunning);
}

Even with the correct code added to MoveModel –

if (this.TotalDistanceMoved > this.Movement)
{
this.IsRunning = true;
}

– this doesn’t work. Because ValidateMove is throwing an exception (as we designed in earlier). So ValidateMove has to allow up to twice the MovementRate.

if (GetDistanceFrom(positionX, positionY, positionZ) + this.TotalDistanceMoved > this.Movement * 2)
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}

Now, all the tests pass. But should they be? Checking my working, the MoveModel_CannotMoveFurtherThanModelsMovement test is moving the model more than twice it’s movement rate. So it is correct to throw an exception, and therefore pass the test. Anything testing to stay beneath the model’s Movement rate is obviously going to be beneath it’s doubled Movement rate, so they will continue to pass. MoveModel_TotalMovementInASingleTurn… that tests whether two movements that combined make more than the model’s Movement is also working correctly. But I’ve noticed I had an error in that test:

[TestMethod]
public void MoveModel_TotalMovementInASingleTurnCannotExceedModelMovement_ThrowsArgumentException()
{
bool correctExceptionThrown = false;
try
{
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
testModel.MoveModel(newX, newY, newZ);
testModel.MoveModel(0, 0, 0);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
}

The try catch was working on both MoveModel calls – and those values (after the calculation fix a couple of posts back) would have sent it way over the Movement on the first move, not the second. Moving the try…catch so that it only covers the second call to MoveModel would check that it’s failing in precisely the right place. By reversing my change to ValidateMove, I can confirm that the test would have failed before if the try…catch was in the right place. Putting it back in, and it throws an exception on the second MoveModel call, just as it should do. All the tests pass, and I’m a little more comfortable about them testing the right thing.

Lesson learned: Only test exactly the line you expect to break things.

The rest of the ‘Running’ section mentions not being able to shoot – this is something that we can cover in the Shooting section (after Movement), and isn’t important right now. The next bit that should matter is that a running model must stop 8 units away from an enemy model that he can see. This brings a number of things into play immediately:

  1. Can we identify models as being enemies?
  2. Can we identify which models can see others?
  3. How do we perform the sight checks all along it’s movement to work out if it can see the enemy (they may not be in sight at the beginning of the move, only halfway along it)?
  4. What action should be taken if the model’s movement is disrupted – should it still count as running? How can it be prevented from moving further?

Before we write tests, we should explore the problem a bit further.

Essentially, the enemy is at the centre of a circle 16 units in diameter (radius of 8). The active model’s path may intersect the circle at some point. If it does so, the active model must stop at the point along that path nearest to his starting point, providing that he can draw a line of sight to the enemy model at the centre of the circle.

So we only really need to work out if any point of the active model’s path intersects the enemy ‘disruption’ circles, and check those sections of the path for line-of-sight to the centre of the circle.

IE9 Beta + VS2010, and a blog-reading tip

I’ve been experimenting with IE9 beta in work recently, and been finding it annoying when I go to show someone what I’ve been working on and need to refresh a page a couple of times after running it from Visual Studio 2010 before it ‘takes’, and will display the page and work properly. I’m getting a little tired of saying ‘it’s only a beta…’ and sort of harms my decision to install it in the first place. Sure, hitting refresh a few times isn’t really cutting into my productivity any but it’s one of those small frustrations… something about controlling one’s environment, and smoothing our day’s problems out. That sort of thing.

I was browsing around trying to find help on a problem I’ve been working on at home (another learning project), and came across a blog that had a great explanation, a working sample, and the answer that I wanted – although the explanation didn’t point me to the answer that I wanted, when I went back and re-read it I realised it was right there and could have solved my problem an evening sooner. D’oh.

One of my habits when reading blogs is that if I find the post useful, or at least well-written and informative, I will go to the front page and see what they’ve posted recently. Dan Wahlin’s blog front page is an archive page, so you get to see a lot of interesting titles all at once. One of those titles was Getting the IE9 Beta to Play Well with Visual Studio 2010 and it described exactly the problem that I’m having in work with the beta, and also a suggestion to get around it. Since I found this in the middle of the Christmas bank holiday season, I had to wait a few days to try it out and see if it works… I’m not really keen on installing IE9 at home just to see a few days earlier! It seems to have worked so far, it’s a lot nicer than hitting refresh over and over till it sticks. So anyway, if you see a helpful or interesting blog post – look up recent posts in that blog. There might be something useful there too.

Learning Unit Testing VI – Code Coverage

Before I get into finally finishing off that blasted page 10, I thought I’d go through a code coverage run to see how I was doing. Test Driven Development, see, everything should be covered by a test.

image

7.41% of the code is not covered by tests! I must be doing this wrong…

image_3

Phew, that was a relief. Turns out all of that uncovered code is in the WrongPhaseException I created from the Exception snippit without thinking about it. Activating the code coverage colouring in the code shows me what I’ve missed:

image_4

Because I only use one constructor out of a possible four, it counts as only 25% coverage and brings my average code coverage way down.

If I was to remove all those extra constructors (and leave them to the default Exception behaviour), would it improve my code coverage score?

image_5

Absolutely. It might be a bit like cheating (those methods are still not covered by tests), but since they’re core parts of the framework it doesn’t feel necessary to me. Short and sweet, on to part VII!

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.

Learning Unit Testing V – Refactoring Mistakes

I implied in the last post that I had made a mistake when I moved the MoveModel code into the Model class from the MovementManager class. Now, tests on the MovementManager class are actually testing functionality in the Model class. I also discovered that I am not properly testing the ‘GetDistanceFrom’ method with known data at all. This will have to be corrected.

Since I already have Model implementing an IModel interface, it’ll be easy enough to mock the Model part in the MovementManager. To see what tests are reaching into Model.MoveModel, I can just alter that method to throw an exception and see which tests fail.

image

Since this functionality has been moved to the Model class, these tests should actually be made against the Model class itself. Simple? Yes, but incorrect, as I found out next – it still fails on one condition and checking further, I don’t believe it’s checking the other one correctly. The validation of whether or not a model may make a move (ie, the distance is still under it’s Movement rate) is done in the MovementManager. My two options at this point are: move the validation back to the MovementManager and do a lot of mocking around the Model, or to move that validation into the Model as a ValidateMove method. Then the movement manager really becomes a mere progress tracker for the Movement phase… but I think that’s probably the best idea in this situation. Just one more test to move over (MoveModel_CannotMoveFurtherThanModelsMovement), then the GetDistanceFrom method needs to be tested. I think the following cases will need to be covered:

  • Full three-dimensional movement (all values change)
  • Two-dimensional movement (one value doesn’t change)
  • One-dimensional movement (only one value does change)
  • Cover reverse cases of each of the above (so the direction is backwards)

This test (worked on with a calculator and doodles to prove my working), however:

[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenAllValuesChange()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 4;
double result = testModel.GetDistanceFrom(2, 5, 7);
Assert.AreEqual(3.74, Math.Round(result, 2));
}

Shows me that either my test calculation is wrong or my original working is wrong. In the GetDistanceFrom method, this line

distance = Math.Sqrt(Math.Sqrt((differenceX * differenceX) + (differenceY * differenceY)) + (differenceZ * differenceZ));

Should actually be

distance = Math.Sqrt((differenceX * differenceX) + (differenceY * differenceY) + (differenceZ * differenceZ));

So I got the calculation wrong. Now the test passes, but another one breaks.

image_3

This is because that movement calculation now requires the model to move further than it’s allowed distance. Fixing that test’s values (from 3, 4, 5 to 2, 2, 2) and adding in the following tests:

[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenTwoValuesChange()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 4;
double result = testModel.GetDistanceFrom(1, 5, 7);
Assert.AreEqual(3.61, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenOneValueChanges()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 4;
double result = testModel.GetDistanceFrom(1, 3, 7);
Assert.AreEqual(3, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenAllValuesChange_Reversed()
{
Model testModel = new Model();
testModel.PositionX = 2;
testModel.PositionY = 5;
testModel.PositionZ = 7;
double result = testModel.GetDistanceFrom(1, 3, 4);
Assert.AreEqual(3.74, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenTwoValuesChange_Reversed()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 5;
testModel.PositionZ = 7;
double result = testModel.GetDistanceFrom(1, 3, 4);
Assert.AreEqual(3.61, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenOneValueChanges_Reversed()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 7;
double result = testModel.GetDistanceFrom(1, 3, 4);
Assert.AreEqual(3, Math.Round(result, 2));
}

Gives me 19 passes out of 19 tests. Excellent – I was expecting some of the 0-distance values being squared and rooted to throw some sort of calculation exception in .Net, but I can get along with this result.

This leaves me with my refactoring mess cleaned up, a calculation error solved, a method I somehow missed tests for covered properly, and all ready to tackle the last part of page 10 – a much longer page than I had initially expected. “Ooh look”, said the me at the beginning of the week, “half the page is picture and prose, and the other half is mostly descriptive. One or two posts to talk about design ideas and I’ll be on page 20 in a fortnight!” Isn’t hindsight awesome.

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.

Learning Unit Testing IV – Diagrams and Mathematics

Programming uses maths. It’s hard to ignore sometimes, especially when modelling something that is inherently graphical and position based such as a game.

I’ve decided to give the models three different position indicators – PositionX, PositionY and PositionZ. This will describe their exact position anywhere on the board – including on a ladder, a walkway or the ground. When they are given instructions to move, they should change those position variables accordingly – but not past the maximum move distance.

My two options are to either pass in a distance and direction (both X direction and Y direction, like an aircraft would need to navigate) or a new set of position points – in essence, saying precisely ‘go here’. In the first, the new position would need to be calculated, and in the second the distance would need to be calculated. Either way, I’d need to write both sets of code at some point.

I think that it will be easier to back-track the distance and directions from a set of positions than it would be the other way around. Transforming a simple co-ordinate of (X, Y, Z) – where X is East-West, Y is North-South and Z is Up-Down – such as (1, 2, 1) to a new position of (2, 1, 2) tells me that the model has moved up a slope to the North-East for a distance of… actually, that bit gets harder. But it’s at least easy to work out with trigonometry!

image

On a two-dimensional plane, it is fairly simple to work out – as on the (hastily scribbled, not-to-scale) diagram to the left. This brings back distant memories of Pythagoras – a2 + b2 = c2 – or, the square root of the difference in X + the difference in Y is the distance between the two points.

On a three-dimensional world, this is a bit more complicated – it has to be reduced to two different two-dimensional triangles to calculate the distance. The difference between two points is the ‘difference in X’ value of the second triangle. Another way of putting it would be √ (√ ((X1 – X2)2 + (Y1 – Y2)2) + (Z1 – Z2)2). Excellent.

In my original example then, the answer would be 1.554 arbitrary units. I could work out the directions (angles) by using more of my dusty trigonometric knowledge, but I only need to know the distance at this point. All I need to know are some test values that give a value above a model’s Movement rate and some under, so I can test the outcomes of the MoveModel method. In the case of overshooting a model’s permitted movement, I think I’ll throw a new exception. I can see (a few pages down the line) that the model is going to need to be able to tell it’s distance from other objects anyway, so this could be checked before attempting to move the model.

Time for a test! These values will move the model just a smidgen over 4 units.

[TestMethod]
public void MoveModel_CannotMoveFurtherThanModelsMovement()
{
bool correctExceptionThrown = false;
try
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
decimal newX = 5;
decimal newY = 6;
decimal newZ = 3;
movementManager.MoveModel(testModel, newX, newY, newZ);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
}

The code to pass this in the MovementManager is:

public void MoveModel(Model testModel, float newX, float newY, float newZ)
{
if (testModel.Movement < testModel.GetDistanceFrom(newX, newY, newZ))
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}
}

And in the Model itself is:

public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }
public double GetDistanceFrom(float positionX, float positionY, float positionZ)
{
double distance = 0;
double differenceX = this.PositionX - positionX;
double differenceY = this.PositionY - positionY;
double differenceZ = this.PositionZ - positionZ;
distance = Math.Sqrt(Math.Sqrt((differenceX * differenceX) + (differenceY * differenceY)) + (differenceZ * differenceZ));
return distance;
}

I can’t help but think that I am still over-designing this, but it feels about right to me. Finally, the test to ensure that the model actually does move:

[TestMethod]
public void MoveModel_PositionHasChanged()
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
movementManager.MoveModel(testModel, newX, newY, newZ);
Assert.AreEqual(5, testModel.PositionX);
Assert.AreEqual(4, testModel.PositionY);
Assert.AreEqual(3, testModel.PositionZ);
}

Which requires a change to MoveModel –

public void MoveModel(Model testModel, float newX, float newY, float newZ)
{
if (testModel.Movement < testModel.GetDistanceFrom(newX, newY, newZ))
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}
else
{
testModel.PositionX = newX;
testModel.PositionY = newY;
testModel.PositionZ = newZ;
}
}

Next, the situation that a model may move in two goes – and cannot go above it’s movement rate in both chunks. For this, we’ll have to record the distance moved.

[TestMethod]
public void MoveModel_TotalMovementInASingleTurnCannotExceedModelMovement_ThrowsArgumentException()
{
bool correctExceptionThrown = false;
try
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
movementManager.MoveModel(testModel, newX, newY, newZ);
movementManager.MoveModel(testModel, 0, 0, 0);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
}

Movement of a model is starting to take on several different, inter-related actions so I’m going to move that stuff into the Model class itself. MoveModel in the MovementManager becomes simpler:

public void MoveModel(Model testModel, float newX, float newY, float newZ)
{
if (testModel.Movement < testModel.GetDistanceFrom(newX, newY, newZ) + testModel.TotalDistanceMoved)
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}
else
{
testModel.MoveModel(newX, newY, newZ);
}
}

And the addition to the Model class is:

public double TotalDistanceMoved { get; private set; }
public void MoveModel(float positionX, float positionY, float positionZ)
{
this.TotalDistanceMoved += GetDistanceFrom(positionX, positionY, positionZ);
this.PositionX = positionX;
this.PositionY = positionY;
this.PositionZ = positionZ;
}

Next is to make sure we can make multiple moves without going over the limit and throwing an exception:

[TestMethod]
public void MoveModel_MakeTwoSmallMovementsWithoutGoingOverMovementRate()
{
bool correctExceptionThrown = false;
try
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 1;
float newY = 1;
float newZ = 0;
movementManager.MoveModel(testModel, newX, newY, newZ);
movementManager.MoveModel(testModel, 0, 0, 0);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsFalse(correctExceptionThrown);
}

This doesn’t need any new code, it just proves that the existing code still works. Finally, there needs to be a check that the TotalDistanceMoved will reset to 0 at the beginning of each turn. What is going to be the trigger for that? Currently, the only place that a new turn is known about is the GameManager, and the IncrementPhase method. The question is, therefore, how should the model be informed of this change? Should the GameManager contain a collection of all the models currently in the game, so the IncrementPhase method can just iterate that collection? Or should models be held elsewhere, and subscribe to a ‘new turn’ event that is triggered? I think it makes most sense for the models to be stored in the GameManager – at least at this time – and for them to expose a ‘new turn’ method.

I have become aware as I am refactoring this code around that I’m starting to break the isolation of the unit tests – some tests are calling methods in classes that are not the class under test. This will obviously need to be refactored, but I’d like to finish the current train of thought first. To do that properly though, I need to add a new test class – ModelTests – and test the NewTurn method on that as well as making sure the GameManager calls NewTurn on each of it’s (mocked) Models. Testing these two things becomes an integration test, and cannot guarantee which class/method is actually responsible for failing a test.

[TestMethod]
public void IncrementTurnPhase_CallsNewTurnOnModels()
{
GameManager manager = new GameManager(2);
Mock<IModel> mockModel = new Mock<IModel>();
manager.Models.Add(mockModel.Object);
manager.IncrementPhase(); // Go to Shooting
manager.IncrementPhase(); // Go to Close Combat
manager.IncrementPhase(); // Go to Recovery
manager.IncrementPhase(); // Go back to Movement
mockModel.Verify(item => item.NewTurn(), Times.Once());
}

In the above test, I am adding a mock model into the GameManager, then verifying that the NewTurn method is called once. I add the Models property, create an IModel interface, change the IncrementPhase code to

public void IncrementPhase()
{
if (CurrentPhase == TurnPhase.Recovery)
{
CurrentPhase = TurnPhase.Movement;
if (CurrentPlayersTurn == NumberOfPlayers)
{
CurrentPlayersTurn = 1;
}
else
{
CurrentPlayersTurn++;
}
foreach (IModel model in this.Models)
{
model.NewTurn();
}
}
else
{
CurrentPhase++;
}
}

And… four tests fail on me!

image_3

This is exactly the purpose of unit testing. In this case, I realised that the Models collection (List<IModel>) hadn’t been initialised – these tests suddenly failing are a result of the turn ending and attempting to iterate through a collection that hasn’t been set up yet – a NullReferenceException. One quick tweak to the constructor, and they’re all passing again.

Finally, the test on the Model side to make sure that it sets TotalDistanceMoved back to zero.

[TestClass]
public class ModelTests
{
[TestMethod]
public void NewTurn_SetsDistanceMovedToZero()
{
Model testModel = new Model();
testModel.TotalDistanceMoved = 4;
testModel.NewTurn();
Assert.AreEqual(0, testModel.TotalDistanceMoved);
}
}

And the code in Model being insultingly simple:

public void NewTurn()
{
this.TotalDistanceMoved = 0;
}

Thirteen tests so far, and all passing. A quick lesson in how unit tests can quickly point to something going awry – though I am sure more important lessons will come along as I move through the project – and we’re almost to the end of page 10 in the rulebook. This has been a long section, and it’s a good point to leave it at.

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.

Learning Unit Testing III – Emergent Design

So having seen the answers on my own StackOverflow question on TDD Design, I’ve decided to go ahead with the ‘emergent design’ crowd and see what happens. It appears that the refactoring and mid-stream redesigning is an integral part of the TDD process. It’ll all, of course, be described here (the process might be a little bit stream-of-consciousness) as I go through my design decisions ‘out loud’).

I got up to the end of page 9 last time, about to start on the Movement section. In keeping with the single responsibility principle, I’ll be putting movement logic in it’s own class. Movement happens in a strict order – all chargers are declared and moved first, then any compulsory moves are made, and finally ‘everything else’ movement. This would be represented in the MovementManager class as having an internal phase structure, just like the GameManager.

The question is, where should this be called from? The decision to stop moving chargers and move onto the next sub-phase is a player choice, therefore a user interface trigger (just as IncrementPhase). It is not something that can be automated or inferred. Should the IncrementPhase method (and associated fields) be moved out into a TurnManager class which is owned by GameManager – GameManager can then expose valid actions based on what phase and whose turn it is. Would that even need to be moved out into another class – if I am deciding actions based on what the GameManager will expose to a user interface, the turn logic can remain in GameManager.

Alternatively, the MovementManager can broadly restrict actions based on the properties of it’s parent (GameManager) and regulate it’s own, internal restrictions based on sub-phase and a variation of that logic. This seems like the simplest solution – I can raise a custom exception if a method is called on the MovementManager that is invalid (wrong sub-phase, or wrong phase entirely). Time for a new cl- uh, test class, obviously. Some of the tests can be cribbed from the existing GameManagerTests, but there’s no real worry about whose turn it is.

[TestClass]
public class MovementManagerTests
{
[TestMethod]
public void IncrementSubPhase_RollsBackToMoveChargersAfterEverythingElse()
{
MovementManager movementManager = new MovementManager();
movementManager.IncrementSubPhase(); // Go to compulsory moves
movementManager.IncrementSubPhase(); // Go to everything else
movementManager.IncrementSubPhase(); // Go back to Move Chargers
Assert.AreEqual(MovementSubPhase.MoveChargers, movementManager.CurrentSubPhase);
}
[TestMethod]
public void IncrementSubPhase_MovesForwardSubPhase()
{
MovementManager movementManager = new MovementManager();
MovementSubPhase firstPhase = movementManager.CurrentSubPhase;
movementManager.IncrementSubPhase();
MovementSubPhase secondPhase = movementManager.CurrentSubPhase;
Assert.AreNotEqual(firstPhase, secondPhase);
}
}

As expected, after resolving build errors (new class, property and method stubs) the two tests fail. And with the barest minimum of code:

public class MovementManager
{
public MovementSubPhase CurrentSubPhase { get; private set; }
public void IncrementSubPhase()
{
if (CurrentSubPhase == MovementSubPhase.EverythingElse)
{
CurrentSubPhase = MovementSubPhase.MoveChargers;
}
else
{
CurrentSubPhase++;
}
}
}

It all passes. Next up, there needs to be a way of preventing the Movement sub-phase from advancing when it is not the Movement phase at all. The expected behaviour for this should be a custom exception to be thrown, and dealt with elsewhere (presumably, the hypothetical UI). To fool it that it is not the Movement phase, it needs to have a reference to the GameManager – passed in as a constructor parameter to the MovementManager. The GameManager passed in for this test also needs to be mocked, so it will need to be given a public interface. One quick mocking later:

[TestMethod]
public void IncrementSubPhase_ThrowsExceptionIfNotMovementPhase()
{
bool correctExceptionThrown = false;
try
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
mockGameManager.Setup(item => item.CurrentPhase).Returns(TurnPhase.Shooting);
MovementManager movementManager = new MovementManager(mockGameManager.Object);
movementManager.IncrementSubPhase();
}
catch (WrongPhaseException ex)
{
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
}

Which is passed by:

private void ValidatePhase()
{
if (_gameManager.CurrentPhase != TurnPhase.Movement)
{
throw new WrongPhaseException("Cannot perform Movement actions in the " + _gameManager.CurrentPhase.ToString() + " phase.");
}
}

And calling that at the beginning of the IncrementSubPhase method.

Now it’s time to make some changes to the (as yet unused) Model class. Now it starts to get into things in a bit more of a distinct rule structure – the next line states that ‘models can move up to their move rate in inches in any direction’. I’m deciding that ‘inches’ refers to an arbitrary (and divisible) number, so a decimal will serve very well to decide how far they’ve moved, and how far they can move. The movement manager can either take in a co-ordinate to specify the target position, and change the model’s position to as far as it can go towards that point, or take in a distance and direction and move the model as specified.

It’ll probably be easier to sort out the distance and direction at the moment – those calculations will need to be made in the code that calls the MovementManager – though at some future point, these could be made into helper methods on the MovementManager. To work out where the model’s new position is, we need diagrams – this will have to wait until the next post!

This has been a nice long post that gets about halfway through page 10. I’m still not sure I’m allowing the design to emerge – I am, for example, thinking a few tests ahead of where I am – but at this stage, I’ve not (consciously) made a decision about design based on that forewarning, only on the basis of ‘I want Movement code separate from Game Manager code). This is more to do with the single responsibility principle than some master design drawn upfront.

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.

Learning Unit Testing II – TDD vs. Traditional Design

As you can see, I’ve only done a small amount of Test-Driven Development so far. I notice that for small classes – so far, there’s only a very simple turn tracker – it’s easy to write a test first when there’s only very little code and no interaction with other classes. When things get a little more complex, will it still be so easy?

I am wondering how people use TDD when they have big projects (as this will invariably become). Is it possible to stick to just writing code to pass tests all the way through to the end? Surely, at some point, major refactoring will need to be done when something comes right out of nowhere. I can see one example I’ll run into at some point: in Necromunda, a model may go on ‘Overwatch’. This allows them to fire in their opponents turn, shooting at a target before it’s move, after it’s move or during it’s move. That’s probably going to require a major change to the Movement code (to account for the opponent taking an action), which could itself lead to a lot of refactoring. Should I try and design around this idea now, or wait until much, much later when I get to the Overwatch section to worry about it?

Whether or not there is a simple solution to that particular problem will depend on many things – not least, the movement and shooting code that is written before it. I would traditionally sit down and try to work out exactly how to architecture the whole thing, taking into account things like shooting, overwatch, etc before I sit down to code. TDD seems to suggest that I write the test, then the code, and then eventually get around to a new test that – had I known – would have influenced the code I wrote earlier. I can see that would have some benefits (for example, the Bowling Game Kata shows the change in design to a simpler one due to TDD) but I don’t know how likely it is that writing code just to pass the test will lead to a design path that isn’t optimal given later functionality requirements.

Maybe I am worrying about nothing, and the forced simplicity of design for TDD will ultimately lead to a good solution. Maybe I’m missing the point entirely, and there will be major refactoring down the road, and that’s a good thing. If that’s true, isn’t TDD going to end up taking a lot more time than is useful? Is there a secret, undocumented art to writing code following TDD where certain things are written first entirely to limit this sort of refactoring? If that’s the case, I may be handicapping myself by slavishly following the rulebook.

After reading the accepted answer on this StackOverflow question,  I’ve decided to push ahead with my TDD experiment. I need to understand the beast. I’ve got an idea of how certain things should be done, but we’ll see if it makes sense once I’ve laid the foundations using TDD. It’s going to be an interesting way to do the work!

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.

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.

My Next Learning Project

I’ve long ago established that I learn best from doing things. Even if those ‘things’ never get anywhere, the journey through real problems helps me get a handle on what they are. My army list program got me through WPF, and then MVC. It’s faltered, since I don’t really have the enthusiasm for it that I once did (I’ve spent over a year on it, and as it is a learning project I keep needing to redesign things…)

This brings me to my new idea. Everyone who is anyone in .NET programming at the moment is unit testing. I’ve read a lot about unit testing, and dependency injection, and all those things but I am not entirely convinced I am doing it right. It was when I tried to apply these things to the wargame tools / army list program that I realised I had lost my direction with that one, and it was time to move to something new. Sticking with what I knew best, I initially thought about a WFRP (second edition, naturally) calculator or helper of some sort – then quickly abandoned that idea as madness.

But what about an easier system? Necromunda is a relatively simple game system. Something to calculate the effects of it’s combat, shooting modifiers, exotic weapons and the many charts and tables for the end-game clean-up would be ideal. If I felt adventurous, I could even add in Gorkamorka variants.

The scope I am envisioning is a disconnected class library, capable of managing and running a game of Necromunda. In theory, I could hook it up to a Silverlight, WPF or XNA (ha!) frontend, and all the functionality will be there to go. I would just need to connect certain bits for display. As it is all pure logic, it should be a good way to practice unit testing using a Test-Driven Development approach.

I’ll be documenting each step of the way in here, so I am forced to think about and describe what I’m doing. The rules for the game are available for free (click on the image to get them) from Games Workshop, so it shouldn’t be a problem me mentioning the odd one or two, followed by reams of code.

Validation and self-worth!

I had an answer accepted as the answer on Stack Overflow! I answered this question absolutely ages ago, not expecting it to go anywhere (the question had already been answered, but I felt it was a valid, different approach) but slowly, over the months, it’s been up-voted (until, I am pleased to say, it had a vote more than the accepted answer) and at the weekend the accepted answer was actually changed to my one.

It makes me feel good, anyway. Now I just need to try hard and see if I can get some more – rather than my usual activity on there, asking tricky questions for which there isn’t an easy answer (or in one deleted case, a simple answer I should really have spotted myself).

Anyway, I answered a question: Woohoo!