如何在单元测试中测试想要引发的编译错误?
考虑代码:
class ErrorTest
{
OtherClass& read_write() {
return other;
}
const OtherClass& read_only() const {
return other;
}
private:
OtherClass other;
};
如何测试read_only()赋值?这非常重要,应该坚定地检查以正确生成编译器错误:
ErrorTest test;
OtherClass other = test.read_only();
test.read_write() = other.modify();
test.read_only() = other.modify(); /* This should error */
答案 0 :(得分:1)
我想现在的主要问题是,您是否正在测试您的代码或编译器?
测试编译器并不一定是坏事......我过去曾经有过编译器升级掩码错误,所以确保你得到你期望的同一组安全检查会很好。< / p>
但是,你必须做很多腿部工作。您的单元测试必须生成编译器,捕获它的输出,并在正确的行上解析它以获取正确的错误语句。这不是微不足道的,可以说是不值得的。
一种稍微简单的方法可能是保留错误代码的目录,并让脚本一次编译一个文件。在那里有一个'#ifdef MAKEFAIL'标志,打开应该失败的确切条件。确保编译器在未设置该标志时返回0,并在执行时返回非零值。这假设编译器在失败时返回非零...我不知道MSVC是否遵循该规则。
为了解决可移植性问题,我将抛出的第三个选项是autoconf。设置可能会很痛苦,但其目的之一是确保在编译之前拥有一个理智的开发环境。你可以在其中添加这样的测试,然后让它找到编译器并尝试它。
答案 1 :(得分:1)
这看起来有点像在* nix机器上从源代码“./configure”进行构建时发生的自动检测。 autoconf脚本构建很少的程序并尝试编译它们以确定编译器可用和支持的内容。
重用其中任何一种可能都不实际,但您可能需要相同的模型。每个测试都有自己的文件或文件集,以及单独的项目文件/ make target / etc。然后你的测试脚本会尝试制作每个测试用例,并通过grep或比较来检查是否发生了预期的错误。输出到与测试用例一起存储的基线输出。
答案 2 :(得分:0)
编译器和平台的有效测试将针对运行时的运行时变化。我经常这样做,重现生产代码中存在的一些小行为,并检查行为是否符合预期。
但是对于这种情况,你真正想要的是一个静态分析工具,它会检查以确保开发人员编写的代码遵循这样的约定。这当然是一个有效的构建工具。但是,搜索静态分析工具以查找您在此处指定的内容可能很困难。我将从List of tools for static code analysis部分的维基百科文章C/C++开始。
请注意,您编写的代码不是“错误”,它只是您的惯例。这是一个非常好的约定,但编译器不会也不应该限制您使用该约定。静态分析工具也不应该。因此,您需要找到一个允许您配置允许内容和不允许内容的内容。
答案 3 :(得分:0)
在C ++ 11中,您可以使用
std::is_const< decltype( std::declval<ErrorTest>().read_only() ) >::value
在编译时(或根据需要运行时)知道此返回类型是否为const。