这更像是一个设计问题。
假设您有这样的方法(作为示例):
if (x == 5) {
c = 1;
} else {
if (z != 2) {
b = 6;
} else {
a = 3;
}
您是否认为为每个可能的分支设置junit是最佳做法?即,testx5,测试xnot5znot2,testxnot5z2等,或类似的东西:
void testMethod() {
// x is 5
test/assert code;
// x not 5, z not 2
test/assert code;
// x not 5, z is 2
test/assert code
// etc
}
编辑:为了清楚起见,我的目标是完整的代码覆盖率。我只想知道是否应该为每个分支进行新测试或将它们组合在一个测试中。感谢您的投入。
答案 0 :(得分:9)
您正在讨论的内容称为分支覆盖。
传统观点认为,编写代码来覆盖该用例非常重要,编写测试用例来覆盖该代码非常重要。所以这似乎可以说100%的分支覆盖率是一个很好的目标(并且也意味着100%的声明覆盖率,但不一定是100%循环或100%条件覆盖率)。
但是,您还需要平衡编写测试的工作量和获得测试的价值。例如,如果您正在测试的代码有一个try / catch来捕获已检查的异常,但几乎从不抛出异常(或者很难导致在测试用例中引发异常),那么编写一个测试来覆盖该异常可能不值得你花时间。
这就是为什么你在许多地方看到,针对一定百分比的测试覆盖率是一个坏主意,因为你最终编写测试用例来获得覆盖,而不是发现错误。在您的示例中,是的,每个分支都应该拥有自己的测试用例。在每一条生产代码中,它可能都没有必要。
答案 1 :(得分:9)
JUnit FAQ似乎表明,如果只是因为JUnit只报告测试方法中的第一个断言失败,那么使用更少的断言进行更多测试会更好。使用一种方法,如果你打破x = 5的情况,你就无法判断是否有任何x!= 5个案例仍然有效。
答案 2 :(得分:4)
在单元测试中,您的目标是测试行为 - 而不是“代码”。想想你正在测试一个黑盒子的方法,你想看看它是否正常工作。你不知道它是如何在内部完成的,但是你期望某些输入有某些结果。因此,您需要针对您希望代码如何工作的不同情况创建测试,就像您不知道该方法的内部如何实际完成它的工作一样。所以你要编写像“applysDiscountToShoppingCart”和“addsDeliveryFeeToShoppingCart”这样的测试。
现在,所有这一切,创建“边缘情况”也很有用,在这种情况下,你正在测试可能会破坏的东西(如空值,零,负数,数据太大/太小等),看看是否它也以预期的方式失败了。通常要写那些,你需要知道方法实际上是如何工作的。如果您可以设计涵盖所有代码的测试,那就太棒了! 100%的测试覆盖率是一个肯定的事情,但根据具体情况,它并不总是实用(或有用)。
答案 3 :(得分:3)
特别是在构建服务器上,更容易拥有许多不同的测试用例/函数,因为很容易识别哪个测试失败。另一个缺点是,如果第一个测试用例失败,测试用例将停止,并且您将不知道其他测试用例的结果。
对于我个人来说,当你必须进行大量的复制粘贴来设置/解释测试用例时,这个好处就会停止,在这种情况下,我将在同一个测试用例中做几个断言。