将我当前的代码项目转换为TDD,我注意到了一些事情。
class Foo {
public event EventHandler Test;
public void SomeFunction() {
//snip...
Test(this, new EventArgs());
}
}
在测试此代码时,我可以看到两种危险,并依赖代码覆盖率工具来确定您是否有足够的测试。
Test
事件是否被触发。如果您忘记了这一点,单独使用代码覆盖工具就不会告诉您。为此,我在启动函数中添加了一个事件处理程序,使它看起来像这样:
Foo test;
int eventCount;
[Startup] public void Init() {
test = new Foo();
// snip...
eventCount = 0;
test.Test += MyHandler;
}
void MyHandler(object sender, EventArgs e) { eventCount++; }
现在我只需检查eventCount
即可查看我的事件被调用的次数,如果它被调用的话。很简约。只有现在我们才能通过一个永远不会被任何测试捕获的阴险小错误:即SomeFunction()
在尝试调用它之前不会检查事件是否有任何处理程序。这将导致null取消引用,我们的任何测试都不会捕获它,因为默认情况下它们都附加了一个事件处理程序。但同样,代码覆盖工具仍将报告完整覆盖率。
这只是我手边的“真实世界的例子”,但是我发现这些错误可能会更多,即使你的代码覆盖率达到100%,这仍然无法转化为100%测试。在编写测试时,我们是否应该采用这种工具报告的覆盖范围?是否还有其他类型的工具可以捕获这些漏洞?
答案 0 :(得分:4)
我不会说“带着一粒盐”(代码覆盖有很多实用工具),但引用自己
TDD和代码覆盖率不是 万能:
·即使100%阻止 报道,仍然会有错误 在选择哪个条件下 要执行的块。
·即使100%阻止 有覆盖率+ 100%弧覆盖率 仍将是直线误差 代码。
·即使100%阻止 覆盖率+ 100%弧覆盖率+ 100% 无差错换的,至少一路径 直线代码,仍然会有 是输入执行的数据 路径/循环以表现更多的方式 错误。
(来自here)
虽然可能有一些工具可以提供改进,但我认为高阶位是代码覆盖只是确保产品质量的整体测试策略的一部分。
答案 1 :(得分:4)
< 100%的代码覆盖率很差,但并不是说100%的代码覆盖率是好的。这是一个必要但不充分的条件,应该这样对待。
另请注意,代码覆盖率和路径覆盖率之间存在差异:
void bar(Foo f) {
if (f.isGreen()) accountForGreenness();
if (f.isBig()) accountForBigness();
finishBar(f);
}
如果您将一个大的绿色Foo作为测试用例传递给该代码,则可获得100%的代码覆盖率。但是对于所有你知道的大红色Foo会使系统崩溃,因为accountForBigness错误地认为某些指针是非空的,只有accountForGreenness才会使其为非空。您没有100%的路径覆盖率,因为您没有覆盖跳过对accountForGreenness的调用的路径,而没有覆盖对accountForBigness的调用。
在没有100%路径覆盖的情况下,也可以获得100%的分支覆盖率。在上面的代码中,一个带有一个大的绿色Foo的调用和一个带有一个小的红色Foo的调用给前者,但仍然没有捕获大的红色bug。
并不是说这个例子是有史以来最好的OO设计,但是很少看到代码覆盖意味着路径覆盖的代码。即使它确实暗示在您的代码中,它并不意味着库或系统中的所有代码或所有路径都被覆盖,您的程序可能会使用它。您原则上需要100%覆盖程序的所有可能状态(并因此确保例如在任何情况下都不会使用无效参数调用,导致库或系统中的错误捕获代码无法获得),这通常是不可行的。
答案 2 :(得分:2)
在编写测试时,我们是否应该采用这种工具报告的覆盖范围?
绝对。覆盖率工具仅告诉您在测试期间代码中的哪些行实际运行。它没有说明这些线路经过多次彻底测试。某些代码行只需要测试一次或两次,但有些代码需要在很多输入上进行测试。覆盖工具无法区分。
答案 3 :(得分:1)
此外,如果测试驱动程序只是在没有关于结果正确性的有意义断言的情况下执行代码,那么100%的测试覆盖率并不意味着什么。
答案 4 :(得分:0)
覆盖范围仅对识别尚未经过测试的代码非常有用。它没有告诉你很多关于已经涵盖的代码。
答案 5 :(得分:0)
是的,这是“线路覆盖”和“路径覆盖”之间的主要区别。实际上,您无法真正衡量代码路径覆盖率。与静态编译时间检查一样,单元测试和静态分析 - 线路覆盖只是您在寻求高质量代码时使用的另一种工具。
答案 6 :(得分:0)
绝对必要的是测试。实施也必须是合理的。
如果你以一种尚未进入测试的方式实现某些东西......就会出现问题。
当您测试的数据与将要流经您的应用程序的数据无关时,也可能会出现问题。
是的,代码覆盖是必要的。但不如真人所做的真实测试那么多。