单元测试(UT,C++版)经验总结(gtest+gmock)

最近做了一段测试工作,其中包括单元测试,编程语言是C++。这里提供一些基本知识总结,方便入门单元测试。

1.单元测试介绍

单元测试(Unit Testing, 简称UT)是软件测试的一种方法,目的是通过对单个软件组件(即单元)的验证,确保其按预期工作。对于C++程序开发者来说,单元测试是一项重要的质量保障手段,能够帮助开发者在代码开发过程中及时发现和修复问题。

单元测试的优点:

  • 提高代码质量:通过自动化的测试,能够有效捕捉到程序中的潜在缺陷。
  • 回归测试:随着代码的不断重构和修改,单元测试能够确保原有功能没有被破坏。
  • 文档化代码:良好的单元测试不仅是验证代码的工具,也充当了文档角色,帮助开发人员更容易理解代码的预期行为。
  • 减少调试时间:因为测试能够尽早发现问题,能够帮助开发者避免在较后阶段出现难以调试的问题。

单元测试的挑战:

  • 测试覆盖率:虽然单元测试能够有效发现许多问题,但并不是每个错误都能被检测到,因此测试覆盖率需要设计得足够高。
  • 维护性:随着项目规模的增大,单元测试本身也可能会变得非常庞大和复杂,维护起来可能会成为一个负担。

2.google test

Google Test(gtest)是由Google开发的一个C++测试框架,用于编写和执行单元测试。它提供了许多功能,使得编写和执行单元测试变得更加简便和高效。gtest支持断言(assertion)、异常捕获、参数化测试等功能。

在项目中使用: 在Cmakelist里通过 find_package(GTest REQUIRED) 来引入Google Test库

头文件:

cpp 复制代码
#include <gtest/gtest.h>

常用断言:

cpp 复制代码
EXPECT_EQ(val1, val2):断言两个值相等。
EXPECT_NE(val1, val2):断言两个值不相等。
EXPECT_TRUE(expression):断言表达式为true。
EXPECT_FALSE(expression):断言表达式为false。
ASSERT_* 和 EXPECT_*:两者的区别在于ASSERT_*失败时会立即终止当前测试用例的执行,而EXPECT_*会继续执行。
 

参数化测试:

gtest支持参数化测试,允许使用不同的参数多次运行同一个测试逻辑。

cpp 复制代码
class MyTest : public ::testing::TestWithParam<int> {};

TEST_P(MyTest, TestWithParam) {
    EXPECT_EQ(GetParam(), 1);  // 断言传入的参数与1相等
}

INSTANTIATE_TEST_SUITE_P(MyTests, MyTest, ::testing::Values(1, 2, 3));

3. goole mock

Google Mock(gmock)是Google推出的一个用于C++的模拟框架,用于为依赖的外部对象创建模拟(Mock)对象。在单元测试中,经常需要模拟外部依赖,以便测试目标函数的行为,而Google Mock正是提供了这种能力。

在项目中使用: 在Cmakelist里通过 find_package(GMock REQUIRED) 来引入Google Test库

头文件:

cpp 复制代码
#include <gmock/gmock.h>

使用gmock时,我们通过模拟对象来替代真实的对象,避免依赖外部系统。以下是gmock的一些基本用法。

  1. 创建 Mock 类 :通过继承testing::Mock,然后模拟所需的成员函数。
cpp 复制代码
class MyClass {
public:
    virtual int Multiply(int a, int b) {
        return a * b;
    }
};

class MockMyClass : public MyClass {
public:
    MOCK_METHOD(int, Multiply, (int a, int b), (override));
};
  • 2. 设置期望 :使用EXPECT_CALL来设置期望,断言模拟对象的方法是否按预期被调用。

