C++工程实践必备:测试、基准测试、覆盖测试、性能分析、内存泄漏检测
这篇文章是 C++ 工程实践工具链的系统性清单,串联了单元测试、基准测试、覆盖率、Sanitizer 与性能剖析五条主线。测试与断言:从框架选型到可维护用法对比了 googletest、catch2、doctest 的集成与编译体验,重点推荐 doctest 的轻量与易用。详细梳理了 TEST_CASE、SUBCASE…
单元测试框架 google test是一个C++中常用且历史悠久的测试框架,其他类似且较新的测试框架有 catch2 或 doetest等,这两个测试框架的优势在于引入简单,是完全 head only 的,但是也正是因为 head only 导致编译速度很慢,当然 doctest 还是挺快的,但 catch2 真的编译太慢了。而 googletest 引入就需要我们自行编译了,当然用cmake的话是可以简化这个过程的,gtest 的使用和引入其实也很简单,由于是直接链接编译好的库,所以编译速度是比较快的(最近测试了下,同样以链接库的方式比 doctest 慢一些... )。我现在更推荐使用 doctest 而不是 gtest 了。 本来是想讲 Google test 的使用的(看我开篇就知道),但是使用了 doctest 后,我现在完全放弃了 Googletest,对我而言有以下几点非常好:文件轻量,非常轻量,就几个文件,而且代码量好像就7000行,编译速度奇快,而相对的 Googletest 里包含的东西有点多,比如 gmock,对比起来略显重量级。CLion 对 doctest 的支持更好,每次我用 Googletest 的时候,CLion都需要重新我当前使用的测试框架,而使用doctest后,则完全没有这方面困扰,反应奇快,这也是轻量带来的好处。api超级友好,用过就真的回不去。虽然断言宏不是很多,但核心观点是它分解了比较表达式,所以会比其他框架用起来方便太多。功能丰富(比如支持对模板进行批量测试),尽管代码轻量,但是功能也毫不含糊,感觉比googletest更好用。如何引入 正如上述所说,doctest 是head-only的,所以仅仅只需要一个 .h 文件即可,但是我建议不要这样,这样编译速度会慢一些,建议使用编译库再链接的方式,这种方式在cmake里面也很简单,如果不懂cmake,可以看看我这期视频:cmake入门 。 你只需在cmake项目中添加下列代码:include(FetchContent) FetchContent_Declare( doctest GIT_REPOSITORY https://github.com/doctest/doctest.git GIT_TAG v2.4.9 GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(doctest) target_link_libraries(target doctest_with_main) 这里的仓库链接由于是GitHub上,如果你不会科学上网的话,建议可以去手动下载GitHub上的代码然后 add_subdirectory() 也是一样的。当然也可以把对应的仓库在gitee上创建一个镜像,那么你就可以直接把上面的 GIT_REPOSITORY 换成你镜像的地址了,比如我拉了一个镜像地址如下:https://gitee.com/acking-you/doctest.git 替换即可。如何使用 开始前,你可以直接去看官方文档,写的也挺详细:官方文档 首先,我们要清楚,一个测试框架,你需要注意的就只有两点:如何组织测试 -> 测试宏如何进行测试断言 -> 断言宏 通过下面这个简单的测试进行一个简单的讲解://这个宏如果是通过链接的方式引入库的话千万不要加,如果是通过直接的include头文件引入的则需要加入 //#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "doctest.h" int factorial(int number) { return number <= 1 ? number : factorial(number - 1) * number; } TEST_CASE("testing the factorial function") { CHECK(factorial(1) == 1); CHECK(factorial(2) == 2); CHECK(factorial(3) == 6); CHECK(factorial(10) == 3628800); } 上述代码是在测试斐波那契数列的值。 通过 TEST_CASE 这个宏来组织一个测试,参数是该测试的名字是一个字符串值,在CLion中会以这个名字来标识这个测试。与 googletest 相比,对应的是 TEST 宏,但不同的是 googletest 需要传两个参数,两个都不是字符串,而且必须符合C++变量命名的字符规则,所以不能以空格或者其他非字母数字的任何符号放在其中,这点其实很不方便。 通过 CHECK 宏来进行断言判断,如果失败了CLion中会有对应的提示。参数是一个判断表达式,不…
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行