I've been working
to assign ownership to the correct team for "unit tests"
recently. While changing the team name
that owns each test is straightforward in most cases, in some I had to step
into the tests to determine exactly what was being validated. This is a great way for me to learn the code,
by the way.
In any case, I soon
discovered that some of the tests I had been thinking about as unit tests are
actually integration tests. The
difference between the two is what I want to mention today.
A unit test is the
simples form of automated testing that we write. In a simple case, suppose I am writing a
calculator application and want to multiply two whole numbers. I could write a function that looks something
like this:
int multiply(int
first, int second)
{
int
result = 0;
for
(int i=0;i<first;i++)
{
result
= result + second;
}
return
result;
}
Now when I write a
unit test, I can pass in 8 and 4 and validate I get 32 as a result and also 0
and 2 to validate I get 0. Not much to
this but that is the point of a unit test - it tests just one function. If it fails, I know the exact one function
that now needs to be investigated.
Then suppose I add a
power function to the calculator.
Raising a number to a power is just multiplying the number by itself as
many times as I want the power t be, so my function to this might be:
int power(number,
power)
{
If(power<0)
return
ERROR_CODE;
int
result ;
for
(int i=0;i<power;i++)
{
result
= multiply(result, 1);
}
return
result;
}
I just call my
multiply command as part of my power command.
Reusing code is always a goal.
But now when I test
my power function, I have a challenge if the test fails. A failure might be in the part of the code
that is unique to my power function, or it could also be in the multiply
command. There could also exist a case
in which both tests are failing for different reasons. So instead of quickly finding the one bit of
ode I need to investigate, I now have 2 places to look and three investigations
to complete.
Looking more at the
calculator, if I added a "Compute compounded interest function" I
would need to use the power function and the multiply function and possibly a
few others as well. Now if a test fails
I might have dozens of locations to investigate.
On the positive
side, I might also discover a flaw in my code that only shows when one function
calls another. This type of
functionality is referred to as an integration
test and is absolutely critical to shipping software. Read about the most famous example of not
covering this here:
a Mars satellite was lost because Lockheed Martin tested all their code with
miles and everyone else tested all their code with kilometers. Very loosely speaking, the Lockheed code told
the spacecraft it was "1,000,000" from earth it meant one million
miles. When the satellite heard
"1,000,000" it assumed kilometers and that was the root of the loss
of the satellite. Integration tests
should have been use to catch this type of error.
Eagle eyed readers
will point out that my power function is useless without the multiply
function. How can I isolate my unit
tests to use only the code in that function instead of needing the multiply
command as well? I'll cover that next
time up.
Questions, comments,
concerns and criticisms always welcome,
John
No comments:
Post a Comment