【问题标题】:Computation of Conditional Coverage in CoberturaCobertura中条件覆盖的计算
【发布时间】:2013-01-28 12:07:02
【问题描述】:

我有 2 段代码给我带来了麻烦。我使用单元测试对它们进行测试,使用 cobertura 来分析测试覆盖率,但我不明白条件覆盖率是如何计算的。 这是第一篇:

if ((x.getInt() == a) 
 || (x.getInt() == y.getInt()) { ...

Cobertura 报告我需要涵盖 4 个案例,假设忽略短路,这似乎很好。

然后,在另一种方法中,我有另一个(更长的)条件:

if ((x == null)
 || ObjectUtils.equals(x.getInt(), a)
 || ObjectUtils.equals(x.getInt(), y.getInt())) {
  ...

下面是我不明白的部分:Cobertura 报告说涵盖了 5/6 个案例。我本来预计有 8 个案例,我可以解释 5 个案例(考虑到 x == null),但是

cobertura 在这些情况下如何处理条件覆盖,为什么会导致 6 个情况?

【问题讨论】:

  • 您正在考虑全路径覆盖和/或分支覆盖。对于条件覆盖,每个布尔表达式都需要评估为真和假(两个不同的测试用例)。如果您有三个布尔表达式,那么您有 6 个案例。在code coverage 上的维基百科文章中对此进行了很好的解释。

标签: code-coverage cobertura


【解决方案1】:

覆盖率不是通过测试所有可能的布尔标志状态组合来衡量的,而是仅通过测试足以覆盖所有用例的那些组合来衡量。

考虑以下类:

public class MyClass {

public boolean allOr(boolean x, boolean y) {
    return x || y;
}

public boolean allOr(boolean x, boolean y, boolean z) {
    return x || y || z;
}

public boolean allOr(boolean w, boolean x, boolean y, boolean z) {
    return w || x || y || z;
}

public boolean allAnd(boolean x, boolean y) {
    return x && y;
}

public boolean allAnd(boolean x, boolean y, boolean z) {
    return x && y && z;
}

public boolean andOr(boolean x, boolean y, boolean z) {
    return x && y || z;
}

public boolean orAnd(boolean x, boolean y, boolean z) {
    return (x || y) && z;
}

}

提供完整覆盖的测试如下:

public class MyClassTest {

@Test
public void testAllOr2() {
    MyClass instance = new MyClass();
    // For OR clause, test that all false returns false
    assertFalse(instance.allOr(false, false));
    // For OR clause, test that any one true returns true
    assertTrue(instance.allOr(false, true));
    assertTrue(instance.allOr(true, false));
}

@Test
public void testAllOr3() {
    MyClass instance = new MyClass();
    // For OR clause, test that all false returns false
    assertFalse(instance.allOr(false, false, false));
    // For OR clause, test that any one true returns true
    assertTrue(instance.allOr(false, false, true));
    assertTrue(instance.allOr(false, true, false));
    assertTrue(instance.allOr(true, false, false));

    // These do not add to coverage
    // assertTrue(instance.allOr(false, true, true));
    // assertTrue(instance.allOr(true, false, true));
    // assertTrue(instance.allOr(true, true, false));
    // assertTrue(instance.allOr(true, true, true));
}

@Test
public void testAllOr4() {
    MyClass instance = new MyClass();
    // For OR clause, test that all false returns false
    assertFalse(instance.allOr(false, false, false, false));
    // For OR clause, test that any one true returns true
    assertTrue(instance.allOr(false, false, false, true));
    assertTrue(instance.allOr(false, false, true, false));
    assertTrue(instance.allOr(false, true, false, false));
    assertTrue(instance.allOr(true, false, false, false));
}

@Test
public void testAllAnd2() {
    MyClass instance = new MyClass();
    // For AND clause, test that all true returns true
    assertTrue(instance.allAnd(true, true));
    // For AND clause, test that any one false returns false
    assertFalse(instance.allAnd(true, false));
    assertFalse(instance.allAnd(false, true));
}

@Test
public void testAllAnd3() {
    MyClass instance = new MyClass();
    // For AND clause, test that all true returns true
    assertTrue(instance.allAnd(true, true, true));
    // For AND clause, test that any one false returns false
    assertFalse(instance.allAnd(false, true, true));
    assertFalse(instance.allAnd(true, false, true));
    assertFalse(instance.allAnd(true, true, false));
}

@Test
public void testAndOr() {
    MyClass instance = new MyClass();
    // Since AND takes precedence,
    // OR is the external operator, AND is the internal operator
    // For the AND clause, false can be achieved in two ways
    // Compare to testAllAnd2 # 2, 3
    assertFalse(instance.andOr(true, false, false));
    assertFalse(instance.andOr(false, true, false));
    // This completes the first test case for the external operator
    // Compare to testAllOr2 # 1

    // Now irrespective of the arguments
    // as long as the value returned by the internal operation is false
    // we can perform the testAllOr2 # 2
    assertTrue(instance.andOr(true, false, true));
    // We do not need the case for false, true, true
    // because we have tested that no matter what the first two args are
    // it does not make a difference as long as one of them is false

    // However, if both args are true
    // the value returned by the internal operation is true
    // we can perform the testAllOr2 # 3
    // This is only possible in one way
    // Compare testAllAnd2 # 1
    assertTrue(instance.andOr(true, true, false));
}

@Test
public void testOrAnd() {
    MyClass instance = new MyClass();
    // Since OR takes precedence,
    // AND is the external operator, OR is the internal operator
    // For the OR clause, true can be achieved in two ways
    // Compare to testAllOr2 # 2, 3
    assertTrue(instance.orAnd(false, true, true));
    assertTrue(instance.orAnd(true, false, true));
    // This completes the first test case for the external operator
    // Compare to testAllAnd2 # 1

    // Now irrespective of the arguments
    // as long as the value returned by the internal operation is true
    // we can perform the testAllAnd2 # 2
    assertFalse(instance.orAnd(false, true, false));
    // We do not need the case for true, false, false
    // because we have tested that no matter what the first two args are
    // it does not make a difference as long as one of them is true

    // However, if both args are false
    // the value returned by the internal operation is false
    // we can perform the testAllAnd2 # 3
    // This is only possible in one way
    // Compare testAllOr2 # 1
    assertFalse(instance.orAnd(false, false, true));
}

}

【讨论】:

    猜你喜欢
    • 2013-09-26
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 2011-04-11
    • 2017-01-03
    • 2010-11-14
    相关资源
    最近更新 更多