Simon V.
Simon V.

Reputation: 1485

How can I keep my unit tests independent of each other in this simple case?

I'm writing a small game in C# using Test Driven Development approach. I'm facing a problem:

I have a class CheckersBoard:

public class CheckersBoard
{
    private const string InitialBoardPattern = "B-B-B-B-" +
                                               "-B-B-B-B" +
                                               "B-B-B-B-" +
                                               "--------" +
                                               "--------" +
                                               "-W-W-W-W" +
                                               "W-W-W-W-" +
                                               "-W-W-W-W";

    public SquareStatus[,] Squares { get; private set; }

    public CheckersBoard(IBoardGenerator boardGenerator)
    {
        Squares = boardGenerator.GenerateFromPattern(InitialBoardPattern, 8, 8);
    }

    //....
}

And a class BoardGenerator:

public class BoardGenerator : IBoardGenerator
{

    public SquareStatus[,] GenerateFromPattern(string pattern, int width, int height)
    {
        //....
    }

}

BoardGenerator allows me to initialize CheckersBoard in a very readable way. So, I really would like to use BoardGenerator in my unit tests to avoid ugly array initialization.

But it's against the rule that says that I must keep all my unit tests independent of each other. If the test of GenerateFromPattern fails, that will produce a "cascade" effect and all the tests which use GenerateFromPattern will fail too.

This is the first time I have ever used unit tests so I'm a little bit confused. How can I avoid this problem? Is there something wrong with my design?

Upvotes: 6

Views: 331

Answers (2)

k.m
k.m

Reputation: 31444

Apparently this is a common problem without obvious answer, and I happened to deal with two similar questions:

To certain level, reusing business logic (other, tested components) is kind of similar to using 3rd party libraries in unit testing - we assume they work, and don't bother generating extra assertions about them. Will you have any hesitations to use List<T> in unit test? Most likely no. Note however, that List<T> is tested by many other developers daily and has big software house behind it. Can you say the same about BoardGenerator?

Another question to consider is, will the CheckersBoard test code be as obvious to somebody who never worked on BoardGenerator as it is to you? You claim it is readable, but that's common given the authoring. Maybe using array initialization is not as bad (unreadable) as you think it is.

Upvotes: 2

James
James

Reputation: 82096

You could mock your BoardGenerator class or just fake the implementation e.g.

internal class MockBoardGenerator : IBoardGenerator
{
    public SquareStatus[,] GenerateFromPattern(string pattern, int width, int height)
    {
        // return fixed test data
    }
}

Upvotes: 1

Related Questions