Use enum classes with Boost Test

3k views Asked by At

I have an enum class that I would like to use in my unit tests:

enum class MyEnumClass
{
    MyEntryA,
    MyEntryB
};

I would like to use it as follows:

MyEnumClass myEnumValue = MyEnumClass::MyEntryA;
BOOST_CHECK_EQUAL(myEnumValue, MyEnumClass::MyEntryB);

But I get this error, clearly because boost test is trying to output the value:

include/boost/test/test_tools.hpp:326:14: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
         ostr << t; // by default print the value
              ^

Adding ugly static_cast "solves" the problem:

BOOST_CHECK_EQUAL(static_cast<int>(myEnumValue), static_cast<int>(MyEnumClass::MyEntryB));

But I would like to avoid doing that for every enum class. I would also like to avoid defining << stream operators for every enum class.

Is there a simpler way to use enum classes with boost test?

Or do other unit test frameworks have a better way to deal with enum classes?

5

There are 5 answers

5
Malvineous On BEST ANSWER

You can disable printing of the type in question with BOOST_TEST_DONT_PRINT_LOG_VALUE(). From the Boost docs:

typedef std::pair<int,float> pair_type;

BOOST_TEST_DONT_PRINT_LOG_VALUE( pair_type )

In this case should you get a mismatch, the test error message will tell you, but it but won't print the actual differing values.

0
Shoe On

The problem is that Boost.Test has to print the value in case they are not equal, and it uses operator<< on a stream to do that.

In this case there's no cleaner way than to simply define operator<< on an std::ostream or to static_cast to an int, that I can see.

On the other hand, libraries like Catch do not have that requirements, and they probably use some macro magic to accomplish it.

0
pandreidoru On

Solution:

enum class MyEnumClass {
  MyEntryA,
  MyEntryB
};

MyEnumClass myEnumValue = MyEnumClass::MyEntryA;
BOOST_TEST((myEnumValue == MyEnumClass::MyEntryA)); // Note extra pair of brackets
BOOST_TEST((myEnumValue == MyEnumClass::MyEntryB)); // Note extra pair of brackets

Results:

info: check (myEnumValue == MyEnumClass::MyEntryA) has passed
error: in "Suite/Test": check (myEnumValue == MyEnumClass::MyEntryB) has failed

Details:

  1. Use BOOST_TEST() as a test universal macro (Assertion Boost Test Universal Macro):

    • BOOST_TEST // or BOOST_TEST_CHECK
    • BOOST_TEST_REQUIRE
    • BOOST_TEST_WARN
  2. It seems that scoped enums (enum classes) should be added to Limitations and workaround that needs an extra pair of brackets.

0
56ka On

Here is my solution (so simple)

Add this at the top of your test file

#define CHECK_ENUM_CLASS_EQUAL(L, R) BOOST_CHECK_EQUAL(static_cast<int>(L), static_cast<int>(R))

Example:

CHECK_ENUM_CLASS_EQUAL(a, MyEnumClass::MyEntryA);
1
jbcolli2 On

Another solution is to use BOOST_CHECK(myEnumValue == MyEnumClass::MyEntryB), instead of BOOST_CHECK_EQUAL. This works for me, I'm assuming that for a simple true/false check, boost doesn't need to print out the enum class.