从覆盖率报告中删除自动生成的异常代码
Remove auto generated exception code from coverage report
让我们从一个最小的工作示例开始:
main.cpp:
#include <iostream>
#include <string>
int main() {
std::cout << "hello " + std::to_string(42);
return 0;
}
我使用以下标志编译此代码:
[g++/clang++] -std=c++11 -g -Og --coverage -Wall -o main main.cpp
clang 4.0.1
海湾合作委员会 4.8.5.
我只有 50% 的代码覆盖率,因为编译器生成异常代码,但未执行,如 in another Whosebug question 所述。
问题是通过 -fno-exceptions
禁用异常对我来说不是一个选项。我正在为使用异常编写单元测试的代码,因此禁用所有异常不是一个选项。
为了生成报告,我使用 gcovr
,如果是 clang++,另外 llvm-cov gcov
进行转换。但我不受这些工具的约束,所以如果您有其他不显示此行为的工具,请推荐它们!
基本上,我需要一种方法来 compile/write 对此代码进行单元测试,并在启用异常的情况下获得 100% 的分支/条件覆盖率。有办法吗?
嗯,我相信你的意图不是实际测试这一小段代码,而是在项目中使用这个概念...
您输入的代码抛出异常 - 当您没有剩余内存来存储将使用 std::to_string
创建的字符串时抛出 bad_alloc
。为了 100% 安全,std::to_string
应该被 try-catch
包围,您可以在其中处理异常。
要构建 100% 代码覆盖率的单元测试,您需要强制发生异常 - 在这种特定情况下几乎不可能保证,因为参数是一个常数。但是,在您的项目中,您可能需要分配一些大小可变的数据 - 在这种情况下,您可以在代码中隔离分配内存的方法,以分别测试它们。然后你传递给这些方法,在测试函数中,分配大量数据来评估你在 catch 块中放置的内容(并检查你是否正确处理它)。
例如,这段代码应该抛出异常,您可以在构建测试时用它来启发自己 (source):
// bad_alloc.cpp
// compile with: /EHsc
#include<new>
#include<iostream>
using namespace std;
int main() {
char* ptr;
try {
ptr = new char[(~unsigned int((int)0)/2) - 1];
delete[] ptr;
}
catch( bad_alloc &ba) {
cout << ba.what( ) << endl;
}
}
但是,如果您不打算处理代码中的所有 bad_alloc
异常(或绝对所有异常),则无法获得 100% 的覆盖率 - 因为它不会被 100% 覆盖... 不过,在大多数情况下,真正的 100% 覆盖率是不必要的。
让我们从一个最小的工作示例开始:
main.cpp:
#include <iostream>
#include <string>
int main() {
std::cout << "hello " + std::to_string(42);
return 0;
}
我使用以下标志编译此代码:
[g++/clang++] -std=c++11 -g -Og --coverage -Wall -o main main.cpp
clang 4.0.1
海湾合作委员会 4.8.5.
我只有 50% 的代码覆盖率,因为编译器生成异常代码,但未执行,如 in another Whosebug question 所述。
问题是通过 -fno-exceptions
禁用异常对我来说不是一个选项。我正在为使用异常编写单元测试的代码,因此禁用所有异常不是一个选项。
为了生成报告,我使用 gcovr
,如果是 clang++,另外 llvm-cov gcov
进行转换。但我不受这些工具的约束,所以如果您有其他不显示此行为的工具,请推荐它们!
基本上,我需要一种方法来 compile/write 对此代码进行单元测试,并在启用异常的情况下获得 100% 的分支/条件覆盖率。有办法吗?
嗯,我相信你的意图不是实际测试这一小段代码,而是在项目中使用这个概念...
您输入的代码抛出异常 - 当您没有剩余内存来存储将使用 std::to_string
创建的字符串时抛出 bad_alloc
。为了 100% 安全,std::to_string
应该被 try-catch
包围,您可以在其中处理异常。
要构建 100% 代码覆盖率的单元测试,您需要强制发生异常 - 在这种特定情况下几乎不可能保证,因为参数是一个常数。但是,在您的项目中,您可能需要分配一些大小可变的数据 - 在这种情况下,您可以在代码中隔离分配内存的方法,以分别测试它们。然后你传递给这些方法,在测试函数中,分配大量数据来评估你在 catch 块中放置的内容(并检查你是否正确处理它)。
例如,这段代码应该抛出异常,您可以在构建测试时用它来启发自己 (source):
// bad_alloc.cpp
// compile with: /EHsc
#include<new>
#include<iostream>
using namespace std;
int main() {
char* ptr;
try {
ptr = new char[(~unsigned int((int)0)/2) - 1];
delete[] ptr;
}
catch( bad_alloc &ba) {
cout << ba.what( ) << endl;
}
}
但是,如果您不打算处理代码中的所有 bad_alloc
异常(或绝对所有异常),则无法获得 100% 的覆盖率 - 因为它不会被 100% 覆盖... 不过,在大多数情况下,真正的 100% 覆盖率是不必要的。