Search code examples
c++c++17googletestparametrized-testing

GTest parametrized test unpack Values arguments from array or similar


Having a simple parametrized test with GTest, like for eg:

class Example :public ::testing::TestWithParam<std::tuple<int, int>> {

};

TEST_P(LeapYearMultipleParametersTests, ChecksIfLeapYear) {
    int a = std::get<0>(GetParam());
    int b = std::get<1>(GetParam());
    ASSERT_EQ(a, b);
}

INSTANTIATE_TEST_CASE_P(
        Ex,
        Example,
        ::testing::Values(
                std::make_tuple(0, 0),
                std::make_tuple(1, 2)
));
                

if I would like to generate the values from an array for e.g:

auto make_values() {
 std::tuple<int, int> res[2];
 res[0] = std::make_tuple(0, 0);
 res[1] = std::make_tuple(1, 2);

 return res;
}

And then using that array to be used as argument in ::testing::Values(...), eg:

INSTANTIATE_TEST_CASE_P(
        Ex,
        Example,
        ::testing::Values(make_values())
));

How could it be done to unpack the array into multiple arguments instead?


EDIT:

I have reach a partial solution defining a template function

template<typename T, std::size_t... I>
    auto values(T* t, std::index_sequence<I...>)
    {
        return ::testing::Values(t[I]...);
    }

And then use it like eg:

values(make_values() /*res*/, std::make_index_sequence<2>{});

but that 2nd parameter,std::make_index_sequence<2>{}, is not really elegant. Anyway that would be possible with another template to feed that 2nd parameter?


Solution

  • Key to your issue is to use ::testing::ValuesIn instead of ::testing::Values. Cause in your case you are passing container and not a bunch of values. Complete answer will looks like this:

    class Example : public ::testing::TestWithParam<std::tuple<int, int>> {
    };
    
    TEST_P(Example, ChecksIfLeapYear)
    {
        int a = std::get<0>(GetParam());
        int b = std::get<1>(GetParam());
        ASSERT_EQ(a, b);
    }
    
    using ValuesContainer = std::vector<std::tuple<int, int>>;
    
    ValuesContainer make_values()
    {
        ValuesContainer res;
        res.emplace_back(0, 0);
        res.emplace_back(1, 2);
    
        return res;
    }
    
    INSTANTIATE_TEST_CASE_P(
        Ex,
        Example,
        ::testing::ValuesIn(make_values())
    );