Search code examples
globalgoogletestgooglemock

gtest - How to run the same code in the beginning of some functions


I have some functions on my gtest, like below. (don't mind the syntax)

TEST(HotelTest, test1)
{
   MyObj obj;
   int a = obj.doStuff(1);

   EXPECT_EQ(test1, a);
}

TEST(HotelTest, test2)
{
   MyObj obj;
   int a = obj.doStuff(2);

   EXPECT_EQ(test2, a);
}

TEST(HotelTest, test3)
{
   MyObj obj;
   int a = obj.doStuff(3);

   EXPECT_EQ(test3, a);
}

TEST(HotelTest, test4)
{
   MyObj obj;
   int a = obj.doStuff(4);

   EXPECT_EQ(test4, a);
}

As you can see, there is code repeated all over the functions.

QUESTION: Is there any way to avoid this? I mean... Something like an inline function where I could store that repeated code in another place and then just call?

P.S. I really need to have different TEST functions. This example is just to show the problem.

Thanks in advance:)


Solution

  • At the very least, you could use test fixtures.

    This will allow you to avoid duplicating the MyObj obj; line in each case:

    class HotelTest : public ::testing::Test {
     protected:
      MyObj obj;
    };
    
    TEST_F(HotelTest, test1) {
       int a = obj.doStuff(1);
       EXPECT_EQ(test1, a);
    }
    
    TEST_F(HotelTest, test2) {
       int a = obj.doStuff(2);
       EXPECT_EQ(test2, a);
    }
    

    If your calls to obj.doStuff are more involved than a single command, you can wrap these in a function of the fixture too:

    class HotelTest : public ::testing::Test {
     protected:
      int doStuff(int i) { return obj.doStuff(i); }
      MyObj obj;
    };
    
    TEST_F(HotelTest, test1) {
       EXPECT_EQ(test1, doStuff(1));
    }
    
    TEST_F(HotelTest, test2) {
       EXPECT_EQ(test2, doStuff(2));
    }
    

    Finally, you might be able to make use of the more advanced value-parameterised tests. This example would run the test case four times. On the first iteration GetParam() would yield 1, on the second 2 and so on up to 4 as specified by ::testing::Range(1, 5).

    class HotelTest : public ::testing::TestWithParam<int> {
     protected:
      int doStuff(int i) { return obj.doStuff(i); }
      MyObj obj;
    };
    
    TEST_P(HotelTest, test) {
       EXPECT_EQ(testx, doStuff(GetParam()));
    }
    
    INSTANTIATE_TEST_CASE_P(AllHotelTests, HotelTest, ::testing::Range(1, 5));