【问题标题】:googletest type parameterized tests with incomplete templates带有不完整模板的 googletest 类型参数化测试
【发布时间】:2020-03-20 19:14:09
【问题描述】:

假设我有一个比较模板类的两个实例的测试:

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

我现在想为UV 将其转换为Type-Parameterized Test,因为它们实现了相同的接口:

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);

当然,这无法编译,因为 UV 在此 using 表达式中需要一个模板参数。

如果没有一个主要的解决方法来创建包装类来传递,这是否可能?

【问题讨论】:

  • 你的 U 和 V 不是不完整的类型,它们是模板。我从未使用过类型化测试,但在快速查看文档后,您应该将类​​型注入测试而不是模板。
  • 没错,“不完整的类型”是错误的描述。但是,我不能在没有模板参数的 using 语句中简单地使用 UV 的问题仍然存在。我重新表述了这部分问题。

标签: c++ googletest


【解决方案1】:

您可以使用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);

【讨论】:

    【解决方案2】:

    如果没有一个主要的解决方法来创建包装类来传递,这是否可能?

    文档中的 AFAICS,答案是:不,你不能。问题是 TestingTypes 接受类型,但您想传递模板。我能看到的唯一解决方案是创建一个简单的包装器类型,将感兴趣的模板携带到测试函数中,并使用所需的模板参数将其实例化。

    免责声明:我对谷歌测试不够熟悉,也许有办法做到这一点。

    但是,根据您对“主要解决方法”的确切含义,以下代码说明了一种可能的方法,我认为它应该可行。我认为这种努力还不错。

    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;
    }
    

    Live code here

    【讨论】:

      猜你喜欢
      • 2011-12-14
      • 1970-01-01
      • 2019-01-19
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      相关资源
      最近更新 更多