Reputation: 11
I want to test a template function on a range of values and a range of types. So something like
template <class T>
void foo(Bar<T>&);
But the issue is I can't get the google test's value parametrised tests to work with template test suite. Most of my tests currently look like this:
TYPED_TEST(FooTest, foo) {
for (int repeats = 0 ...) { // don't want this
Bar<TypeParam> bar;
for (... i < repeats ...)
foo(bar);
EXPECT_EQ(bar, /*...*/);
}
}
So I am looking for a way to get rid of that first for loop and pass repeats
as a const parameter instead. And just in case you are wondering here is the real test file. Although its not entirely this way right now because I am refactoring this code.
I have tried this so far:
using NumericTypes = ::testing::Types<uint8_t /*...*/ >;
template <class T>
class FooTest
: public ::testing::TestWithParam<const int> { };
TYPED_TEST_SUITE(FooTest,
NumericTypes,
TestingTypenames);
INSTANTIATE_TEST_SUITE_P(SomeFooTest,
FooTest,
testing::Range(0,3));
The error I am getting:
foo.cpp: error: template argument 1 is invalid
16 | INSTANTIATE_TEST_SUITE_P(SomeFooTest,
| ^~~~~~~~~~~~~~~~~~~~~~~~
So these type parametrized tests are making wonders for me its just the for loops that are bothering me. And in the new tests I am writing there would be 3 layers of for loops because I am testing nested lists and they will behave differently if they are nested.
Upvotes: 1
Views: 1583
Reputation: 7184
If you can, it is much easier either to pass your values as template arguments or to pass your types as values.
An example with values as template arguments:
#include <variant>
#include <gtest/gtest.h>
template<typename T, T value>
struct param1 {
static T get(){ return value; }
};
template <typename >
class example1
: public ::testing::Test { };
using params = ::testing::Types<
param1<uint8_t, 0>,
param1<uint8_t, 1>,
param1<uint16_t, 0>
>;
TYPED_TEST_SUITE(example1, params);
TYPED_TEST(example1, test) {
ASSERT_TRUE(TypeParam::get() < 2);
}
And with types as values:
using param2 = std::variant<uint8_t, uint16_t>;
class example2 : public ::testing::TestWithParam<param2> {};
INSTANTIATE_TEST_SUITE_P(foo, example2, testing::Values<param2>(
uint8_t(0),
uint8_t(1),
uint16_t(0)
));
TEST_P(example2, test) {
std::visit([&](auto value){
ASSERT_TRUE(value < 2);
}, GetParam());
}
Upvotes: 1