我正在使用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_EEQUAL_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):“测试”中的错误:检查{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);

要获得非常基本的比较。不利的一面是,如果失败的话,只有提升才告诉您 ab 不一样。但是,您可以通过比较元素来获得更多信息,而元素可以以优雅的方式进行

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

或者,如果您想进行词典比较,您可能会这样做

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

您可以使用 BOOST_REQUIRE_EQUAL_COLLECTIONSstd::vector<T>, ,但是您必须教boost。测试如何打印 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 << ']';
}

}

这将向量格式化为 [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