Search code examples
c++unit-testingboost

How to use both BOOST_PARAM_TEST_CASE and BOOST_AUTO_TEST_CASE and avoid referencing all tests from main()?


I am learning to use Boost unit tests and I am seeing lot of conflicting methods to write them. My ideal unit test system does not require referencing individual tests from some root file, and to that end BOOST_AUTO_TEST_CASE seems to exist. So I started like this:

tests_main.cpp

#define BOOST_TEST_MODULE "Root file for all tests"
#include <boost/test/included/unit_test.hpp>

test_simple_thing.cpp

#include <boost/test/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>

using namespace boost::unit_test;

BOOST_AUTO_TEST_SUITE(test_fixed_str)

namespace unit
{
BOOST_AUTO_TEST_CASE(test_add)
{
  BOOST_CHECK_EQUAL(1+1, 2);
}
}

BOOST_AUTO_TEST_SUITE_END()

But I also need parametric tests, and there will be lot of them most likely. I have constexpr std::arrays defined and I will want to test for each entry where it makes sense.

I found this way:

#include <boost/test/included/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>

#include <array>

constexpr std::array numbers{
 2, 4, 6, 8
};

void my_param_test(const int& number)
{
  BOOST_CHECK_EQUAL(number%2, 0);
}

BOOST_AUTO_TEST_SUITE_END()

test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
{

  framework::master_test_suite().add(BOOST_PARAM_TEST_CASE(&my_param_test, std::begin(numbers), std::end(numbers)));
  return 0;
}

Note the difference between test/included/unit_test.hpp and test/unit_test.hpp, the former may only be included in one cpp file.

And so, the above code will cause duplicate linker errors. Even if you remove /included/, init_unit_test_suite is already duplicated by tests_main.cpp. If you remove it, the parametric tests are not tests anymore, just random functions.

So how can I combine these two?

I can't figure how to make this range based test using the first method.


Solution

  • Consider data test cases:

    Live On Coliru

    #define BOOST_TEST_MODULE "Root file for all tests"
    #include <array>
    #include <boost/test/data/test_case.hpp>
    #include <boost/test/included/unit_test.hpp>
    
    BOOST_AUTO_TEST_SUITE(test_fixed_str)
    
    namespace unit {
        BOOST_AUTO_TEST_CASE(test_add) {//
            BOOST_CHECK_EQUAL(1 + 1, 2);
        }
    } // namespace unit
    
    constexpr std::array numbers{2, 4, 6, 8};
    
    BOOST_DATA_TEST_CASE(my_param_test, numbers, number) { //
        BOOST_TEST((number <= 4 && number >= 0));
    }
    
    BOOST_AUTO_TEST_SUITE_END()
    

    Which already does the expected:

    enter image description here