Reputation: 8757
I'm having trouble getting my unit tests to stay independent of each other. For instance, I have a linked list with two append
methods, one that takes a single element and appends it to the list, and one that takes another list and appends the whole thing; but I can't test the second append
method (the one that takes a whole list) without using the first append
method to populate the list I'm passing in. How do I keep the unit tests for these two methods separate from each other?
Upvotes: 1
Views: 443
Reputation: 5949
The situation you describe happens everywhere in testing: You have some class or library to test. The class or library has certain methods / functions that need to be tested, and for the test of some of these, you have to call other methods / functions of that same library.
In other words, when breaking down the test according to the four phase test pattern (setup, exercise, evaluate, cleanup), you want to call your class / lib in the exercise phase. However, it seems annoying that you have to call some elements of it also in the setup phase, and, possibly, also in the evaluate and/or cleanup phases.
This is simply unavoidable: You mentioned that in the setup for the list append
function you had to use the single-element append
function. But, it is even worse: You also had to use the constructor of your list class - no chance to get away without that one. But, the constructor could also be buggy...
What can certainly happen is, that tests fail (or, mistakenly pass) because the functions called in the setup are defective. A proper test suite, however, should (as was mentioned in the comments) also have tests for the other (call them lower-level) functions.
For example, you should have a number of tests which check that the constructor of your class works correctly. If at some point you modify the constructor so it becomes defective, all tests that use the constructor in the setup phase are no longer trustworthy. But, some of the tests that test the constructor itself (and thus call it in the exercise phase) should fail now.
From the overview of the test results you will then be able to identify the root cause of the test failures. This requires some understanding about the dependencies: Which of the tests focus on the lower-level aspects and which are higher-level in the sense that they depend on some lower-level functionality to work.
There are some ways to make these dependencies more apparent and therefore make it easier to analyse test failures later - but none of these are essential:
Upvotes: 2
Reputation: 9093
You can create one method which itself is not a unit test method but instead creates the conditions for multiple tests, then performs verification of the results. Your actual unit test methods will call into this other method. So you can use the same data set for multiple tests, and not introduce dependencies between test methods.
I don't know what language you are using, but here is an example for Objective-C in Xcode 5 with the new XCTest framework. I would do something like this:
- (void)performTestWithArray:(NSArray *)list
{
NSMutableArray *initialList = ...; // create the initial list you will use with multiple tests
[initialList addObjectsFromArray:list];
XCTAssertTrue(testCondition, @"message");
}
- (void)testAddSingleElement
{
NSArray *array = @[ @"one element" ];
[self performTestWithArray:array];
}
- (void)testAddList
{
NSArray *array = @[ @"first element", @"second element", @"third element" ];
[self performTestWithArray:array];
}
Upvotes: 0