“Code covered” vs. “Code tested”?

岁酱吖の 提交于 2019-12-01 11:14:51
Brian

I wouldn't say "take it with a grain of salt" (there is a lot of utility to code coverage), but to quote myself

TDD and code coverage are not a panacea:

· Even with 100% block coverage, there still will be errors in the conditions that choose which blocks to execute.

· Even with 100% block coverage + 100% arc coverage, there will still be errors in straight-line code.

· Even with 100% block coverage + 100% arc coverage + 100% error-free-for-at-least-one-path straight-line code, there will still be input data that executes paths/loops in ways that exhibit more bugs.

(from here)

While there may be some tools that can offer improvement, I think the higher-order bit is that code coverage is only part of an overall testing strategy to ensure product quality.

<100% code coverage is bad, but it doesn't follow that 100% code coverage is good. It's a necessary but not sufficient condition, and should be treated as such.

Also note that there's a difference between code coverage and path coverage:

void bar(Foo f) {
    if (f.isGreen()) accountForGreenness();
    if (f.isBig()) accountForBigness();
    finishBar(f);
}

If you pass a big, green Foo into that code as a test case, you get 100% code coverage. But for all you know a big, red Foo would crash the system because accountForBigness incorrectly assumes that some pointer is non-null, that is only made non-null by accountForGreenness. You didn't have 100% path coverage, because you didn't cover the path which skips the call to accountForGreenness but not the call to accountForBigness.

It's also possible to get 100% branch coverage without 100% path coverage. In the above code, one call with a big, green Foo and one with a small, red Foo gives the former but still doesn't catch the big, red bug.

Not that this example is the best OO design ever, but it's rare to see code where code coverage implies path coverage. And even if it does imply that in your code, it doesn't imply that all code or all paths in library or system are covered, that your program could possibly use. You would in principle need 100% coverage of all the possible states of your program to do that (and hence make sure that for example in no case do you call with invalid parameters leading to error-catching code in the library or system not otherwise attained), which is generally infeasible.

Should we take the coverage reported by such a tool with a grain of salt when writing tests?

Absolutely. The coverage tool only tells you what proportion of lines in your code were actually run during tests. It doesn't say anything about how thoroughly those lines were tested. Some lines of code need to be tested only once or twice, but some need to be tested over a wide range of inputs. Coverage tools can't tell the difference.

Also, a 100% test coverage as such does not mean much if the test driver just exercised the code without meaningful assertions regarding the correctness of the results.

Coverage is only really useful for identifying code that hasn't been tested at all. It doesn't tell you much about code that has been covered.

Yes, this is the primary different between "line coverage" and "path coverage". In practice, you can't really measure code path coverage. Like static compile time checks, unit tests and static analysis -- line coverage is just one more tool to use in your quest for quality code.

Testing is absolutly necessary. What must be consitent too is the implementation.

If you implement something in a way that have not been in your tests... it's there that the problem may happen.

Problem may also happen when the data you test against is not related to the data that is going to be flowing through your application.

So Yes, code coverage is necessary. But not as much as real test performed by real person.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!