Вопрос

Я использую тест Boost для модульного тестирования кода C ++.

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

BOOST_REQUIRE_EQUAL(values.size(), expected.size());

for( int i = 0; i < size; ++i )
{
    BOOST_CHECK_EQUAL(values[i], expected[i]);
}

Основная проблема заключается в том, что проверка петли не печатает индекс, поэтому требует некоторого поиска, чтобы найти несоответствие.

Я мог бы использовать std::equal или же std::mismatch На двух векторах, но это также потребует много шаблонов.

Есть ли более чистый способ сделать это?

Это было полезно?

Решение

Использовать BOOST_CHECK_EQUAL_COLLECTIONS. Анкет Это макрос в test_tools.hpp Это занимает две пары итераторов:

BOOST_CHECK_EQUAL_COLLECTIONS(values.begin(), values.end(), 
                              expected.begin(), expected.end());

Он сообщит об индексах и значениях, которые несоответствуют. Если размеры не совпадают, это также сообщит об этом (и не будет просто сбежать с конца вектора).


Обратите внимание, что если вы хотите использовать BOOST_CHECK_EQUAL или же BOOST_CHECK_EQUAL_COLLECTIONS С типами не-POD вам нужно будет реализовать

bool YourType::operator!=(const YourType &rhs)  //  or OtherType
std::ostream &operator<<(std::ostream &os, const YourType &yt)

Для сравнения и ведения журнала соответственно.
Орден итераторов передал BOOST_CHECK_EQUAL_COLLECTIONS определяет, что является RHS и LHS != Сравнение - Первый диапазон итератора будет LHS в сравнениях.

Другие советы

Однако немного не по теме, когда иногда нужно сравнить коллекции чисел с плавающей точкой, используя Сравнение с терпимостью тогда этот фрагмент может быть полезен:

// Have to make it a macro so that it reports exact line numbers when checks fail.
#define CHECK_CLOSE_COLLECTION(aa, bb, tolerance) { \
    using std::distance; \
    using std::begin; \
    using std::end; \
    auto a = begin(aa), ae = end(aa); \
    auto b = begin(bb); \
    BOOST_REQUIRE_EQUAL(distance(a, ae), distance(b, end(bb))); \
    for(; a != ae; ++a, ++b) { \
        BOOST_CHECK_CLOSE(*a, *b, tolerance); \
    } \
}

Это не печатает индексы массива несоответствующих элементов, но он печатает несоответствующие значения с высокой точностью, так что их часто легко найти.

Пример использования:

auto mctr = pad.mctr();
std::cout << "mctr: " << io::as_array(mctr) << '\n';
auto expected_mctr{122.78731602430344,-13.562000155448914};
CHECK_CLOSE_COLLECTION(mctr, expected_mctr, 0.001);

Как насчет Boost_check_equal_collections?

BOOST_AUTO_TEST_CASE( test )
{
    int col1 [] = { 1, 2, 3, 4, 5, 6, 7 };
    int col2 [] = { 1, 2, 4, 4, 5, 7, 7 };

    BOOST_CHECK_EQUAL_COLLECTIONS( col1, col1+7, col2, col2+7 );
}

пример

Запуск 1 тестовый пример ...

test.cpp (11): ошибка в "test": check {col1, col1+7} == {col2, col2+7} не удалось.

Несоответствие в позиции 2: 3! = 4

Несоответствие в позиции 5: 6! = 7

* 1 сбой, обнаруженный в тестовом наборе "Пример"

Поскольку Boost 1.59 гораздо проще сравнить std::vector экземпляры. Видеть эта документация Для версии 1.63 (которая почти равна в этом отношении к 1,59).

Например, если вы объявили std::vector<int> a, b; ты можешь написать

BOOST_TEST(a == b);

Чтобы получить очень простое сравнение. Недостатком этого является то, что в случае сбоя Boost только говорит вам, что a а также b не то же самое. Но вы получаете больше информации, сравнивая элементы, что возможно элегантно

BOOST_TEST(a == b, boost::test_tools::per_element() );

Или если вы хотите лексикографическое сравнение, вы можете сделать

BOOST_TEST(a <= b, boost::test_tools::lexicographic() );

Вы можете использовать BOOST_REQUIRE_EQUAL_COLLECTIONS с std::vector<T>, но вы должны научить Boost.test, как печатать std::vector Когда у вас есть вектор векторов или карта, значения которых являются векторами. Когда у вас есть карта, Boost.test нужно научить, как печатать std::pair. Анкет Поскольку вы не можете изменить определение std::vector или же std::pair, вы должны сделать это таким образом, чтобы оператор вставки потока, который вы определяете std::vector. Анкет Кроме того, этот метод полезен, если вы не хотите добавлять операторов вставки потока в тестируемую систему, чтобы сделать Boost.test Happy.

Вот рецепт для любого std::vector:

namespace boost
{

// teach Boost.Test how to print std::vector
template <typename T>
inline wrap_stringstream&
operator<<(wrap_stringstream& wrapped, std::vector<T> const& item)
{
    wrapped << '[';
    bool first = true;
    for (auto const& element : item) {
        wrapped << (!first ? "," : "") << element;
        first = false;
    }
    return wrapped << ']';
}

}

Это форматирует векторы как [e1,e2,e3,...,eN] для вектора с N элементы и будут работать для любого количества вложенных векторов, например, где элементы вектора также являются векторами.

Вот аналогичный рецепт для std::pair:

namespace boost
{

// teach Boost.Test how to print std::pair
template <typename K, typename V>
inline wrap_stringstream&
operator<<(wrap_stringstream& wrapped, std::pair<const K, V> const& item)
{
    return wrapped << '<' << item.first << ',' << item.second << '>';
}

}

BOOST_REQUIRE_EQUAL_COLLECTIONS Расскажу вам индекс несоответствующих предметов, а также содержимое двух коллекций, предполагая, что две коллекции имеют одинакового размера. Если они имеют разные размеры, то это считается несоответствием, а разные размеры напечатаны.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top