Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set up the internal state of a data structure during unit testing?

Tags:

c#

tdd

I'm writing a data structure in C# (a priority queue using a fibonacci heap) and I'm trying to use it as a learning experience for TDD which I'm quite new to.

I understand that each test should only test one piece of the class so that a failure in one unit doesn't confuse me with multiple test failures, but I'm not sure how to do this when the state of the data structure is important for a test.

For example,

private PriorityQueue<int> queue;

[SetUp]
public void Initialize()
{
    this.queue = new PriorityQueue<int>();       
}

[Test]
public void PeekShouldReturnMinimumItem()
{
    this.queue.Enqueue(2);
    this.queue.Enqueue(1);

    Assert.That(this.queue.Peek(), Is.EqualTo(1));
}

This test would break if either Enqueue or Peek broke.

I was thinking that I could somehow have the test manually set up the underlying data structure's heap, but I'm not sure how to do that without exposing the implementation to the world.

Is there a better way to do this? Is relying on other parts ok?

I have a SetUp in place, just left it out for simplicity.

like image 727
Neil Williams Avatar asked Oct 16 '08 03:10

Neil Williams


2 Answers

Add a private accessor for the class to your test project. Use the accessor to set up the private properties of the class in some known way instead of using the classes methods to do so.

You also need to use SetUp and TearDown methods on your test class to perform any initializations needed between tests. I would actually prefer recreating the queue in each test rather than reusing it between tests to reduce coupling between test cases.

like image 72
tvanfosson Avatar answered Oct 07 '22 14:10

tvanfosson


Theoretically, you only want to test a single feature at a time. However, if your queue only has a couple methods (Enqueue, Peek, Dequeue, Count) then you're quite limited in the kinds of tests you can do while using one method only.

It's best you don't over-engineer the problem and simply create a few simple test cases (such as the one above) and build on top of that to ensure an appropriate coverage of various features.

I feel it is appropriate to write tests that cover multiple features, as long as you have something underneath that will also break if one of the used features is broken. Therefore, if you have a test suite and you break your Enqueue, obviously, all of your tests (or most of them will fail), but you'll know Enqueue broke because of your simplest tests. The relationship of a test to its test suite should not be neglected.

like image 37
Jason Kealey Avatar answered Oct 07 '22 13:10

Jason Kealey