如何将矢量与Boost.Test进行比较?

msk*_*her 19 c++ boost unit-testing boost-unit-test-framework

我正在使用Boost Test来测试一些C++代码.

我有一个值的向量,我需要与预期的结果进行比较,但我不想手动检查循环中的值:

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

for( int i = 0; i < size; ++i )
{
    BOOST_CHECK_EQUAL(values[i], expected[i]);
}
Run Code Online (Sandbox Code Playgroud)

主要问题是循环检查不会打印索引,因此需要进行一些搜索才能找到不匹配.

我可以使用std::equalstd::mismatch在两个向量上,但这也需要很多样板.

有更清洁的方法吗?

msk*_*her 32

使用BOOST_CHECK_EQUAL_COLLECTIONS.它是一个宏test_tools.hpp,需要两对迭代器:

BOOST_CHECK_EQUAL_COLLECTIONS(values.begin(), values.end(), 
                              expected.begin(), expected.end());
Run Code Online (Sandbox Code Playgroud)

它将报告索引和不匹配的值.如果大小不匹配,它也会报告(并且不会仅仅在向量的末尾运行).


请注意,如果要使用BOOST_CHECK_EQUALBOOST_CHECK_EQUAL_COLLECTIONS使用非POD类型,则需要实现

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

分别用于比较和记录.
传递的迭代器的顺序BOOST_CHECK_EQUAL_COLLECTIONS决定了!=比较的RHS和LHS - 第一个迭代器范围将是比较中的LHS.

  • 这是在文档中,它只是隐藏得很好 (2认同)

Max*_*kin 12

但是,如果有时需要使用与容差进行比较来比较浮点数的集合,那么这个片段可能是有用的:

// 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); \
    } \
}
Run Code Online (Sandbox Code Playgroud)

这不会打印不匹配元素的数组索引,但它会以高精度打印不匹配的值,因此通常很容易找到它们.

用法示例:

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);
Run Code Online (Sandbox Code Playgroud)


Ste*_*end 10

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 );
}
Run Code Online (Sandbox Code Playgroud)

运行1个测试用例...

test.cpp(11):"test"中的错误:检查{col1,col1 + 7} == {col2,col2 + 7}失败.

位置2:3不匹配!= 4

位置5:6不匹配!= 7

* 1在测试套件中检测到故障"示例"


Tob*_*obi 6

从Boost 1.59开始,比较std::vector实例要容易得多.请参阅此文档以获取版本1.63(在这方面几乎相等于1.59).

例如,如果您已声明std::vector<int> a, b;可以写

BOOST_TEST(a == b);
Run Code Online (Sandbox Code Playgroud)

得到一个非常基本的比较.这样做的缺点是,如果失败,Boost只会告诉你a并且b不一样.但是你可以通过比较元素来获得更多信息,这可能是一种优雅的方式

BOOST_TEST(a == b, boost::test_tools::per_element() );
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要进行字典比较,您可以这样做

BOOST_TEST(a <= b, boost::test_tools::lexicographic() );
Run Code Online (Sandbox Code Playgroud)


leg*_*ize 5

您可以BOOST_REQUIRE_EQUAL_COLLECTIONS与结合使用std::vector<T>,但必须教Boost.Test std::vector当具有向量矢量或值是向量的地图时如何打印。拥有地图时,需要教Boost.Test如何打印std::pair。由于您无法更改std::vector或的定义std::pair,因此必须以这样的方式进行操作,即Boost.Test将使用您定义的流插入运算符,而不会成为的类定义的一部分std::vector。同样,如果您不想仅仅为了使Boost.Test高兴而将流插入运算符添加到被测系统中,则此技术很有用。

这是任何食谱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 << ']';
}

}
Run Code Online (Sandbox Code Playgroud)

这会将[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 << '>';
}

}
Run Code Online (Sandbox Code Playgroud)

BOOST_REQUIRE_EQUAL_COLLECTIONS假设两个集合的大小相同,则会告诉您不匹配项的索引以及两个集合的内容。如果它们的尺寸不同,则认为它们不匹配,并且会打印不同的尺寸。