4

我喜欢在我的 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

REQUIRE(direction == false_direction) 扩展: { 0.1, 0.3, 0.4 } == { 0.1, 0.0, 0.4 }

并且对于std::array

REQUIRE(direction == false_direction) 扩展: {?} == {?}

我该怎么做才能显示实际值和预期值?我喜欢在as for的违反REQUIRE条件下有相同的显示。std::arraystd::vector

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

4

3 回答 3

3

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

精简版是有一个简单的算法

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

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

  3. 利用 ”{?}”。

直到最近,Catch 还为std::vector开箱即用提供了专门化,但没有std::arraystd::array. 从 2.1.0 版开始,Catch 改为检查该类型是否提供了类似容器的接口,具体来说,是响应begin(T)end(T)。这为许多不同类型提供了自动字符串化,包括std::vector,std::array以及静态数组。

于 2018-01-13T21:49:38.583 回答
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);
}
于 2017-10-17T11:19:11.477 回答
1

toString我在 catch 标头中的方法中追踪了问题。它缺少 , 的重载std::arraystd::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() );
}
于 2017-10-17T12:36:05.710 回答