HareMQ

GTest


What is GTest

GTest is a cross-platform C++ unit testing framework released by Google. GTest is generated for writing C++ unit tests on different platforms. It provides rich assertions, fatal and non-fatal judgments, parameterization, etc.

GTest functions we need to learn

  1. Simple macro assertion mechanism

  2. Event mechanism (global test, single case test)

Macro Assertions

Assertions in GTest can be divided into two categories:

// Boolean value check
ASSERT_TRUE(res)    // Expects that res is true
ASSERT_FALSE(res)   // Expects that res is false
// Numeric data check
ASSERT_EQ(arg1, arg2) // Returns true if arg1 == arg2
ASSERT_NE(arg1, arg2) // Returns true if arg1 != arg2
ASSERT_LT(arg1, arg2) // Returns true if arg1 < arg2
ASSERT_GT(arg1, arg2) // Returns true if arg1 > arg2
ASSERT_LE(arg1, arg2) // Returns true if arg1 <= arg2
ASSERT_GE(arg1, arg2) // Returns true if arg1 >= arg2
TEST(test1, MYTEST) {

}

All tests must be placed under a unit test. The first parameter of the macro represents the “test suite name” and the second parameter represents the “test name”.

testing::InitGoogleTest(&argc, argv);
RUN_ALL_TESTS();

This is how all tests are initialized and run.

Event mechanism

In a test, there can be multiple test suites (including a set of unit tests)

Test suite: It can be understood as a test environment. The test environment can be initialized before the unit test and cleaned up after the test is completed

Global test suite

#include "../log.hpp"
#include <gtest/gtest.h>
#include <iostream>

class MyEnv : public testing::Environment {
public:
    virtual void SetUp() override {
        LOG(INFO) << "before testing, init ..." << std::endl;
    }
    virtual void TearDown() override {
        LOG(INFO) << "after testing, clearing ..." << std::endl;
    }
};
TEST(MyEnv, test1) {
    LOG(INFO) << "unit test1" << std::endl;
}
TEST(MyEnv, test2) {
    LOG(INFO) << "unit test2" << std::endl;
}
int main(int argc, char** argv) {
    testing::AddGlobalTestEnvironment(new MyEnv);
    testing::InitGoogleTest(&argc, argv);
    auto res = RUN_ALL_TESTS();
    LOG(INFO) << "res: " << res << std::endl;
    return 0;
}

Observe the location of each print message and observe when the global suite is initialized and cleaned up.

Independent test suite

#include "../log.hpp"
#include <gtest/gtest.h>
#include <iostream>
#include <unordered_map>

class MyTest : public testing::Test {
public:
    static void SetUpTestCase() {
        LOG(INFO) << "before each suit test, init ..." << std::endl;
    }
    static void TearDownTestCase() {
        LOG(INFO) << "after each suit test, clearing ..." << std::endl;
    }
    virtual void SetUp() override { }
    virtual void TearDown() override { }
public:
    std::unordered_map<std::string, std::string> __map;
};

TEST_F(MyTest, insert_test) {
    __map.insert({ "hello", "nihao" });
    __map.insert({ "bye", "zaijian" });
}
TEST_F(MyTest, size_test) {
    ASSERT_EQ(__map.size(), 2);
}

int main(int argc, char** argv) {
    testing::InitGoogleTest(&argc, argv);
    auto res = RUN_ALL_TESTS();
    LOG(INFO) << "res: " << res << std::endl;
    return 0;
}

If you run the program now, you will find that the test fails because __map is independent of each test unit. Therefore, the data added in insert_test will not appear in size_test.

If you want to have two data at the beginning, you can use:

    virtual void SetUp() override { }
    virtual void TearDown() override { }

Perform all initialization, that is, public initialization.