【发布时间】:2018-03-16 10:46:59
【问题描述】:
我有一个相当大的 C++ library 测试套件,其线路覆盖率接近 100%,但分支覆盖率只有 55.3%。浏览lcov 的结果,似乎大部分遗漏的分支都可以用C++ 的多种抛出std::bad_alloc 的方式来解释,例如每当构造 std::string 时。
我在问自己如何在这种情况下提高分支覆盖率,并认为最好有一个 new 运算符,该运算符可以配置为在命中每个错过的分支所需的尽可能多的分配之后抛出 std::bad_alloc我的测试套件。
我(天真地)尝试定义一个全局 void* operator new (std::size_t) 函数,该函数对全局 int allowed_allocs 进行倒计时,并在达到 0 时抛出 std::bad_alloc。
这有几个问题:
- 在“第一个”所需的
throw之前,很难获得new的调用次数。我可以执行试运行来计算成功所需的调用,但是如果多个调用可能在同一行中失败,这将无济于事,例如类似std::to_string(some_int) + std::to_string(another_int)的东西,其中每个std::to_string,通过operator+的连接以及初始分配可能会失败。 - 更糟糕的是,我的测试套件(我正在使用 Catch)本身使用了很多
new调用,所以即使我知道 我的 代码需要多少调用,也很难猜测如何测试套件的许多额外调用是必要的。 (更糟糕的是,Catch 有几种“冗长”模式,这些模式会产生大量需要记忆的输出......)
您知道如何提高分支覆盖率吗?
2017 年 10 月 7 日更新
同时,我发现https://stackoverflow.com/a/43726240/266378 带有指向 Python 脚本的链接,用于过滤由 lcov 输出中的异常创建的一些分支。这使我的分支覆盖率达到了 71.5%,但剩下的未命中分支仍然很奇怪。例如,我有几个这样的 if 语句:
有四个 (?) 分支,其中一个未命中(reference_token 是 std::string)。
有谁知道这些树枝是什么意思以及它们是如何被击中的?
【问题讨论】:
-
你建议如何从 bad_alloc 中恢复?
-
@NeilButterworth Catch 有一个断言
CHECK_THROWS_AS,如果传递的表达式抛出特定异常,则该断言成功。 -
@MooingDuck 是的,大多数错过的分支都在没有 if/switch 的行中,但是对函数的简单分配可能会因为调用构造函数而抛出。
-
@NielsLohmann:哦,我明白了。这是有道理的。
-
@Neils 我不认为这是恢复,只是报告,即使您没有处理它,您的运行时或操作系统也可能会为您完成。我的意思是,如果你无法恢复,它可能不值得测试 - 只是失败。
标签: c++ code-coverage lcov catch-unit-test