Here's my function which takes pointer to integer to an integer. (42 in this case)
void ft_ft(int *nbr)
{
*nbr = 42;
}
Can someone explain me how to write a test for this function?
CodePudding user response:
You could add a call and an assertion (which will only be active in debug builds):
#include <assert.h>
void ft_ft(int *nbr) {
*nbr = 42;
}
int main(void) {
int foo = 0;
ft_ft(&foo); // call the function
assert(foo == 42); // exit with an error message if foo is not 42
}
CodePudding user response:
The purpose of testing is to find bugs.
In all except very “small” or simple functions, it is beyond our abilities to prove a function works: Most functions are too complicated for mathematical proof without great effort or have more cases than we can test. For example, a function that computes xy given two 64-bit double
values x and y has 2128 cases to test, and that is more than we can test exhaustively.
Therefore, testing is usually not done to “see if a function works.” We want to find bugs, not to find working code. Another reason to frame the hunt this way is human psychology: If you tell a human to see if a function works, that makes them more likely to find that the function works rather than motivating them to hunt for bugs. This is more important than some people realize: A positive test is one that finds a bug. Failing to find a bug is a negative result. We are trying to find positive results.
To test your function, think of ways it can fail.
Before you know how a function can fail, you must know what it should do. As you described your function, it “takes pointer to an integer.” You did not say what it does. Judging by the sample code, it sets the int
that the arguments points to to 42. But that is judging by the sample code, which is what we are testing for bugs, not by the specification of the function. You need a complete specification of the function, such as:
- The function
ft_ft
accepts an argument of typeint *
(pointer toint
, not just “pointer to integer) and has return typevoid
. - The argument is required to point to an object. There is no specification for the function’s behavior if the argument is null.
- The function sets the pointed-to
int
to 42 and returns with no other effects.
Now suppose somebody gave you an object module containing this function and no source code. How would you test the function?
To start, for this function, you must pass it an int *
that points to an int
. With some functions, they might be defined to behave in a certain way if passed a null pointer. However, with the specification above, there is no definition for that case, so we do not need to test it.
Then here are some things to test:
- Is the function actually changing the
int
we pass it? Test: Set anint
to zero, pass its address to the function, and test whether its value is not 42 when the function returns. - Does the function add 42 instead of setting the
int
to 42? Test: Set anint
to another value, say 1, pass its address to the function, and test whether its value is not 42 when the function returns. - Does the function actually operate on a whole
int
, not just ashort
orchar
? Test: Set anint
to a value that is different in each byte from theint
containing 42, and test whether its value is not 42 when the function returns. - Does the function work for “edge” cases? Set
int
toINT_MIN
and test whether its value is not 42 when the function returns. TestINT_MAX
. If your C implementation supports trap values forint
, test a trap value. - Does the function change anything else? How about stuff near the
int
it is passed? Test: Embed theint
in an array of otherint
, set them all to zero, call the function, and test whether any part of the array other than theint
changed. Repeat with values other than zero and with each element of the array containing a different value from other elements. - Does the function change anything else in memory, maybe stuff not near the
int
? There is not usually an easy way to test this, but you might examine the object module containing the function to see if it contains references to any external identifiers.