Search code examples
c++googletest

C++ and Google Test


I am looking into the Google Test Parameterized Tests. They look really good however, unless i'm missing a trick, I can't see how you use a different set of test data for each test.. I have used an example that I found online which works great but it looks like I would need to create a new class i.e. FooTest1, 2, 3, 4 etc in order to provide a INSTANTIATE_TEST_CASE_P for each one, if I wanted to provide a TEST_P with different params.. I'm thinking that I must be missing something.

class FooTest: public ::testing::TestWithParam < int >{....};

TEST_P(FooTest, DoesBar)
{
    ASSERT_TRUE(foo.DoesBar(GetParam());
}

INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); 

Can anybody confirm whether this can be achieved differently?

Thanks


Solution

  • Unfortunately there is no simple way around that.

    Each INSTANTIATE_TEST_CASE_P instantiates a (parametrized) test fixture (class FooTest: public ::testing::TestWithParam < int >{....}) with the provided range of test values (in the case of INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)) with a the values from 1 to 9 - remember, the end value is not included)

    Each TEST_P defined to use that fixture (e.g. TEST_P(FooTest, DoesBar)) will be executed once for each value in the value range (i.e. GetParam() will return 1 to 9 accross all executions, with "OneToTenRange" as a test prefix ).

    You can add a second INSTANTIATE_TEST_CASE_P for the same test fixture (e.g. INSTANTIATE_TEST_CASE_P(TenToTwentyRange, FooTest, ::testing::Range(10, 20))) which will cause all tests that use the FooTest fixture to execute that range (in this case 10 to 19, with the prefix "TenToTwentyRange") too.

    If you do NOT want a TEST_P to execute a specific range (or use different parameters) you need to create a separate test fixture and instantiate that according to your needs. Flipping the perspective, the test fixture defines the parameters of the test you run (i.e. what GetParam() returns) and ensures that each TEST_P associated with it is executed once for/with each parameter.

    Fortunately you can use the following trick to make things easier for you:

    Create a normal (non-parametrized) test fixture that contains all the setup/teardown. Then derive a bare-bones parametrized test fixture from that and instantiate it via INSTANTIATE_TEST_CASE_P

    #include "gtest/gtest.h"
    
    class BaseTest : public ::testing::Test
    {
      // Do your common stuff here
    };
    
    // FooTest
    class FooTest: public BaseTest, public testing::WithParamInterface<int>
    {
     public:
      FooTest() : BaseTest() {}
    };
    
    TEST_P(FooTest, DoesFoo)
    {
      ASSERT_TRUE(true);
    }
    
    INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
    
    // BarTest
    class BarTest: public BaseTest, public testing::WithParamInterface<int>
    {
     public:
      BarTest() : BaseTest() {}
    };
    
    TEST_P(BarTest, DoesBar)
    {
      ASSERT_TRUE(true);
    }
    
    INSTANTIATE_TEST_SUITE_P(TenToTwentyRange, BarTest, ::testing::Range(10, 20));
    
    
    int main(int argc, char **argv) {
      testing::InitGoogleTest(&argc, argv);
      return RUN_ALL_TESTS();
    }