gtest 单元测试

前言

Google Test(简称gtest)是一个开源的C++单元测试框架。和常见的测试工具一样,gtest提供了单体测试常见的工具和组件。比如判断各种类型的值相等,大于,小于等,管理多个测试的测试组如testsuit下辖testcase,为了方便处理初始化数据减少重复代码,提供了setup和teardown函数等。

一、Google Test介绍

1.1 gtest源码下载编译

git clone https://github.com/google/googletest.git
cd googletest
mkdir build && cd build && cmake .. && make -j4
sudo make install
sudo ldconfig

googletest/samples文件夹中里面存放了10个官方提供的示例代码,默认是不编译的,这里我们修改googletest/CMakeLists.txt,将第20行的OFF改为ON。

option(gtest_build_tests "Build all of gtest's own tests." OFF)

option(gtest_build_samples "Build gtest's sample programs." ON)

option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)

重新构建后,可以在build目录下看到googletest自带的sample都编译为了可执行文件。

root@localhost:~/gtest/build/googletest# ls
CMakeFiles           Makefile             generated          sample1_unittest  sample3_unittest  sample5_unittest  sample7_unittest  sample9_unittest
CTestTestfile.cmake  cmake_install.cmake  sample10_unittest  sample2_unittest  sample4_unittest  sample6_unittest  sample8_unittest

root@localhost:~/gtest/build/googletest# ./sample1_unittest
Running main() from /root/gtest/googletest/src/gtest_main.cc
[==========] Running 6 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 3 tests from FactorialTest
[ RUN      ] FactorialTest.Negative
[       OK ] FactorialTest.Negative (0 ms)
[ RUN      ] FactorialTest.Zero
[       OK ] FactorialTest.Zero (0 ms)
[ RUN      ] FactorialTest.Positive
[       OK ] FactorialTest.Positive (0 ms)
[----------] 3 tests from FactorialTest (0 ms total)

[----------] 3 tests from IsPrimeTest
[ RUN      ] IsPrimeTest.Negative
[       OK ] IsPrimeTest.Negative (0 ms)
[ RUN      ] IsPrimeTest.Trivial
[       OK ] IsPrimeTest.Trivial (0 ms)
[ RUN      ] IsPrimeTest.Positive
[       OK ] IsPrimeTest.Positive (0 ms)
[----------] 3 tests from IsPrimeTest (0 ms total)

[----------] Global test environment tear-down
[==========] 6 tests from 2 test suites ran. (0 ms total)
[  PASSED  ] 6 tests.

在googletest的说明手册中,给出了示例代码更详细的解释:Googletest Samples

1.2 gtest运行参数介绍

  1. 命令行参数:–gtest_output=“xml:report.xml”,可以把控制台内容输出转储为 XML 格式,其中report为存储的文件名,e.g.
./unittest --gtest_output="xml:report.xml"
  1. 命令行参数:–gtest_repeat=n,表示进行n次的重复测试,某些测试进行多次尝试后可能会结果不一致,可以使用重复测试功能进行测试;参数–gtest_break_on_failure可以支持自动调试,运行测试有时候会失败,但是在大多数时候会顺利通过。这是与内存损坏相关的问题的典型特点。如果多次运行测试,就能够提高发现失败的可能性,e.g.
./unittest --gtest_repeat=2 --gtest_break_on_failure

表示重复运行相同的测试用例两次,如果测试失败,会自动调用调试器。

  1. 命令行参数:运用–gtest_filter来过滤case。有时候我们并不需要运行所有测试,尤其是在修改的代码只影响某几个模块的情况下。为了支持运行一部分测试,Google 提供 --gtest_filter=,e.g.
./unittest --gtest_filter=* #执行所有测试
./unittest --gtest_filter=PoissonUdpClientTest* #执行PoissonUdpClientTest开头的测试
./unittest --gtest_filter=-PoissonUdpClientTest* #不执行PoissonUdpClientTest开头的测试

二、Google Mock

gmock是谷歌推出的开源白盒测试工具,用于编写C++模拟类的框架。通过gmock可以用一些简单的宏描述想要模拟的接口并指定其期望,在测试中有效地去除外部依赖,更方便地测试模块功能。
对类里面需要打桩的函数mock,语法如下:

