I have a problem performing several scenarios one by one in unit testing. I'm testing a function, where static variables are used and they store states of variables after previous test scenarios. Is it a common problem during testing? An example of simple code below which will shed light on the issue. Of course in the second test, the result fails. I know that the solution could be to create the external variable, which will be passed through a parameter pointer to the function I will have control over this variable and I can set the initial value before starting testing, but in more complex functions where there are many variables is not convenient. Is there any way to run each test as if it were a new process?
// productionCode.c
int productionFunction(void)
{
static int counter;
counter++;
return counter;
}
// prodctionCode.h
int productionFunction(void);
// main.c - test
#include "productionCode.h"
#include "Unity.h"
void test1(void);
void test2(void);
main()
{
RUN_TEST(test1);
RUN_TEST(test2);
}
void test1(void)
{
TEST_ASSERT_EQUAL(1, productionFunction());
TEST_ASSERT_EQUAL(2, productionFunction());
}
void test2(void)
{
TEST_ASSERT_EQUAL(1, productionFunction());
TEST_ASSERT_EQUAL(2, productionFunction());
}
I have a problem performing several scenarios one by one in unit testing. I'm testing a function, where static variables are used and they store states of variables after previous test scenarios. Is it a common problem during testing? An example of simple code below which will shed light on the issue. Of course in the second test, the result fails. I know that the solution could be to create the external variable, which will be passed through a parameter pointer to the function I will have control over this variable and I can set the initial value before starting testing, but in more complex functions where there are many variables is not convenient. Is there any way to run each test as if it were a new process?
// productionCode.c
int productionFunction(void)
{
static int counter;
counter++;
return counter;
}
// prodctionCode.h
int productionFunction(void);
// main.c - test
#include "productionCode.h"
#include "Unity.h"
void test1(void);
void test2(void);
main()
{
RUN_TEST(test1);
RUN_TEST(test2);
}
void test1(void)
{
TEST_ASSERT_EQUAL(1, productionFunction());
TEST_ASSERT_EQUAL(2, productionFunction());
}
void test2(void)
{
TEST_ASSERT_EQUAL(1, productionFunction());
TEST_ASSERT_EQUAL(2, productionFunction());
}
If you don't want to modify the function signature, you can create a global context structure to store the static
variable, like this:
typedef struct Context {
int counter;
} Context;
static Context context = {0};
int productionFunction() {
context.counter++;
return context.counter;
}
Then, for each test, you can save and restore the context using macros:
#define BEGIN_TEST \
{ \
Context _storedContext = context;
#define END_TEST \
context = _storedContext; \
}
void test1() {
BEGIN_TEST
TEST_ASSERT_EQUAL(1, productionFunction());
TEST_ASSERT_EQUAL(2, productionFunction());
END_TEST
}
This approach is similar to CPython's Py_BEGIN_ALLOW_THREADS
and Py_END_ALLOW_THREADS
, so it is reliable.
Alternatively, there is a less elegant solution. If you are on a Linux system, you can use fork()
to create a copy of the current program state. Each test can then be run in a separate process. For example:
int main() {
if (fork() == 0) {
RUN_TEST(test1);
return 0;
}
RUN_TEST(test2);
}