Google Test: How to run fixture only once for multiple tests?
Asked Answered
M

2

12

I am trying to test a http client using gtest. I want to test this client with my own http server. I have a small python server. Test cases would be client sending various requests to this python server. Is there a way to start the server before all tests run and destroy that server after tests?

I am trying to use gtest fixture as shown here; by creating a new process in SetUp and killing it in TearDown. But it looks like the these calls are made for every test.

class Base: public ::testing::Test {
public:
    pid_t child_pid = 0;
    void SetUp() {
        char *cmd = "/usr/bin/python";
        char *arg[] = {cmd, "./http_server.py", NULL};
        child_pid = fork();
        if ( child_pid == 0) {
            execvp(cmd, arg);
            std::cout << "Failed to exec child: " << child_pid << std::endl;
            exit(-1);
        } else if (child_pid < 0) {
            std::cout << "Failed to fork child: " << child_pid << std::endl;
        } else {
            std::cout << "Child HTTP server pid: " << child_pid << std::endl;
        }
    }

    void TearDown() {
        std::cout << "Killing child pid: " << child_pid << std::endl;
        kill(child_pid, SIGKILL);
    }
};

TEST_F(Base, test_1) {
    // http client downloading url
}

TEST_F(Base, test_2) {
    // http client downloading url
}
Mcelroy answered 18/6, 2019 at 23:3 Comment(0)
W
24

If you want to have single connection per test suite (single test fixture), then you can define static methods SetUpTestSuite() and TearDownTestSuite() in your fixture class (documentation)

class Base: public ::testing::Test {
public:
    static void SetUpTestSuite() {
        //code here
    }

    static void TearDownTestSuite() {
        //code here
    }
};

If you'd rather have single instance for all the tests suites, you can use global SetUp and TearDown (documentation)

class MyEnvironment: public ::testing::Environment
{
public:
  virtual ~MyEnvironment() = default;

  // Override this to define how to set up the environment.
  virtual void SetUp() {}

  // Override this to define how to tear down the environment.
  virtual void TearDown() {}
};

Then you need to register the environment of yours in GoogleTest, preferable in main() (before RUN_ALL_TESTS is called):

//don't use std::unique_ptr! GoogleTest takes ownership of the pointer and will clean up
MyEnvironment* env = new MyEnvironment(); 
::testing::AddGlobalTestEnvironment(env);

Note: The code wasn't tested.

Whity answered 19/6, 2019 at 9:29 Comment(0)
P
1

Faced similar issue when testing with a database. For every test execution, the database connection was connected and disconnected. Tests execution took too much time besides the intention of the tests was to check the logic inside a particular function and not to connect/disconnect from database.

So, the approach was changed to create and use mock objects instead of actual objects. Maybe in your case also you can mock the server object and make the mock object return responses to client requests and run asserts on those responses thereby checking that a particular request gets a particular corresponding response. Hence, avoiding to start and stop the actual server for every test execution.

more about google mocks here

Update: If you are using Visual Studio then you can leverage the CppUnitTestFramework which gives facility to execute functions only once at module level(TEST_MODULE_INITIALIZE ) or once at class level(TEST_CLASS_INITIALIZE ) or method level etc. GMock works with Visual Studio CppUnitTestFramework as well.

check here for CppUnitTestFramework

Pitterpatter answered 19/6, 2019 at 4:59 Comment(1)
Note: googlemock page has changed to github.com/google/googletest/blob/master/googlemock/docs/…Denims

© 2022 - 2024 — McMap. All rights reserved.