Search code examples
c++global-variablesresetfixturesboost-unit-test-framework

C++ Global variables sticking to all boost unit tests once set


I am stuck trying to isolate my test cases in terms of global variables.

In my core.h,

int globalMethod(bool flag);

In my core.cpp,

#include "core.h"
bool globalVar = false;

int globalMethod(bool flag) {
   if(flag)
   {
        globalVar = true;
        return true;
   }
   return false;
}

In my myextns_test.cpp (corresponding to myextns.h),

#include <boost/test/unit_test.hpp>
#include <api/core.h>
#include <myfolder/myextns.h>

BOOST_AUTO_TEST_SUITE(ourextns)
BOOST_AUTO_TEST_SUITE(myextns)

BOOST_AUTO_TEST_CASE(case1)
{
    globalMethod(true);
    bool result = myFirstMethod(); // does not fail because globalVar is true
    BOOST_REQUIRE(result);
}

BOOST_AUTO_TEST_CASE(case2)
{
    someother_api_method(); // internally CHECKS globalVar is true or not and finds true!!
    bool result = mySecondMethod(); // !!succeeds as the method before this succeeded - it should fail
    BOOST_REQUIRE(result); // success
}

BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()

The reason is case1 and case2 gets the pointer to the same globalVar. I am reading into Fixtures but it seems there is nothing I can do since the variable is global and cannot be accessed from outside. Anyone know how to solve this? Thanks


Solution

  • That is indeed the problem with global variables; they make the modules of your code notoriously difficult to separate, with unit tests being the first parts to expose that problem. A global variable is global to the entire program, not just to any particular test (or other software module).

    The two most reasonable solutions I can think of are:

    1 - Introduce a fixture

    Using a test fixture, you can set the global variable to a well-known value before each test runs. I'm not too familiar with how to define such a fixture in Boost, but the gist of it is to write setUp() and tearDown() functions that run before and after each test respectively.

    2 - Eliminate the global variable

    The recommended solution. If you can find a way to avoid the global state, you should do so. That gets rid of this problem entirely, both in your tests and in your production code. There are multiple ways to do this, and which one you go for is an architecture topic more than a programming one - but if in doubt, try moving access to function parameters and return values instead of reading and writing directly in function bodies. That's usually a pretty good first step in figuring out how to get rid of globals.