GoogleTest简介

GTest框架谷歌推出的一款C++单元测试框架,基于BSD3协议开源。因为是C++,所以基本上兼容所有系统。

QT项目集成GTest

QT Creator自带的Test集成插件可以快速帮助集成QTest或者GTest,虽然QTest是QT自带的测试框架,但是我还是更喜欢使用纯C++的东西。

新建项目->其他项目->Auto Test Project->配置项目TestCase TestSuit->选择GTest根目录

这就是一个完整可以运行的项目了,运行可以看见测试结果。

需要添加新的测试用例可以通过新建测试用例进行测试

TEST(TestSuit,TestCase){
    // do some test
}

根据自己项目的需求include被测项目header和cpp文件,这样可以将测试代码和要测试的代码一起编译导出。

当然如果被测项目是一个库的话,也是可以使用链接动态库的方式链接,但是这样就无法从单元测试结果获取测试代码覆盖率和分支覆盖率等信息。

如果需要那些信息的话还是建议和单元测试一起编译运行。

配置单元测试项目

需要在pro文件内加入新的编译参数

QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0
LIBS += -lgcov
  • -ftest-coverage:在编译的时候产生.gcno文件,它包含了重建基本块图和相应的块的源码的行号的信息。
  • -fprofile-arcs:在运行编译过的程序的时候,会产生.gcda文件,它包含了弧跳变的次数等信息。

网上一般都是教你如上参数,就可以实现统计代码覆盖率的效果,实际上,新的GCC标准使用了--coverage来组合替代上面两个参数,而且还包含Link的过程出处

所以我们只需要在pro文件内加入LIBS += --coverage就行。

使用gcovr生成覆盖率报告

项目编译完成后还不算完,只生成了.gcno文件,还需要运行一次程序才能生成.gcda文件。

现在就可以使用gcovr生成覆盖率报告了.

Gcovr

Gcovr是一个python编译的工具,是利用gcc组件中的gcov对单个c++文件生成的代码覆盖率结果进行总和输出。

安装Gcovr

pip install gcovr

使用Gcovr

输出格式参数:默认直接输出可以阅读的表格形式

--html: 保存项目汇总结果至html
--html-details: 保存详细单个文件结果
--xml: 生成格式化的Cobertura格式xml结果
--sonarqube: 生成格式化的Sonarqube格式xml结果
--json: 生成混合源文件结构和代码覆盖率的JSON格式报告

顺便介绍几个常用的参数

-o <output>, --output <output>
// 输出信息至目标文件
-r <root>, --root <root>
// 读取文件的根目录
--config <config>
// 读取配置文件,默认读取根目录下的gcovr.cfg
-e <exclude>, --exclude <exclude>
// 排除文件

现在就可以直接使用了,

Example: gcovr -r ../ -f ../src -f ../include -e ../test -e ../test/googletest --html --html-detail -o cov.html

project
    - build
    - src
    - include
    - test
        -googletest
        ....

范例程序就在build文件夹内被编译,和运行所以gcovr读取项目内的src和include目录,test下的单元测试源码和gtest组件不用计算覆盖率,所以直接全部排除掉。最后输出cov.html并且生成详细的覆盖率报告。

到这一步就能看到一个完整的程序报告了 image.png

.gitlab-ci.yml

gitlab ci 是基于docker运行的容器,所以需要一个带qmake的容器。docker hub上已经有很多帮我们提前做好了镜像,并且还有很多qt版本。

比如https://hub.docker.com/r/rabits/qt/就已经做好了5.4-5.14的桌面版(linux)和安卓版本的镜像。

所以我们可以基于其编写一个一个.gitlab-ci.yml文件

image: "rabits/qt:5.14-desktop"
stages:
  - build
  - test

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  
build:
  stage: build
  only:
    - develop
    - master
  artifacts:
    paths:
    - build/
  script:
    - mkdir build
    - cd build
    - qmake ../src/xxx.pro CONFIG+=x86_64 CONFIG+=qtquickcompiler && /usr/bin/make qmake_all
    - make -j$(nproc)
    - make clean
    - mkdir test && cd test
    - qmake ../../test/test.pro CONFIG+=x86_64 CONFIG+=qtquickcompiler && /usr/bin/make qmake_all
    - make -j$(nproc)
    - make clean
    
test:
  stage: test
  only:
    - develop
    - master
  dependencies:
    - build
  script:
    - sudo apt-get update -qq && sudo apt-get -y install python3 python3-pip
    - pip3 install gcovr
    - cd build/test
    - ./test
    - python3 -m gcovr -r ../.. -f ../../src -f ../../include -e ../../test -e ../../test/googletest

我这里提供了一个模版,拥有两个job,对于构建build和测试test场景,script中写入正常的qt项目编译过程

同时因为测试场景需要使用构建好的程序,所以需要使用artifacts参数将编译好的文件上传,在test场景中下载回来再测试

还有需要注意的一个参数就是GIT_SUBMODULE_STRATEGY,默认ci clone项目时是不clone子项目的,所以如果使用了子项目来包含gtest的话就一定得加上GIT_SUBMODULE_STRATEGY: recursiveci才会连同子项目一起clone

设置gitlab读取覆盖率

进入项目设置->CI/CD->General pipelines->Test coverage parsing

可以看到gitlag已经对很多代码覆盖率测试工具写了对应的正则规律,在这里写入gcovr对应的规则^TOTAL.*\s+(\d+\%)$就可以让ci自动读取ci日志并且获取覆盖率。

还能在下面的Pipeline status中获取pipeline的badges