MOCK_METHODn(..., ...); //其中n表示参数的个数
MOCK_CONST_METHODn(..., ...); //const成员方法用这种

对mock的方法可以指定期望,包括返回值,调用次数等,使用EXPECT_CALL()宏:

EXPECT_CALL(mock_object, method(matchers))
    .Times(cardinality) //可以指定调用几次
    .WillOnce(action) //可以指定调用行为
    .WillRepeatedly(action);

Matchers指参数匹配器,可以指定任意参数,::testing::_ 表示输入的参数为任意参数,其他参数不一一列举

Mock virtual方法如下,不需要对工程代码做修改:

// Foo.h
class Foo {
   
public:
    virtual int FooFuncOne(int num);
};

// FooTest.cc
class MockFoo : public Foo {
   
public:
    MOCK_METHOD1(FooFuncOne, int(int num));
};

TEST(FooTest, FooFuncOne)
{
   
    MockFoo mockFoo;
    // 指定FooFuncOne返回值为5
    EXPECT_CALL(mockFoo, FooFuncOne((::testing::_)))
        .WillRepeatedly((::testing::Return)(5));
}

上面mock方法主要用到了虚函数重写,但是对于非虚函数,上述写法是不能够生效的,需要有较大的改动,可以根据实际需要选择。下面贴了使用的示例:

// foo.h
class Foo {
   
public:
    void CallSelfMethod();
    void PublicMethod();
protected:
    void ProtectedMethod();
private:
    void PrivateMethod();
};

// 重构成模板类 foo_testable.h
template <typename T>
class FooTestable {
   
public:
    FooTestable(T &self);
    void CallSelfMethod();
    void PublicMethod();
protected:
    void ProtectedMethod();
private:
    void PrivateMethod();
    T &self;
};

// foo_test.cc
class MockFoo {
   
public:
    MOCK_METHOD(PublicMethod, void());
    MOCK_METHOD(ProtectedMethod, void());
    MOCK_METHOD(PrivateMethod, void());
};
TEST(Test_MockSelfNonVirtualMethod, SelfMethod) {
   
    MockFoo mockFoo;
    FooTestable<MockFoo> fooTestable(mockFoo);
    EXPECT_CALL(mockFoo, PublicMethod()).Times(1);
    EXPECT_CALL(mockFoo, ProtectedMethod()).Times(1);
    EXPECT_CALL(mockFoo, PrivateMethod()).Times(1);
    fooTestable.CallSelfMethod();
}

参考资料

  1. 转一篇小亮同学的google mock分享
  2. https://github.com/google/googletest
  3. 【CMake 系列】(四)用 GoogleTest 测试 #136
  4. Golang 中的测试 #95
  5. Linux项目搭建Gtest/Gmock框架总结

相关推荐

  1. gtest 单元测试

    2024-01-24 08:34:02       56 阅读
  2. 【C++】Google Test(gtest单元测试

    2024-01-24 08:34:02       26 阅读
  3. 【C++】使用gtest单元测试框架写单元测试

    2024-01-24 08:34:02       23 阅读
  4. 软件测试:C++ Google Test单元测试框架GTest

    2024-01-24 08:34:02       43 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-24 08:34:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-24 08:34:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-24 08:34:02       82 阅读
  4. Python语言-面向对象

    2024-01-24 08:34:02       91 阅读

热门阅读

  1. 汇编(1)

    2024-01-24 08:34:02       55 阅读
  2. OC-NSNumber

    2024-01-24 08:34:02       53 阅读
  3. opencv中的几个重要函数

    2024-01-24 08:34:02       56 阅读
  4. TensorFlow

    2024-01-24 08:34:02       62 阅读
  5. yolov8 训练voc数据集

    2024-01-24 08:34:02       54 阅读
  6. RabbitMQ

    RabbitMQ

    2024-01-24 08:34:02      55 阅读
  7. 关于C# 使用 sqlite 映射实体类笔记

    2024-01-24 08:34:02       51 阅读