cpp 复制代码
TEST(MockTest, MultiplyTest) {
    MockMyClass mock;
    EXPECT_CALL(mock, Multiply(2, 3)).WillOnce(testing::Return(6));  // 设置期望:Multiply(2, 3)返回6
    
    EXPECT_EQ(mock.Multiply(2, 3), 6);  // 断言返回值是否为6
}
  • 3. 模拟行为 :可以通过WillOnceWillRepeatedly指定模拟方法的返回值或行为。

cpp 复制代码
EXPECT_CALL(mock, Multiply(testing::Gt(0), testing::Lt(10)))
    .WillRepeatedly(testing::Return(42));  // 所有大于0且小于10的输入都会返回42
  • 4. 模拟void函数 :对于返回类型为void的函数,使用MOCK_METHOD时,可以通过WillOnce模拟其行为。

    cpp 复制代码
    class MyClass {
    public:
        virtual void DoSomething() {
            // Do something
        }
    };
    
    class MockMyClass : public MyClass {
    public:
        MOCK_METHOD(void, DoSomething, (), (override));
    };
    
    TEST(MockTest, DoSomethingTest) {
        MockMyClass mock;
        EXPECT_CALL(mock, DoSomething()).Times(1);  // 期望DoSomething()被调用一次
        
        mock.DoSomething();  // 调用
    }
  • 5. 验证期望 :gmock会根据EXPECT_CALL的期望来验证实际行为。如果期望的行为未被触发或被触发的次数不正确,gmock会报告错误。

  • 6. 匹配器(Matchers):gmock提供了强大的匹配器,能够对函数参数进行更灵活的验证。例如:

    • testing::Eq(val):匹配相等的值。
    • testing::Gt(val):匹配大于val的值。
    • testing::Lt(val):匹配小于val的值。

进阶使用:

  • 动作链式调用 :通过WillOnceWillRepeatedly可以设置多个返回值。
  • Mock方法的调用顺序 :可以通过InSequence来检查多个期望的调用顺序。
cpp 复制代码
TEST(MockTest, CallOrderTest) {
    MockMyClass mock;
    {
        testing::InSequence seq;  // 保证调用顺序
        EXPECT_CALL(mock, Multiply(2, 3)).WillOnce(testing::Return(6));
        EXPECT_CALL(mock, Multiply(4, 5)).WillOnce(testing::Return(20));
    }
    
    mock.Multiply(2, 3);
    mock.Multiply(4, 5);
}
相关推荐
黄金贼贼1 天前
2026最新java单元测试json校验器
java·单元测试·json
帅次1 天前
从开发到部署:软件实现、测试与交付全流程核心技术解析
功能测试·单元测试·测试用例·集成测试·压力测试·模块测试·安全性测试
叶落无痕524 天前
Electron应用自动化测试实例
前端·javascript·功能测试·测试工具·electron·单元测试
汽车仪器仪表相关领域4 天前
工况模拟精准检测,合规减排赋能行业 ——NHASM-1 型稳态工况法汽车排气检测系统项目实战经验分享
数据库·算法·单元测试·汽车·压力测试·可用性测试
码农水水4 天前
大疆Java面试被问:TCC事务的悬挂、空回滚问题解决方案
java·开发语言·人工智能·面试·职场和发展·单元测试·php
卓码软件测评4 天前
CMA-CNAS软件测评报告机构【Apifox动态Mock响应处理复杂业务逻辑设计】
测试工具·性能优化·单元测试·测试用例
孙琦Ray4 天前
GitHub开源项目日报 · 2026年1月7日 · 本期热门开源全景
单元测试·开源·前端调试·浏览器自动化·知识管理·ai代理·跨语言序列化
程序员三藏4 天前
单元测试详解
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
卓码软件测评5 天前
CMA/CNAS双资质软件测评机构【Apifox高效编写自动化测试用例的技巧和规范】
测试工具·ci/cd·性能优化·单元测试·测试用例
回眸&啤酒鸭5 天前
【回眸】Tessy 单元测试软件使用指南(五)进阶报错之解决指南(含泪整理)
单元测试