提问人:Zanko 提问时间:7/17/2017 最后编辑:Koray TugayZanko 更新时间:8/15/2017 访问量:636
是否有可能编写一个涵盖所有内容的单元测试?
Is it possible to write a unit test that cover everything?
问:
假设我有一个函数
function (int x) {
if (x < 10) return true;
return false;
}
理想情况下,您想编写 2^32 - 1 个测试用例来涵盖从 INT_MIN 到 INT_MAX?当然,这是不切实际的。
为了让生活更轻松,我们编写了测试用例
- x < 10,测试 x = 9 期望为 true
- x == 10,测试 x = 10 期望为 false
- x > 10,测试 x = 11 预期为 false
这些测试用例很好,但并不涵盖所有用例。假设有一天有人将函数修改为
function (int x) {
if (x == 12) return true;
if (x < 10) return true;
return false;
}
他将运行测试并实现所有测试通过。我们如何确保在不走极端的情况下覆盖每个 senario。我所描述的这个问题有一个关键词吗?
答:
这部分是评论,部分是答案,因为你表达问题的方式。
评论
是否有可能编写一个涵盖所有内容的单元测试?
不。即使在您的示例中,您也可以将测试用例限制为 但是,如果将代码移动到 64 位系统,然后有人添加一行 using 或其他东西怎么办?2^32
2^34
此外,您的问题向我表明您正在考虑使用动态代码的静态测试用例,例如,代码是动态的,因为它会随着时间推移被程序员更改,这并不意味着代码会动态修改。您应该考虑使用动态代码进行动态测试用例。
最后,您没有注意到它是白盒、灰盒还是黑盒测试。
答案
让工具分析代码并生成测试数据。
请参见:关于自动生成测试数据的调查
您还询问了搜索的关键字。
这是我发现有价值的谷歌搜索:
相关
我自己从未使用过这些测试用例工具之一,因为我使用 Prolog DCG 来生成我的测试用例,目前我正在做的一个项目在大约两分钟内生成数百万个测试用例,并在几分钟内测试它们。一些失败的测试用例我自己永远不会想到,所以这可能被一些人认为是矫枉过正,但它是有效的。
由于许多人不知道 Prolog DCG,因此 Eric Lippert 将 C# 与 LINQ 结合使用,每棵二叉树都有类似的解释
不,目前还没有一种通用的算法不涉及某种非常密集的计算(例如,测试大量案例),但你可以以这样一种方式编写单元测试,即在方法更改的情况下,它们失败的可能性更高。例如,在给出的答案中,编写一个 x = 10 的测试。对于其他两种情况,首先选择 11 和 之间的几个随机数并测试它们。然后测试几个介于 9 和 9 之间的随机数。在您描述的修改后,测试不一定会失败,但与刚刚对值进行硬编码相比,它失败的可能性更大。int.Max
int.Min
此外,正如@GuyCoder在他的出色回答中指出的那样,即使你确实尝试过这样的事情,也很难(或不可能)证明一种方法没有可能改变会破坏你的测试。
另外,请记住,没有一种测试自动化(包括单元测试)是万无一失的测试方法;即使在理想条件下,您通常也无法 100% 证明您的程序是正确的。请记住,几乎所有的软件测试方法从根本上都是经验方法,而经验方法并不能真正实现 100% 的确定性。(不过,它们可以达到很高的确定性;事实上,许多科学论文达到了95%或更高的确定性 - 有时甚至更高 - 所以在这种情况下,差异可能不是那么重要)。例如,即使你有 100% 的代码覆盖率,你怎么知道测试中某处没有错误?你打算为测试编写测试吗?(这可能导致海龟一路向下的情况)。
如果你想真正了解它,并且你相信大卫·休谟,你真的不可能根据经验测试对某件事 100% 确定;每次运行测试时都通过了测试,但这并不意味着它将来会继续通过。不过,我跑题了。
如果你有兴趣,形式验证研究演绎证明软件(或至少软件的某些方面)是正确的方法。请注意,这样做的主要问题是,对任何复杂系统的完整程序进行形式验证往往非常困难或不可能,特别是如果您使用的是未经正式验证的第三方库。(这些,以及最初学习技术的困难,是形式验证在学术界和某些非常狭窄的行业应用之外没有真正起飞的一些主要原因)。
最后一点:软件附带错误。你很难找到任何复杂的系统,在发布时是100%没有缺陷的。正如我上面提到的,目前还没有已知的技术可以保证你的测试发现了所有的错误(如果你能找到一个,你就会成为一个非常富有的人),所以在大多数情况下,你必须依靠统计措施来知道你是否已经进行了充分的测试。
TL;DR:不,你不能,即使你可以,你仍然不能100%确定你的软件是正确的(例如,你的测试中可能存在错误)。在可预见的未来,您的单元测试用例也需要维护。不过,您可以编写测试以更灵活地应对更改。
评论