【问题标题】:What combinations of unit tests should be applied for code branches?应该为代码分支应用哪些单元测试组合?
【发布时间】:2014-01-06 21:08:26
【问题描述】:

如果我不太确定以下哪些测试是必要的或多余的。 考虑对以下代码进行单元测试:

public class Locker {

    public enum Type { FOO, BAR, FOOBAR };

    private Locker() {}

    public boolean shouldlock (int x) {
        return x > 10;
    }

    public boolean lock (Type type, int x) {
        switch (type) {
            case FOO : return shouldlock(x);
            case BAR : return shouldlock(x * 2);
        }
        return false;
    }
}

测试用例 1:测试 shouldlock 的真假情况。 - 毫无疑问。

Question 1:

测试用例2:lock 输入类型Foo 也被测试真假情况,即两者。 ?在其调用shouldlock 的基础上,我们已经为它测试了这两种情况。因此它可能是多余的。但不太确定。

Question 2:

测试用例 3:假设Question1 的答案为真,我们还需要测试Bar 的真假吗?

Question 3:

测试用例 4:假设对 Question1 and Question2 的回答都是正确的。现在假设 shouldlock 更改为私有(假设它)。测试的唯一区别是我应该省略Test case 1 吗?

Question 4:

测试用例5:是否需要检查唯一遗漏的枚举FOOBAR是否返回false?

Question 5:

假设问题 4 的答案是正确的,那么如果 enum 明天包含 100 多个项目怎么办?如何扩展这样的测试?

【问题讨论】:

  • 旁注:return x > 10 ? true : false; 可以简化为return x > 10;

标签: java unit-testing testing


【解决方案1】:
  1. 测试用例 1 - 是的,在边界条件上测试真假用例 (10, 11)。
  2. 测试用例 2 - 模拟 shouldlock 并验证它是用 x 调用的(可能使用一个常数值进行测试)。使用 Mockito 之类的东西,并让它仅在调用 lock 时调用真实方法。
  3. 测试用例 3 - 与测试用例 2 相同,但验证 shouldlock 是否被 x * 2 调用。
  4. 测试用例 4 - 您必须测试每种类型的边界用例:FOO 使用 10 和 11,BAR 使用 5 和 6。
  5. 测试用例 5 - 是的,只需对 FOOBAR 进行一项测试。
  6. 您必须为新值编写测试。如果有更多枚举值但它们都进入默认情况,则不需要更多的单元测试。如果有其他逻辑,则应编写单元测试(最好在生产代码之前)以测试该逻辑。

【讨论】:

    【解决方案2】:

    首先,这取决于您的代码必须处理哪些场景。从这个角度来看,您可以考虑以测试驱动开发 (TDD) 的方式来处理您的工作,在这种方式中,您首先编写应该涵盖您所需功能的测试,然后编写使您的测试通过的代码。

    使用这种方法,您的问题没有通用的有效答案。这仅取决于您需要什么以及您需要多么严格。

    其次,您可以在处理单元测试时牢记以下想法:使单元测试的代码覆盖率尽可能高。我在这里主要考虑的是 line 覆盖范围和 条件 覆盖范围。这意味着在单元测试期间执行的代码应该由尽可能多的行组成,并且应该分别覆盖尽可能多的条件分支。

    此外,使用这种方法,您可能希望尽可能减少冗余,即尽可能减少执行行的次数,但要高于 0(理想情况下为 1)。在这种情况下,您的问题的答案是:

    1. 仅适用于一种情况,truefalse
    2. 针对其中一种情况测试BAR 案例,但要测试它(您想覆盖case BAR 行。
    3. 只要您涵盖truefalse 两种情况,就可以。
    4. 是的,您还想覆盖return false 行。
    5. 代码覆盖率很重要,但当它没有回报时不要夸大其词。 :)

    【讨论】:

      【解决方案3】:

      为了这个问题,我知道这是一个人为的例子,所以我会笼统地回答。

      您希望使用尽可能多的输入进行测试,以使您自己确信代码有效。当然,您可能会遗漏一些东西,但是当您稍后需要重新创建错误时,测试将在那里。

      shouldlock 的情况下,我将使用一组整数进行测试,让我放心,代码可以正常工作——比如一个非常低的负数、一个非常高的正数、0 以及您期望的更具代表性的数字作为输入。

      lock而言,您的问题表明您正在考虑实施,我认为这是一个错误。您需要考虑该方法的客户。具体来说,不要说“我们还需要测试BAR 吗?”相反,您只需要考虑合理数量的方法可以被客户端调用并进行相应的测试。这意味着您的所有 enum 值。

      就规模而言,我认为这个问题没有实际意义,因为使用 100 项 enum 进行测试的难度(尽管不太可能)表明您应该更改实现,因此您的方法可能会改变。然后您的测试将反映这一点。

      至于把方法改成private,那就不用再测试了。只有您的公共 API 需要进行测试。不过,您可能希望向这些方法添加断言。

      最重要的是不要为超过 100% 的测试覆盖率而烦恼。收益递减,当发现错误时,您将有一个可用的测试来重现它并修复它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-30
        • 1970-01-01
        • 1970-01-01
        • 2013-03-05
        • 1970-01-01
        • 2021-06-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多