Используйте классы enum с Boost Test

У меня есть класс перечисления, который я хотел бы использовать в своих модульных тестах:

enum class MyEnumClass
{
    MyEntryA,
    MyEntryB
};

Я хотел бы использовать его следующим образом:

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

Но я получаю эту ошибку, очевидно, потому что тест повышения пытается вывести значение:

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
              ^

Добавление уродливого static_cast «решает» проблему:

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

Но я бы хотел избежать этого для каждого класса enum. Я также хотел бы избежать определения операторов потока << для каждого класса перечисления.

Есть ли более простой способ использовать классы enum с тестом повышения?

Или у других фреймворков модульного тестирования есть лучший способ работы с перечислимыми классами?


person ValarDohaeris    schedule 16.06.2015    source источник
comment
возможный дубликат Как я могу вывести значение класса enum в C++11   -  person Ami Tavory    schedule 16.06.2015


Ответы (5)


Вы можете отключить печать рассматриваемого типа с помощью BOOST_TEST_DONT_PRINT_LOG_VALUE(). Из документов Boost:

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

BOOST_TEST_DONT_PRINT_LOG_VALUE( pair_type )

В этом случае, если вы получите несоответствие, сообщение об ошибке теста сообщит вам об этом, но оно не будет печатать фактические отличающиеся значения.

person Malvineous    schedule 24.11.2015
comment
Также обратите внимание, что BOOST_TEST_DONT_PRINT_LOG_VALUE() нельзя встраивать в пространство имен (по крайней мере, в Boost 1.63.0). BOOST_TEST_DONT_PRINT_LOG_VALUE(MyEnumClass) mynamespace { ... } будет работать, а mynamespace { BOOST_TEST_DONT_PRINT_LOG_VALUE(MyEnumClass) ... } — нет. - person dbank; 15.01.2020
comment
@dbank: Это потому, что рассматриваемый тип не является частью пространства имен? Что, если вы сделаете что-то вроде BOOST_TEST_DONT_PRINT_LOG_VALUE(::MyEnumClass)? - person Malvineous; 15.01.2020
comment
Я не уверен, почему, но когда я помещал BOOST_TEST_DONT_PRINT_LOG_VALUE(MyEnumClass) в пространство имен, g++ выдавал ошибки раскрытия макросов для BOOST_TEST_DONT_PRINT_LOG_VALUE и приводил к тому, что любые макросы boost ниже в файле давали ошибки, такие как BOOST_AUTO_TEST_SUITE и BOOST_FIXTURE_TEST_CASE. - person dbank; 15.01.2020
comment
Кроме того, в моем случае объявление/определение класса enum находилось в пространстве имен. - person dbank; 15.01.2020
comment
А, я вижу, выполнение mynamespace { BOOST... } пытается создать тип mynamespace::boost::test_tools::..., откуда и возникает проблема. Не уверен, будет ли это считаться ошибкой или нет - вы можете попробовать спросить в списке рассылки Boost. - person Malvineous; 16.01.2020

Другое решение — использовать BOOST_CHECK(myEnumValue == MyEnumClass::MyEntryB) вместо BOOST_CHECK_EQUAL. Это работает для меня, я предполагаю, что для простой проверки true/false boost не нужно распечатывать класс перечисления.

person jbcolli2    schedule 19.07.2016
comment
Это наименее навязчивый вариант. Это также ваш единственный вариант (ну, вместе с Malveniouses), если вы не можете/не хотите предоставлять оператор ‹‹ для класса. - person Bim; 26.04.2018

Проблема в том, что Boost.Test должен напечатать значение, если они не равны, и для этого он использует operator<< в потоке.

В этом случае нет более чистого способа, чем просто определить operator<< для std::ostream или static_cast для int, как я вижу.

С другой стороны, такие библиотеки, как Catch, не предъявляют таких требований и, вероятно, используют магию макросов для выполнения Это.

person Shoe    schedule 16.06.2015

Решение:

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

Результаты:

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

Подробности:

  1. Используйте BOOST_TEST() в качестве тестового универсального макроса (Универсальный макрос Assertion Boost Test):

    • BOOST_TEST // or BOOST_TEST_CHECK
    • BOOST_TEST_REQUIRE
    • BOOST_TEST_WARN
  2. Кажется, что перечисления с областью действия (классы перечисления) должны быть добавлены в Ограничения и обходной путь, требующий дополнительной пары квадратных скобок.

person pandreidoru    schedule 01.06.2018

Вот мое решение (так просто)

Добавьте это в начало вашего тестового файла

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

Пример:

CHECK_ENUM_CLASS_EQUAL(a, MyEnumClass::MyEntryA);
person 56ka    schedule 21.01.2019