使用gTest

时间:2016-11-22 18:00:16

标签: c++ templates googletest

如果以下3个模板功能:

template <typename T, size_t SIZE>
size_t foo1(array<T, SIZE>& a, size_t start){}

template <typename T, size_t SIZE>
size_t foo2(array<T, SIZE>& a, size_t start){}

template <typename T, size_t SIZE>
size_t foo3(array<T, SIZE>& a, size_t start){}

所有三个对数组a执行相同的操作但具有不同的实现。

现在我想为所有三个功能设置谷歌测试,但没有C'n'P所有测试本身。我读到了“值参数化测试”但我无法在模板函数本身上定义指针。

测试可能如下:

TEST(Foo1, t1) {
    std::array<int, 2> arr = {3,1};
    EXPECT_EQ(1, arr[foo1(arr, 0)]);
}

TEST(Foo2, t1) {
    std::array<int, 2> arr = {3,1};
    EXPECT_EQ(1, arr[foo2(arr, 0)]);
}

TEST(Foo3, t1) {
    std::array<int, 2> arr = {3,1};
    EXPECT_EQ(1, arr[foo3(arr, 0)]);
}

(如何)是否可以设置测试用例并重用所有三个模板函数的测试,而无需将测试包装在自定义函数中(仅限gTest)?

我只想定义一次测试并将使用过的函数“传递”为测试的某种测试参数。

提前致谢: - )

编辑1:

经过长时间的努力,我得到了这个:

template<typename T, size_t SIZE>
using fooFp = size_t (*)(std::array<T, SIZE>&, size_t);

template <typename T, size_t SIZE>
class fooTemplateClass: public ::testing::TestWithParam<fooFp<T, SIZE>> {};

class Tc1 : public fooTemplateClass<int, 1>{};

TEST_P(Tc1 , Fnc) {
    fooFp<int, 1> fnc = GetParam();
    std::array<int, 1> arr = {1};
    EXPECT_EQ(1, arr[fnc(arr, 0)]);
}

INSTANTIATE_TEST_CASE_P(Name, Tc1, ::testing::Values(foo1<int, 1>, foo2<int, 1>, foo3<int, 1>), );

但是,这仍然是不方便的,因为我需要为每个模板组合定义一个类(在本例中为Tc1)。我也不喜欢我需要在INSTANTIATE_TEST_CASE_P中定义所有模板设置。

有没有办法概括这一点,所以我只需要写这样的东西:

TEST_P(fooTemplateClass<int, 1>, Fnc) {
    std::array<int, 1> arr = {1};
    fooFp<int, 1> fnc = GetParam();
    EXPECT_EQ(1, arr[fnc(arr, 0)]);
}

INSTANTIATE_TEST_CASE_P(Name, fooTemplateClass, ::testing::Values(foo1, foo2, foo3), );

我在编译时知道所有模板类型和大小,所以我可以传递它们。但目前我还没有找到如何将模板类传递给TEST_P宏...

1 个答案:

答案 0 :(得分:1)

现在没有gtest手头测试它,但我认为你可以使用一个源自::testing::TestWithParam<std::function<size_t(std::array<T, SIZE>, size_t)>>的测试夹具。这使您可以使用TEST_P宏编写测试,该宏可以调用GetParam()来获取类型std::function<size_t(std::array<T, SIZE>, size_t)>的实例。然后,您可以使用此函数对象来调用您的方法。

但是,由于您的T和SIZE模板参数,您的测试夹具仍然是模板类。这样做的第一个问题是,如果宏参数没有被括号括起,则不能在宏参数中有,。这可以通过编写自己定义typedef并利用可变参数宏的宏来规避。但是,您需要根据模板参数唯一标识每个typedef,以便稍后将其传递给INSTANTIATE_TEST_CASE_P。然而,这需要一些我不具备的高级模板技巧。

以下代码为您提供了一个宏TEST_T,可以如图所示使用

#define CONCAT(a, b) CONCAT_(a,b)
#define CONCAT_(a,b) a ## b
#define ARG(arg1, ...) arg1
#define ARG1(arg, ...) CONCAT(arg, ARG( __VA_ARGS__ ))
#define ARG2(arg, ...) CONCAT(arg, ARG1( __VA_ARGS__ ))
#define ARG3(arg, ...) CONCAT(arg, ARG2( __VA_ARGS__ ))

#define TEST_T(test_case_name, test_name, ...) \
    using CONCAT(test_case_name, ARG2( __VA_ARGS__ )) = test_case_name < __VA_ARGS__ >; \
    TEST_P(CONCAT(test_case_name, ARG2( __VA_ARGS__ )), test_name)

TEST_T(fooTemplateClass, Fnc, int, 1) {
    fooFp<int, 1> fnc = GetParam();
    std::array<int, 1> arr = {1};
    EXPECT_EQ(1, arr[fnc(arr, 0)]);
}

您仍然需要使用

进行实例化
INSTANTIATE_TEST_CASE_P(Name, fooTemplateClassint1, ::testing::Values(foo1<int, 1>, foo2<int, 1>, foo3<int, 1>));

我无法解决这个问题,但也许它可以帮助您找到适合您需求的解决方案。