目录
一、官方文档&代码
二、不同平台导入gtest静态库
Android工程
Linux
三、UT测试 Step by Step
1. 示例入门
2. 断言 EXPECT 与 ASSERT
3. TEST与TEST_F
TEST
TEST_F
4. gmock
Google Test(简称 gtest)是 Google C++ 测试框架,用于编写和运行单元测试、集成测试和功能测试。它是一个功能丰富且易于使用的测试框架,旨在帮助开发人员编写可靠和高效的 C++ 测试代码。
一、官方文档&代码
GoogleTest User’s Guide | GoogleTest
GitHub - google/googletest: GoogleTest - Google Testing and Mocking Framework
二、不同平台导入gtest静态库
Android工程
aosp自带静态库,头文件在标准库中,所以使用很方便。
至少包含下面的库
LOCAL_STATIC_LIBRARIES += \libgtest
使用时直接包含头文件即可
#include <gtest/gtest.h>
Linux
一般自己编译,或直接取编译好的使用
编译方法
# 下载gtest源文件
git clone https://github.com/google/googletest.git# build需要的静态库
# 新建build是为了让编译生成的文件都在这个目录下,整洁
cd googletest/
mkdir build
cd build/
# cmake会根据CMakeLists.txt文件生成Makefile文件
# make生成可执行文件(库)
cmake ..
make
看下生成产物:
对于简单的UT测试程序,只需要libgtest.a这个静态库。
三、UT测试 Step by Step
1. 示例入门
写个测试程序main.cpp
- 需要包含gtest.h头文件
- 不是必须要写main。如果没写main函数,可以引入libgtest_main.a代替,这个也是上节中的编译产物
#include <iostream>
#include <string>#include "gtest/gtest.h"int add(int a, int b)
{return a + b;
}TEST(Fun, AddTest)
{EXPECT_EQ(2, add(1, 1));EXPECT_EQ(0, add(1, -1));
}int main(int argc, char **argv)
{::testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}
编译运行
- 需要连接静态库+头文件
- c++版本要求>=14,依据Supported Platforms | GoogleTest
g++ main.cpp googletest/build/lib/libgtest.a -I googletest/googletest/include/ -o uint_test1 -std=c++14
./uint_test1
执行结果
2. 断言 EXPECT 与 ASSERT
- EXPECT_*:失败继续执行;
- ASSERT_*:失败即终止。
由此可见,通常 EXPECT_* 是首选。
- ASSERT_* 是直接从当前函数返回的,可能会导致一些内存、文件资源没有释放,因此存在内存泄漏的问题。
- EXPECT_*可以继续执行完所有测试用例。
GoogleTest 提供了一系列断言:Assertions Reference | GoogleTest
3. TEST与TEST_F
TEST
TEST(TestSuiteName, TestName) {... test body ...
}
- TestSuiteName 对应测试用例集名称,TestName 是归属的测试用例名称。测试的全名由其包含的测试用例集及其测试名称组成。来自不同测试用例集的测试可以具有相同的名称。
- 这两个名称都必须是有效的 C++ 标识符,并且它们不应包含任何下划线。
TEST_F
如果很多测试都执行一样的操作,那就会用到TEST_F。实际上,这个最常使用,一定要看懂。
TEST_F(TestFixtureName, TestName) {... test body ...
}
Fixture,其语义是固定的设施,而 test fixture 在 GoogleTest 中的作用就是为每个 TEST 都执行一些同样的操作。
TestFixtureName 继承 testing::Test 类,然后根据我们的需要实现下面这两个虚函数:
- virtual void SetUp():在 TEST_F 之前,构造函数之后运行;
- virtual void TearDown():在 TEST_F 之后,析构函数之前运行。
此外 testing::Test 还提供了两个 static 函数:
- static void SetUpTestSuite():在第一个 TEST 之前运行
- static void TearDownTestSuite():在最后一个 TEST 之后运行
全局事件,即继承testing::Environment,需要调用AddGlobalTestEnvironment使能,并实现下面两个虚函数:
- virtual void SetUp():在所有用例之前运行;
- virtual void TearDown():在所有用例之后运行。
举例说明
#include <iostream>
#include <string>#include "gtest/gtest.h"class EnvironmentNew : public ::testing::Environment
{
public:~EnvironmentNew() override {}// Override this to define how to set up the environment.void SetUp() override{std::cout << "Environment SetUp" << std::endl;}// Override this to define how to tear down the environment.void TearDown() override{std::cout << "Environment TearDown" << std::endl;}
};int add(int a, int b)
{return a + b;
}// The fixture for testing class Foo.
class FooTest : public testing::Test
{
protected:// You can remove any or all of the following functions if their bodies would// be empty.FooTest(){// You can do set-up work for each test here.std::cout << "FooTest Constructor" << std::endl;}~FooTest() override{// You can do clean-up work that doesn't throw exceptions here.std::cout << "FooTest Destructor" << std::endl;}// If the constructor and destructor are not enough for setting up// and cleaning up each test, you can define the following methods:void SetUp() override{// Code here will be called immediately after the constructor (right// before each test).std::cout << "FooTest SetUp" << std::endl;}void TearDown() override{// Code here will be called immediately after each test (right// before the destructor).std::cout << "FooTest TearDown" << std::endl;}// Class members declared here can be used by all tests in the test suite// for Foo.static void SetUpTestSuite(){std::cout << "FooTest SetUpTestSuite" << std::endl;}static void TearDownTestSuite(){std::cout << "FooTest TearDownTestSuite" << std::endl;}
};TEST_F(FooTest, AddTest1)
{EXPECT_EQ(2, add(1, 1));
}TEST_F(FooTest, AddTest2)
{EXPECT_EQ(0, add(1, -1));
}TEST_F(FooTest, AddTest3)
{EXPECT_EQ(-2, add(-1, -1));
}int main(int argc, char **argv)
{// AddGlobalTestEnvironment非必须// 可在main外部定义全局变量调用testing::AddGlobalTestEnvironment,保证在RUN_ALL_TESTS前执行// 不需要手动deletetesting::AddGlobalTestEnvironment(new EnvironmentNew());::testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}
编译执行
g++ main1.cpp googletest/build/lib/libgtest.a -I googletest/googletest/include/ -o uint_test1 -std=c++14
执行结果
4. gmock
gmock用来模拟对外部对象的依赖,可以指定模拟对象在测试中应该被调用的次数、调用的顺序以及调用时传入的参数等条件。这有助于确保被测试代码与依赖的交互符合预期,而无需实际依赖于外部资源。
本文暂时不做详细描述,实际工作中用的不算多。提供一些参考资料:
Mocking Reference | GoogleTest
【gmock】Google Mock 入门-CSDN博客