【发布时间】:2020-09-18 03:46:25
【问题描述】:
我有一个由三个成员 { xx, xy, yy } 和一个重载的 == 运算符组成的结构,该运算符按成员测试左右表达式的相应成员是否在某个精度范围内相等,或者两者都是 NaN s。相当琐碎。
对于我的测试用例,我想针对一个错字情况,我错误地比较了错误的成员。也许,我将左侧表达式中的xx 与右侧表达式中的xy 进行比较。也许,我根本忘了比较yy。
由于我使用的是 C++20,我不知道是否有可能构建 == 运算符正确性的编译时证明(如果我应该这样做的话)。试图以通常的方式解决这个问题,我发现自己列举了所有可能的排列:
EXPECT_EQ(C{1, 2, 3}, C{1, 2, 3});
EXPECT_NE(C{1, 2, 3}, C{1, 3, 2});
EXPECT_NE(C{1, 2, 3}, C{2, 1, 3});
EXPECT_NE(C{1, 2, 3}, C{2, 3, 1});
EXPECT_NE(C{1, 2, 3}, C{3, 1, 2});
EXPECT_NE(C{1, 2, 3}, C{3, 2, 1});
EXPECT_NE(C{1, 2, 3}, C{1, 2, nan});
EXPECT_NE(C{1, 2, 3}, C{1, nan, 3});
EXPECT_NE(C{1, 2, 3}, C{nan, 2, 3});
// ...
EXPECT_NE(C{1, 3, 2}, C{1, 2, 3});
EXPECT_EQ(C{1, 3, 2}, C{1, 3, 2});
// ...
这样的代码很丑,如果我用嵌套循环复制同样的代码:
for (T lxx = 1; lxx <= 3; lxx += 1) {
for (T rxx = 1; rxx <= 3; rxx += 1) {
for (T lxy = 1; lxy <= 3; lxy += 1) {
for (T rxy = 1; rxy <= 3; rxy += 1) {
// ...
似乎我在测试中重新实现了相等运算符,这错过了测试的重点。
如何正确执行此操作?我是否错过了一些边缘情况,也许这会简化它?如果我在一个结构中有四个成员并且不希望测试用例代码爆炸,如何扩展此类测试?
【问题讨论】:
-
除非检查所有可能的输入,否则无法证明函数的正确性。
-
@cigien 我同意测试。但除此之外,可以使用 curry-howard 同构和证明助手 (Coq) 来证明代码的正确性而无需测试。
-
在测试中总有一点需要人工验证。由于许多测试通常取决于等式运算符的有效性,因此该等式运算符最终无法使用通常的行为测试技术进行测试。在测试中编写或复制粘贴相等运算符的主体不是一个坏主意,检查两次,查看输入。至少你的测试会发现回归。
标签: c++ unit-testing testing c++20