Возможным способом является типизированный тест GoogleTest следующим образом.Обратите внимание, что это решение для C ++ 14 и более, и целочисленные параметры, как ваш пример {0, 1, 10}
.
Подход
Позвольте намопределите следующую структуру Case
:
template<typename T, std::size_t I>
struct Case
{
using type = T;
static constexpr std::size_t size = I;
};
Основная идея тестирования всех комбинаций типов и размеров заключается в использовании этой структуры для определения типов теста, таких как:
#include <gtest/gtest.h>
template <typename T>
class TypedTest : public ::testing::Test {};
using TestTypes = ::testing::Types<Case<int, 0>, Case<int, 1>, Case<int, 10>, Case<MyCustomStruct, 0>, ...>;
TYPED_TEST_CASE(TypedTest, TestTypes);
TYPED_TEST(TypedTest, sort)
{
auto vec = makeRandomVector<TypeParam::type>(TypeParam::size);
...
}
Комбинаторика
Теперь наша проблема заключается в том, как просто построить все комбинации типов и размеров.Я только что ответил почти на тот же вопрос с этой проблемой вчера.В текущем случае все возможные пары {int, MyCustomStruct}
и {0, 1, 10}
помечены одномерными целыми числами 0,1, ..., 5 следующим образом (и подход max66 также возможен):
0 -> (0/3, 0%3) = (0,0) -> std::tuple<int, 0>
1 -> (1/3, 1%3) = (0,1) -> std::tuple<int, 1>
2 -> (2/3, 2%3) = (0,2) -> std::tuple<int, 10>
3 -> (3/3, 3%3) = (1,0) -> std::tuple<MyCustomStruct, 0>
4 -> (4/3, 4%3) = (1,1) -> std::tuple<MyCustomStruct, 1>
5 -> (5/3, 5%3) = (1,2) -> std::tuple<MyCustomStruct, 10>
, где 3
- размер {0, 1, 10}
.Это просто и понятно написать функцию, которая делает все возможные комбинации с этим алгоритмом следующим образом.Например, Combinations<std::tuple<int, MyCustomStruct>, 0, 1, 10>
соответствует типу std::tuple<Case<int,0>, Case<int,1>, Case<int,10>, Case<MyCustomStruct,0>, ...>
:
template<typename TupleType, typename TupleIdx, std::size_t I>
struct make_case
{
static constexpr std::size_t N = std::tuple_size<TupleIdx>::value;
using type = Case<typename std::tuple_element<I/N, TupleType>::type,
std::tuple_element<I%N, TupleIdx >::type::value>;
};
template <typename T1, typename T2, typename Is>
struct make_combinations;
template <typename TupleType, typename TupleIdx, std::size_t... Is>
struct make_combinations<TupleType, TupleIdx, std::index_sequence<Is...>>
{
using tuples = std::tuple<typename make_case<TupleType, TupleIdx, Is>::type...>;
};
template<typename TupleTypes, std::size_t ...Is>
using Combinations = typename make_combinations
<TupleTypes,
std::tuple<std::integral_constant<std::size_t, Is>...>,
std::make_index_sequence<(std::tuple_size<TupleTypes>::value)*(sizeof...(Is))>>
::tuples;
Тестирование
Применение ответов этого post , мы можем разбить этот кортеж Combinations<...>
на список типов, и здесь я применяю простой способ Наваза.Тогда все тесты можно сделать следующим образом:
template<typename T>
struct Test;
template<typename ...T>
struct Test<std::tuple<T...>>
{
using Types = ::testing::Types<T...>;
};
template <typename T>
class TypedTest : public ::testing::Test {};
using TestTypes = Test<Combinations<std::tuple<int, MyCustomStruct>, 0, 1, 10>>::Types;
TYPED_TEST_CASE(TypedTest, TestTypes);
TYPED_TEST(TypedTest, sort)
{
auto vec = makeRandomVector<TypeParam::type>(TypeParam::size);
...
}