параметризованные тесты типа googletest с неполными шаблонами - PullRequest
0 голосов
/ 20 марта 2020

Предположим, у меня есть тест, который сравнивает два экземпляра класса шаблона:

TEST_F(fooSuite, fooTest) {
    U<A> tA;
    U<B> tB;
    someCheck(tA, tB);
}

Теперь я хочу превратить его в Параметризованный тест типа для обоих U и V потому что они реализуют один и тот же интерфейс:

template <class T>
class U { ... }

template <class T>
class V { ... }

Интуитивно, я хотел бы написать что-то вроде:

template <class TestType>
class fooSuite { };

TYPED_TEST_P(fooSuite, fooTest) {
    TypeParam<A> tA;
    TypeParam<B> tB;
    someCheck(tA, tB);
}

REGISTER_TYPED_TEST_SUITE_P(fooSuite, fooTest);

using TypesToTest = ::testing::Types<U, V>
INSTANTIATE_TYPED_TEST_SUITE_P(fooPrefix, fooSuite, TypesToTest);

Естественно, это не скомпилируется, потому что U и V требуется аргумент шаблона в этом using выражении.

Возможно ли это без серьезного обходного пути создания классов-оберток для обхода?

Ответы [ 2 ]

1 голос
/ 21 марта 2020

Вы можете использовать std::tuple в качестве параметра шаблона вашего тестового прибора, что позволит передавать полные типы.

template <typename Tuple>
class FooSuite : public ::testing::Test
{
public:
    template<typename TA, typename TB>
    void SomeCheck(TA tA, TB tB)
    {
        // Check expectations here
    }
};

TYPED_TEST_SUITE_P(FooSuite);

TYPED_TEST_P(FooSuite, FooTest) {
    using TA = typename std::tuple_element<0, TypeParam>::type;
    using TB = typename std::tuple_element<1, TypeParam>::type;
    TA tA;
    TB tB;
    this->SomeCheck(tA, tB);
}

REGISTER_TYPED_TEST_SUITE_P(FooSuite, FooTest);

using TypesToTest = Types<
    std::tuple<U<A>, U<B>>,
    std::tuple<V<A>, V<B>>
>;

INSTANTIATE_TYPED_TEST_SUITE_P(FooPrefix, FooSuite, TypesToTest);
0 голосов
/ 20 марта 2020

Возможно ли это без серьезного обходного пути создания классов-оберток для обхода?

AFAICS из документов, ответ: нет, вы не можете. Проблема в том, что TestingTypes принимает типы, но вы хотите передать шаблоны. Единственное решение, которое я вижу, - это создать простой тип-обертку, чтобы перенести интересующий шаблон в функцию теста и создать его экземпляр с нужным параметром шаблона.

Отказ от ответственности: я недостаточно знаком с тестом Google, может быть, есть способ, как это сделать.

Однако, в зависимости от того, что именно вы подразумеваете под "основным обходным решением", следующий код иллюстрирует возможный подход, который я думаю, должен работать. Думаю, усилия не так уж и плохи.

template <class T>
class U { };

template <class T>
class V {  };

class A{};
class B{};

template<template<class> typename UorV>
struct TemplateHolder {
    template<class Arg>
    using type = UorV<Arg>;
};

template<class T, class Arg>
using instantiate_t = typename T::template type<Arg>;

// Mimick what I suspect the google testing::Types and TypeParam are. 
template<class... Ts>
struct TestingTypes {};

using types_to_test = TestingTypes<TemplateHolder<U>, TemplateHolder<V>>;



int main( void ) {

    using TypeParam = TemplateHolder<U>;
    using ActualTypeToTestA = instantiate_t<TestingType, A>;
    using ActualTypeToTestB = instantiate_t<TestingType, B>;

    static_assert(std::is_same_v<ActualTypeToTestA, U<A>>);
    static_assert(std::is_same_v<ActualTypeToTestB, U<B>>);
    return 0;
}

Живой код здесь

...