Search code examples
c++unit-testinggoogletest

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


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
}

Solution

  • 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.