如果以下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宏...
答案 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>));
我无法解决这个问题,但也许它可以帮助您找到适合您需求的解决方案。