44

I know how to develop a type-parameterized test and value-parameterized test separately. What I am trying to figure out is if it's possible to combine both. In other words, create a generic test which takes any type and range of values for that type.

linux fanatic
  • 551
  • 1
  • 6
  • 8
  • Why not use a separate template base test fixture class? https://stackoverflow.com/questions/73018270/c-google-type-parameterized-and-value-parameterized-tests-combined – Kok How Teh Jul 20 '22 at 07:12

1 Answers1

36

There isn't any ready-to-wear combination of type-parameterized tests and value-parameterized tests. The googletest developers have been asked the question and they said No.

However, there is a routine and simple way (as suggested by Zhanyong Wan in the linked discussion) in which you can craft you own type-parameterised test case that tests some condition for a specified range of values of the parameter type. Here is an elementary example where the condition is just is greater than 0:

#include <vector>
#include "gtest/gtest.h"

template<class T>
struct foo_test : public ::testing::Test {
    static std::vector<T> _range_;
};

TYPED_TEST_CASE_P(foo_test);

TYPED_TEST_P(foo_test, IsGreaterThanZero) {
    for (TypeParam value : foo_test<TypeParam>::_range_) {
        EXPECT_GT(value,0);
    }
}

REGISTER_TYPED_TEST_CASE_P(foo_test,IsGreaterThanZero);

typedef ::testing::Types<char, int, float> MyTypes;
INSTANTIATE_TYPED_TEST_CASE_P(My, foo_test, MyTypes);

template<> std::vector<char> foo_test<char>::_range_{'1','2','3'};
template<> std::vector<int> foo_test<int>::_range_{1,2,3};
template<> std::vector<float> foo_test<float>::_range_{1.1,2.2,0.0};

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

When compiled and run the output of that is:

[==========] Running 3 tests from 3 test cases.
[----------] Global test environment set-up.
[----------] 1 test from My/foo_test/0, where TypeParam = char
[ RUN      ] My/foo_test/0.IsGreaterThanZero
[       OK ] My/foo_test/0.IsGreaterThanZero (0 ms)
[----------] 1 test from My/foo_test/0 (0 ms total)

[----------] 1 test from My/foo_test/1, where TypeParam = int
[ RUN      ] My/foo_test/1.IsGreaterThanZero
[       OK ] My/foo_test/1.IsGreaterThanZero (0 ms)
[----------] 1 test from My/foo_test/1 (0 ms total)

[----------] 1 test from My/foo_test/2, where TypeParam = float
[ RUN      ] My/foo_test/2.IsGreaterThanZero
/home/imk/develop/SO/gtest/main.cpp:14: Failure
Expected: (value) > (0), actual: 0 vs 0
[  FAILED  ] My/foo_test/2.IsGreaterThanZero, where TypeParam = float (0 ms)
[----------] 1 test from My/foo_test/2 (1 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 3 test cases ran. (1 ms total)
[  PASSED  ] 2 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] My/foo_test/2.IsGreaterThanZero, where TypeParam = float

1 FAILED TEST

The results have coarser granularity than would be ideal: just 3 tests rather than 9. Still, the failing values can be reported, as shown, so the coarse grain may well be tolerable.

KindDragon
  • 6,558
  • 4
  • 47
  • 75
Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
  • 2
    Any idea how to get a Cartesian product of type/value parameters without hard-coding it? – memecs Mar 10 '14 at 13:11
  • 1
    To be quite clear, you want to test each of types `T0,..,Tn` for each of a single set of values `V0,..,Vm` such that a `Ti` is constructible from `Vj` for any `i <= n` and `j <= m`. Is that right? – Mike Kinghan Mar 10 '14 at 16:48
  • Right, not sure what you mean with "Ti constructible from Vj" though. I'll give you an example to be clearer: let's assume I have three types {T1,T2,T3} and two value parameters {V1,V2}, I want to test against the following tuples: {(T1,V1),(T1,V2),(T1,V3),(T2,V1),(T2,V2), etc...}. Point is, I have many parameters and types to test and I can't hard-code all of them. – memecs Mar 10 '14 at 17:11
  • Is there any common type of the Vs? There would have to be even for a value-parameterized test. – Mike Kinghan Mar 10 '14 at 19:02
  • Not really, I am mostly using numerical types such as char,uchar,ushort,short,int,float,double. – memecs Mar 11 '14 at 10:54
  • Righto, this is a different question from the OP's. I think you should post it as your own question with some concrete illustration of the form of test(s) you would want generated for a type `Ti` and type-heterogenous values `V0,...,Vn`. If you think my answer to OP's question is good enough I might come up with a good enough answer to yours; otherwise probably not. – Mike Kinghan Mar 11 '14 at 19:25