tags:

views:

416

answers:

3

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?

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

+1  A: 

i think this is ok; but clear the queue at the start of your test method ;-)

Steven A. Lowe
+5  A: 

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. As @Steven A. Lowe indicated, you also need to use SetUp/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.

tvanfosson
upvote for being more specific - and spelling my name right ;-)
Steven A. Lowe
So how would I access this private accessor? Reflection? or the InternalsVisibleTo magic?
Neil Williams
use InternalsVisibleTo
Ben Robbins
+2  A: 

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 simple 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.

Jason Kealey
Interesting. I'm not really sure how to use a test suite, would you organize it so that all the Enqueue tests are in a suite together etc.?
Neil Williams
It's also called as test fixture - it's the class that contains the test methods.
jop