【问题标题】:CATCH unit testing for C++ compare std::arrayC++ 的 CATCH 单元测试比较 std::array
【发布时间】:2018-03-29 01:28:10
【问题描述】:

我喜欢在我的 C++ 单元测试中使用catch。 我的目标是比较std::arraystd::vector。我创建了这个失败的例子。

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("Vector") {
    std::vector<double> direction = {0.1, 0.3, 0.4};
    std::vector<double> false_direction = {0.1, 0.0, 0.4};
    REQUIRE(direction == false_direction);
}

TEST_CASE("Array") {
    std::array<double, 3> direction = {0.1, 0.3, 0.4};
    std::array<double, 3> false_direction = {0.1, 0.0, 0.4};
    REQUIRE(direction == false_direction);
}

这个测试的输出是为了检查std::vector

要求(方向 == false_direction) 扩展: { 0.1, 0.3, 0.4 } == { 0.1, 0.0, 0.4 }

对于std::array

要求(方向 == false_direction) 扩展: {?} == {?}

如何显示实际值和预期值?我喜欢在 std::array 的违反 REQUIRE 条件下显示与 std::vector 相同的显示。

我使用的是最新版本的 catch (v1.10.0)。

【问题讨论】:

    标签: c++ unit-testing stdvector stdarray catch-unit-test


    【解决方案1】:

    我没有检查 Catch 的源代码以了解他们如何准确地实现 REQUIRE 子句,以及为什么它不起作用但 vector 可以。 但这里有一个解决方法:

    #define COMPARE_ARRAYS(lhs, rhs) compareArrays(Catch::getResultCapture().getCurrentTestName(), __LINE__, lhs, rhs)
    
    template < typename T, size_t N >
    void compareArrays(const std::string & test, unsigned line, std::array<T, N> lhs, std::array<T, N> rhs) {
      std::vector<T> lv(lhs.begin(), lhs.end());
      std::vector<T> rv(rhs.begin(), rhs.end());
      INFO("Test case [" << test << "] failed at line " << line); // Reported only if REQUIRE fails
      REQUIRE(lv == rv);
    }
    
    TEST_CASE("Array") {
        std::array<double, 3> direction = {0.1, 0.3, 0.4};
    
        std::array<double, 3> true_direction = {0.1, 0.3, 0.4};
        COMPARE_ARRAYS(direction, true_direction);
    
        std::array<double, 3> false_direction = {0.1, 0.0, 0.4};
        COMPARE_ARRAYS(direction, false_direction);
    }
    

    【讨论】:

    • 这肯定行得通,但会降低测试代码的可读性。
    • @schorsch312,改进后的解决方案更加简洁、可重复使用且不会影响测试输出信息
    【解决方案2】:

    我在 catch 标头中的 toString 方法中追踪了问题。它缺少std::array 的重载,std::vector 已经被实例化。我会将这个更改提交给 catch 项目。

    // already exists in the catch header
    template<typename T, typename Allocator>
    std::string toString( std::vector<T,Allocator> const& v ) {
        return Detail::rangeToString( v.begin(), v.end() );
    }
    
    // my modification in the catch header
    template<typename T, std::size_t _Nm>
    std::string toString( std::array<T, _Nm> const& v ) {
        return Detail::rangeToString( v.begin(), v.end() );
    }
    

    【讨论】:

      【解决方案3】:

      从根本上说,这是一个类型如何被字符串化的问题,为此总是有documentation

      精简版是有个简单的算法

      1. 检查给定类型的Catch::StringMaker 的特化。如果存在,请使用它。

      2. 检查给定类型的operator&lt;&lt; 过载。如果存在,请使用它。

      3. 使用“{?}”。

      直到最近,Catch 还为 std::vector 提供了开箱即用的特化,但不是为 std::array 提供的,因为 std::array 是 C++11 的一部分并且通常较少使用。 Since version 2.1.0 Catch 而是检查该类型是否提供类似容器的接口,具体来说,响应 begin(T)end(T)。这为许多不同类型提供了自动字符串化,包括std::vectorstd::array,还有静态数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-19
        • 2014-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-13
        相关资源
        最近更新 更多