Testing functions with static variables in C - Stack Overflow

admin2025-04-26  3

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());
}
Share Improve this question asked Jan 15 at 6:27 PatrykLPatrykL 214 bronze badges 2
  • On Linux you could fork the process in two the first thing you do. But the root of the problem is that these are perhaps bad tests for functions containing static variables. You might need a middle layer in between to keep track of the function's expected values. – Lundin Commented Jan 15 at 8:36
  • One option is to split the tests out into separate programs. – Ian Abbott Commented Jan 15 at 13:20
Add a comment  | 

1 Answer 1

Reset to default 2

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);
}
转载请注明原文地址:http://anycun.com/QandA/1745597079a90967.html