B
Bart van Ingen Schenau
Ian said:It sounds to me like your test are too tightly coupled. You should be
able to run the tests for a module or a class in isolation.
Nah, I think it has more to do with a different understanding of
"multiple modifications".
Suppose I have a Point class that uses cartesian coordinates for its
internal representation. To satisfy a new testcase (for a new
requirement), I find that the internal representation should have been
in polar coordinates. Changing the internal representation in this way
requires me to modify multiple existing member functions. That is what I
mean with multiple modifications, and I see no reason to rerun my
testcases until all existing member functions have been changed to use
the new internal representation. I don't even expect the class to
compile before that.
True when you add test after the fact. But with TDD, test n tests the
function before the line is added, test n+1 tests it after.
Adding that line can have one of three effects:
- It adds a new path through the function
- It adds something that is 100% independent of all the existing code in
the function
- It modifies the function in such a way that at least one existing
testcases becomes invalidated.
In the first case, I would have a testcase as well.
In the second, I might have separate testcases, but I also might have
combined some of the tests in a single testcase.
In the third case, there is no way to have tescases M and N+1 pass at
the same time, because they have conflicting expectations about the
presence of that new line of code. One of those testcases would have to
be removed.
Note that it is not frequent testing or even TDD that I have a problem
with. It is the metric of lines.
How many lines do these two functions have? And how many testcases would
you have written to come to the functions? Do the number of testcases
match the number of lines?
long
divide (long lhs, long rhs)
{
long result;
if (rhs == 0)
{
throw std::domain_error("Division by zero");
}
result = lhs / rhs;
return result;
}
long divide (long lhs, long rhs) {
if (rhs == 0) throw std::domain_error("Division by zero");
return lhs / rhs;
}
Bart v Ingen Schenau