I've heard that it's ideal to have one assert
(or expect
or should
, etc) per aspect of a component's behavior you're trying to test. Is this how it works? An addOne
function would be tested like this, I suppose (example is written in javascript syntax):
it("returns one plus its input", function() {
assert(addOne(5) == 6);
});
And I suppose that would be the complete extent of the tests for the addOne
function, as each individual assert
should be orthogonal.
How would one go about testing something more complex, but which still really has only one defining behavior?
Say for example we have an OO class for storing a chessboard, and each tile of the board is assigned an id number between 0 and 63. Then let's say there's a method getNeighbors
which takes an integer from 0 to 63 and returns a sorted integer list/array/set containing the ids of all neighboring tiles. For example, if the numbers were laid out starting at 0 in the upper-left and incrementing across rows, then getNeighbors(0)
would return [1, 8, 9]
I suppose.
How many test cases would be written for this? I see two main options:
Test the entire behavior once
it("throws an error when called with a number below 0", ...);
it("throws an error when called with a number above 63", ...);
it("returns a list of the IDs of the neighboring tiles", function() {
assert(getNeighbors(0) == [1, 8, 9]);
});
This seems like too weak of a test.
Test each case of the behavior once
it("throws an error when called with a number below 0", ...);
it("throws an error when called with a number above 63", ...);
it("returns [1, 8, 9] when called on 0", function() {
assert(getNeighbors(0) == [1, 8, 9]);
});
it("returns [0, 2, 8, 9, 10] when called on 1", function() {
assert(getNeighbors(1) == [0, 2, 8, 9, 10]);
});
... // and so on, for 62 more test cases
This seems over-the-top.
Best Answer
You can do two things:
First, use parameterized tests to minimize the duplication of the test code:
Second, partition your testcases into equivalence classes where you expect the code to behave exactly the same, and have only one test for each class. In your cases, the classes would probably be: