7

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?

ValarDohaeris
  • 6,064
  • 5
  • 31
  • 43
  • possible duplicate of [How can I output the value of an enum class in C++11](http://stackoverflow.com/questions/11421432/how-can-i-output-the-value-of-an-enum-class-in-c11) – Ami Tavory Jun 16 '15 at 06:44

5 Answers5

6

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.

jbcolli2
  • 113
  • 1
  • 4
  • This is the least intrusive option. It is also your only option (well, together with Malveniouses) if you can't / don't want to provide a << operator for the class. – Bim Apr 26 '18 at 07:58
4

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.

3

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.

Shoe
  • 74,840
  • 36
  • 166
  • 272
3

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.

Malvineous
  • 25,144
  • 16
  • 116
  • 151
  • 1
    Also, note that `BOOST_TEST_DONT_PRINT_LOG_VALUE()` can't be embedded in a namespace (at least in Boost 1.63.0). `BOOST_TEST_DONT_PRINT_LOG_VALUE(MyEnumClass) mynamespace { ... }` will work, but `mynamespace { BOOST_TEST_DONT_PRINT_LOG_VALUE(MyEnumClass) ... }` will not. – dbank Jan 15 '20 at 18:28
  • @dbank: Is that because the type in question is not part of the namespace? What if you do something like `BOOST_TEST_DONT_PRINT_LOG_VALUE(::MyEnumClass)`? – Malvineous Jan 15 '20 at 19:48
  • I'm not sure why, but when I put `BOOST_TEST_DONT_PRINT_LOG_VALUE(MyEnumClass)` in a namespace, g++ would give macro expansion errors on `BOOST_TEST_DONT_PRINT_LOG_VALUE` and would cause any boost macros lower in the file to give errors, such as `BOOST_AUTO_TEST_SUITE` and `BOOST_FIXTURE_TEST_CASE`. – dbank Jan 15 '20 at 20:35
  • 1
    Also, in my case, the enum class declaration/definition was in a namespace. – dbank Jan 15 '20 at 20:43
  • Ah I see, doing `mynamespace { BOOST... }` tries to construct a type `mynamespace::boost::test_tools::...` which is where the problem comes from. Not sure if this would be considered a bug or not - you could try asking on the Boost mailing list. – Malvineous Jan 15 '20 at 22:50
1

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);
56ka
  • 1,463
  • 1
  • 21
  • 37