Модульное тестирование CATCH для C++ сравнивает std::array

Мне нравится использовать catch для моих модульных тестов C++. Моя цель - сравнить std::array а также std::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) с расширением: {?} == {?}

Что я могу сделать, чтобы отобразить фактическое и ожидаемое значение? Мне нравится иметь такой же дисплей в нарушенном REQUIRE условие для std::array что касается std::vector,

Я использую последнюю версию catch (v1.10.0).

3 ответа

Решение

Я проследил проблему вниз по toString метод в заголовке catch. Отсутствует перегрузка для std::array, std::vector уже был создан. Я передам это изменение проекту улова.

// 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() );
}

По сути, это вопрос о том, как тип является строковым, и для этого всегда есть документация.

Сокращенная версия заключается в том, что существует простой алгоритм

  1. Проверка на специализацию Catch::StringMaker для данного типа. Если существует, используйте его.

  2. Проверить operator<< перегрузка для данного типа. Если существует, используйте его.

  3. Используйте "{?}".

До недавнего времени Catch предоставляла специализацию для std::vector из коробки, но не для std::array, так как std::array был частью C++11 и вообще менее использовался. Начиная с версии 2.1.0, Catch вместо этого проверяет, предоставляет ли тип контейнероподобный интерфейс, в частности, отвечает begin(T) а также end(T), Это обеспечивает автоматическую строку для многих различных типов, включая std::vector, std::array, но также статические массивы.

Я не проверял исходный код 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);
}
Другие вопросы по тегам