代码之家  ›  专栏  ›  技术社区  ›  mskfisher KeithS

如何比较矢量和增强。测试?

  •  18
  • mskfisher KeithS  · 技术社区  · 15 年前

    我用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 在这两个向量上,但这也需要很多样板文件。

    有更干净的方法吗?

    5 回复  |  直到 8 年前
        1
  •  31
  •   mskfisher KeithS    15 年前

    使用 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_系列 对于非pod类型,您需要实现

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

    分别用于比较和记录。
    传递给的迭代器的顺序 Boost_Check_Equal_系列 确定哪个是 != 比较-第一个迭代器范围将是比较中的lhs。

        2
  •  12
  •   Maxim Egorushkin    12 年前

    然而,当有时需要使用 comparison with tolerance 那么这个代码段可能有用:

    // 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);
    
        3
  •  10
  •   Steve Townsend    15 年前

    怎么样 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”中的错误:检查col1,col1+7=col2,col2+7失败。

    位置2:3不匹配!= 4

    位置不匹配5:6!= 7

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

        4
  •  5
  •   legalize    11 年前

    你可以用 BOOST_REQUIRE_EQUAL_COLLECTIONS 具有 std::vector<T> 但是你必须教Boost。测试如何打印 std::vector 当你有一个向量向量向量或者一个值为向量的地图时。当你有一张地图的时候,加强。测试需要学会如何打印。 std::pair . 因为你不能改变 STD::载体 STD::配对 ,您必须这样做,您定义的流插入运算符将由boost.test使用,而不作为类定义的一部分 STD::载体 . 另外,如果您不想在被测系统中添加流插入操作符来提高性能,这种技术也很有用。

    这是任何 STD::载体 :

    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::配对 :

    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 << '>';
    }
    
    }
    

    增加\需要\相同的\收藏 将告诉您不匹配项的索引,以及两个集合的内容,前提是这两个集合的大小相同。如果它们的尺寸不同,则视为不匹配,并打印不同的尺寸。

        5
  •  5
  •   TobiMcNamobi    8 年前

    因为Boost 1.59,所以比较起来容易得多。 std::vector 实例。见 this documentation 对于版本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() );