'Is it possible to initialize the fixture only once and use it in multiple test cases?

Is it possible to have the fixture initialized only once and use it in multiple test cases within the same test suite? In the following example, fixture is constructed and destructed multiple times:

struct F {
    F() : i( 0 ) { BOOST_TEST_MESSAGE( "setup fixture" ); }
    ~F()         { BOOST_TEST_MESSAGE( "teardown fixture" ); }

    int i;
};


BOOST_FIXTURE_TEST_SUITE( s, F )

BOOST_AUTO_TEST_CASE( test_case1 )
{
    BOOST_CHECK( i == 1 );
}

BOOST_AUTO_TEST_CASE( test_case2 )
{
    BOOST_CHECK_EQUAL( i, 0 );
}

BOOST_AUTO_TEST_SUITE_END()

But I want the fixture to be constructed only once as the test suite begins and shared among all the test cases within it. Is it possible? The destructor would be called after exiting the test suite.
I am using Boost Test Framework but have no problem using other frameworks like UnitTest++.



Solution 1:[1]

Each test case is derived from the Test Suite Fixture, which is constructed at the start of each test case and destructed when it completes (in your case both test_case1 & test_case2 are derived from F ). The fixture configures and cleans up the environment for each individual test case.

For unit-testing this is usually the preferred strategy - each test case is stand alone and completely atomic.

In some scenarios (e.g. integration testing ) it might be preferable to acquire an expensive resource once and hold onto it over all test cases. This can be done via a GLOBAL FIXTURE, which is constructed at the start of the test run and destructed when the test exits.

If any test cases require a different setup / configuration of the global resources then a GLOBAL FIXTURE cannot be used and you should re-think your testing strategy so that each test case configures and cleans up its own environment.

Unfortunately test cases do not have direct access to the global test fixture, ergo you will need to provide a mechanism that allows them to access the resource (e.g. via a global variable or singleton).

In the example below MyFixture is a singleton that holds the resource. e.g.

struct MyFixture
{
    static MyFixture*& instance() { static MyFixture* s_inst = 0;
    return s_inst; }

    MyFixture()
    {
        instance() = this;
        x = 10;
        BOOST_TEST_MESSAGE( "setup fixture" );
    }

    ~MyFixture()
    {
        BOOST_TEST_MESSAGE( "teardown fixture" );
    }

    int x;
};

BOOST_GLOBAL_FIXTURE(MyFixture)


BOOST_AUTO_TEST_CASE(TEST_1)
{
    BOOST_CHECK(MyFixture::instance()->x == 10);
    MyFixture::instance()->x = 12;
}
BOOST_AUTO_TEST_CASE(TEST_2)
{
    BOOST_CHECK(MyFixture::instance()->x == 12);
}

Solution 2:[2]

It is possible but it requires you to use BOOST_AUTO_TEST_SUITE together with the boost::unit_test::fixture decorator instead of BOOST_FIXTURE_TEST_SUITE. IT is also worth noting that while this will work you will not be able to access the member variables of F inside your test cases. Tip: Just put them outside the struct instead like I do below with i. See here and here for more information in the boost documentation.

struct F {
F()  { BOOST_TEST_MESSAGE( "setup fixture" ); }
~F() { BOOST_TEST_MESSAGE( "teardown fixture" ); }
};

int i = 0;

BOOST_AUTO_TEST_SUITE( s, *boost::unit_test::fixture<F>())

BOOST_AUTO_TEST_CASE( test_case1 )
{
    BOOST_CHECK( i == 1 );
}

BOOST_AUTO_TEST_CASE( test_case2 )
{
    BOOST_CHECK_EQUAL( i, 0 );
}

BOOST_AUTO_TEST_SUITE_END()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 saeid zamani
Solution 2 Anton Eriksson