c++ 单元测试 doctest 笔记
Posted khlbat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ 单元测试 doctest 笔记相关的知识,希望对你有一定的参考价值。
相关资料
github: https://github.com/onqtam/doctest
中文文档: C++单元测试工具——doctest
hello world
源码
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>
int add(int a, int b)
return a + b;
TEST_CASE("test_add")
CHECK(3 == add(1, 2));
测试结果
[laolang@localhost doctest-study]$ ./build/dist/test/cm_test
[doctest] doctest version is "2.4.11"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 1 | 1 passed | 0 failed | 0 skipped
[doctest] assertions: 1 | 1 passed | 0 failed |
[doctest] Status: SUCCESS!
[laolang@localhost doctest-study]$
常规使用方法
按照 doctest
官方建议, 只需要在测试程序主文件添加一个 #define
和 doctest.h
即可, 将测试代码移动到其他文件, 测试代码包含 doctest.h
即可.
注意:
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
只能有一个, 不要重复定义
[laolang@localhost test]$ ls -l
总用量 12
-rw-rw-r--. 1 laolang laolang 1359 6月 21 03:37 CMakeLists.txt
-rw-rw-r--. 1 laolang laolang 72 6月 21 03:50 testmain.cpp
-rw-rw-r--. 1 laolang laolang 128 6月 21 03:51 test_util_calc.cpp
[laolang@localhost test]$ cat testmain.cpp # 测试程序主文件只需要两行代码
1 #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
2 #include <doctest/doctest.h>
[laolang@localhost test]$ cat test_util_calc.cpp # 将测试逻辑放在其他文件
1 #include <doctest/doctest.h>
2
3 int add(int a, int b)
4
5 return a + b;
6
7
8 TEST_CASE("test_add")
9
10 CHECK(3 == add(1, 2));
11
[laolang@localhost test]$
TEST_CASE , SUBCASE 与 TEST_SUITE
简单使用
TEST_CASE
是测试用例, 可以包含多个SUBCASE
TEST_SUITE
也就是测试套件, 可以包含多个TEST_CASE
使用 TEST_SUITE
的好处是资源只需要初始化一次
代码
源码
// calc.h
#ifndef _CM_UTIL_CALC_H_
#define _CM_UTIL_CALC_H_
class Calc
public:
Calc();
~Calc();
Calc(const Calc &) = delete;
Calc &operator=(const Calc &) = delete;
int add(int x, int y);
;
#endif
// calc.cpp
#include <iostream>
#include "cm/util/calc.h"
Calc::Calc()
std::cout << "calc constructor" << std::endl;
Calc::~Calc()
std::cout << "calc destructor" << std::endl;
int Calc::add(int x, int y)
return x + y;
测试代码
#include <iostream>
#include <string>
#include <memory>
#include <fmt/core.h>
#include <doctest/doctest.h>
#include "cm/util/calc.h"
TEST_SUITE("test_calc")
auto calc = std::make_unique<Calc>();
TEST_CASE("test_calc_add_1")
SUBCASE("test_calc_add_1_1")
CHECK(3 == calc->add(1, 2));
SUBCASE("test_calc_add_1_2")
CHECK(3 == calc->add(1, 2));
TEST_CASE("test_calc_add_2")
int expected = 4;
int actual = calc->add(1, 2);
CHECK_MESSAGE(expected == actual, fmt::format("add2 测试失败. 期望:, 实际:", expected, actual));
效果
[laolang@localhost doctest-study]$ ./build/dist/test/cm_test
calc constructor # Calc 构造函数
[doctest] doctest version is "2.4.11"
[doctest] run with "--help" for options
===============================================================================
/home/laolang/code/doctest-study/test/test_util_calc.cpp:26:
TEST SUITE: test_calc
TEST CASE: test_calc_add_2
/home/laolang/code/doctest-study/test/test_util_calc.cpp:30: ERROR: CHECK( expected == actual ) is NOT correct!
values: CHECK( 4 == 3 )
logged: add2 测试失败. 期望:4, 实际:3
===============================================================================
[doctest] test cases: 2 | 1 passed | 1 failed | 0 skipped
[doctest] assertions: 3 | 2 passed | 1 failed |
[doctest] Status: FAILURE!
calc destructor # Calc 析构函数
[laolang@localhost doctest-study]$
装饰器
可以实现一些附加功能, 比如超时测试, 单位为秒
TEST_SUITE("not longer than 500ms" * doctest::timeout(0.5))
TEST_CASE("500ms limit")
// asserts
TEST_CASE("200ms limit" * doctest::timeout(0.2))
// asserts
命令行参数
doctest
带了一个命令行管理, 运行时加上--help
就可以查看所有命令行选项的使用帮助, 这些命令行选项没有多余的, 比较有用的比如
- -ltc: 列出所有的
test case
- -lts: 列出所有的
test suite
- -tc: 根据名称过滤
test case
, 例如 -tc="math" - -ts: 与
-tc
想通, 不过过滤的时test suite
- -tce: 跳过指定
test case
- -tse: 跳过指定
test suite
例如
[laolang@localhost doctest-study]$ ./build/dist/test/cm_test --ltc # 列出所有 test case
calc constructor
[doctest] listing all test case names
===============================================================================
test_calc_add_1
test_calc_add_2
===============================================================================
[doctest] unskipped test cases passing the current filters: 2
calc destructor
[laolang@localhost doctest-study]$ ./build/dist/test/cm_test --lts # 列出所有 test suite
calc constructor
[doctest] listing all test suites
===============================================================================
test_calc
===============================================================================
[doctest] unskipped test cases passing the current filters: 2
[doctest] test suites with unskipped test cases passing the current filters: 1
calc destructor
[laolang@localhost doctest-study]$ ./build/dist/test/cm_test --tc="test_calc_add*" # 执行所有 test_calc_add 开头的 test case
calc constructor
[doctest] doctest version is "2.4.11"
[doctest] run with "--help" for options
===============================================================================
/home/laolang/code/doctest-study/test/test_util_calc.cpp:26:
TEST SUITE: test_calc
TEST CASE: test_calc_add_2
/home/laolang/code/doctest-study/test/test_util_calc.cpp:30: ERROR: CHECK( expected == actual ) is NOT correct!
values: CHECK( 4 == 3 )
logged: add2 测试失败. 期望:4, 实际:3
===============================================================================
[doctest] test cases: 2 | 1 passed | 1 failed | 0 skipped
[doctest] assertions: 3 | 2 passed | 1 failed |
[doctest] Status: FAILURE!
calc destructor
[laolang@localhost doctest-study]$ ./build/dist/test/cm_test --tce="test_calc_add_2" # 不执行 test_calc_add_2
calc constructor
[doctest] doctest version is "2.4.11"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 1 | 1 passed | 0 failed | 1 skipped
[doctest] assertions: 2 | 2 passed | 0 failed |
[doctest] Status: SUCCESS!
calc destructor
[laolang@localhost doctest-study]$
测试报告
doctest
支持三种输出, 分别是 console
, junit
, xml
, 默认值为 console
,可以使用-r
选项设置输出报告格式. 使用 -o
选项输出到文件
例如上面的测试代码使用 test -r=xml -o=result.xml
结果如下
<?xml version="1.0" encoding="UTF-8"?>
<doctest binary="./cm_test" version="2.4.11">
<Options order_by="file" rand_seed="0" first="0" last="4294967295" abort_after="0" subcase_filter_levels="2147483647" case_sensitive="false" no_throw="false" no_skip="false"/>
<TestSuite name="test_calc">
<TestCase name="test_calc_add_1" filename="/home/laolang/code/doctest-study/test/test_util_calc.cpp" line="14">
<SubCase name="test_calc_add_1_1" filename="/home/laolang/code/doctest-study/test/test_util_calc.cpp" line="16">
</SubCase>
<SubCase name="test_calc_add_1_2" filename="/home/laolang/code/doctest-study/test/test_util_calc.cpp" line="20">
</SubCase>
<OverallResultsAsserts successes="2" failures="0" test_case_success="true"/>
</TestCase>
<TestCase name="test_calc_add_2" filename="/home/laolang/code/doctest-study/test/test_util_calc.cpp" line="26">
<Expression success="false" type="CHECK" filename="/home/laolang/code/doctest-study/test/test_util_calc.cpp" line="30">
<Original>
expected == actual
</Original>
<Expanded>
4 == 3
</Expanded>
<Info>
add2 测试失败. 期望:4, 实际:3
</Info>
</Expression>
<OverallResultsAsserts successes="0" failures="1" test_case_success="false"/>
</TestCase>
</TestSuite>
<OverallResultsAsserts successes="2" failures="1"/>
<OverallResultsTestCases successes="1" failures="1" skipped="0"/>
</doctest>
这个输出过滤了 std::cout
等输出, 并且包含了所有必要的信息, 比如test case
的名称, 断言失败的原因, 断言数量等, 可以使用python
+Bootstrap
写一个转换器, 把 xml 文件转换为 html, 比如参考这里的 Extent Reports使用示例
本文来自博客园,作者:laolang2016,转载请注明原文链接:https://www.cnblogs.com/khlbat/p/17495278.html
以上是关于c++ 单元测试 doctest 笔记的主要内容,如果未能解决你的问题,请参考以下文章