Execute one test case several times with different fixture each time
Asked Answered
K

1

17

I have a test case that I want to execute for different states of database. I insert objects to DB in fixture (and I'd like to keep it that way). I want to make method for initialization of DB virtual and specialize fixture for different configurations in DB.

One way I can think of is to do something like:

void doTest(){
    //test code here
}

BOOST_FIXTURE_TEST_CASE(test1, fixture1)
{
    doTest();
}

BOOST_FIXTURE_TEST_CASE(test2, fixture2)
{
    doTest();
}

BOOST_FIXTURE_TEST_CASE(test3, fixture3)
{
    doTest();
}

But is there a cleaner, neater way? Or maybe I shouldn't do this altogether? I will appreciate any advice from testing experts.

Killarney answered 27/2, 2014 at 10:9 Comment(4)
Are you trying to create test scripts for .cpp file? I would create a scriptYorktown
If you use Google Test instead of boost test, you can use the "TestWithParam" and "INSTANTIATE_TEST_CASE_P" to instantiate/run a test multiple times with different values: code.google.com/p/googletest/wiki/…Finnougrian
@KRUKUSA Sadly I cannot use scripts here (these will be automatically executed)Killarney
@MichaelAaronSafyan Thanks, seems good, but I have to use boost test framework.Killarney
R
23

You can use BOOST_FIXTURE_TEST_CASE_TEMPLATE to instantiate multiple tests:

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE TestModuleName
#include <boost/test/unit_test.hpp>
#include <boost/mpl/vector.hpp>

struct Fixture1 { int i; Fixture1() : i(1) {} };
struct Fixture2 { int i; Fixture2() : i(2) {} };
struct Fixture3 { int i; Fixture3() : i(3) {} };

typedef boost::mpl::vector<Fixture1, Fixture2, Fixture3> Fixtures;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(Test, T, Fixtures, T){
    std::cout << T::i << "\n";
}

Will print

1
2
3

This code instantiates an own test case for each type in the mpl::vector 'Fixtures'. Each Fixture type will be passed in as T (second parameter of BOOST_FIXTURE_TEST_CASE_TEMPLATE) and T will be used as fixture for the test case (last parameter).

Caveat

Because of the template nature of the test case (class) you need to prepend T:: to access the fixtures members to indicate that they are (template parameter) dependent names.

Improvement

Because BOOST_FIXTURE_TEST_CASE_TEMPLATE is so generic, one might want to define a handy "shortcut" which is more explicit about what is being done:

#define MULTI_FIXTURE_TEST_CASE(NAME, TPARAM, ...) \
        typedef boost::mpl::vector<__VA_ARGS__> NAME##_fixtures; \
        BOOST_FIXTURE_TEST_CASE_TEMPLATE(NAME, TPARAM, NAME##_fixtures, TPARAM)

MULTI_FIXTURE_TEST_CASE(Test, T, Fixture1, Fixture2, Fixture3){
    std::cout << T::i << "\n";
}

As you can see it somewhat hides the mpl::vector. I think it would be best to define this macro in its own header which also does #include <boost/mpl/vector.hpp> to avoid missing the dependency. The fixtures list name is the name of the test case plus '_fixtures' so it should hopefully not clash with existing names and be somewhat meaningful.

Responsory answered 27/2, 2014 at 10:27 Comment(1)
@Dino: I added another convenience macro which makes the interface nicer :)Responsory

© 2022 - 2024 — McMap. All rights reserved.