0

我提前道歉,因为我对软件测试很陌生。但是我有一个看起来很简单的代码来创建一个具有 100% 代码覆盖率的白盒测试用例:

01 public class ShapeAreas {
02
03 public double oneParameter(String shape, float x1)
04 {
05     float area;
06     if (shape.equals("A"))
07         return x1 * x1 * Math.XI;
08     else if (shape.equals("B"))
09         return x1 * x1;
10     else 
11         return -1.0;
12 }
13 
14 public double twoParameter(String shape, float x1, float x2)
15 {
16     float area;
17     if (shape.equals("N"))
18         return x1 * x2;
19     else if (shape.equals("M"))
20         return 0.5 * x1 * x2;
21     else
22         return -1.0;
23 }
24 }

我需要有关我的输入数据在此代码上的外观的帮助,以便以最少的测试用例实现 100% 的代码覆盖率。

我很感激我能得到的任何帮助,谢谢!

4

2 回答 2

1

我自由地将行号添加到您的代码中,以便能够提供更好的解释。您在评论中提到您对语句覆盖感兴趣。您的代码示例中的语句位于第 07、09 和 11 行以及第 18、20 和 22 行。当然,if语句本身也是语句(因此得名),但这些语句将在每次执行时执行相应的功能。

在函数的一次执行中oneParameter,将执行以下条件语句之一:在第 07 行、第 09 行或第 11 行。这是因为if-else if-else语句的排他性。类似地,在一次函数调用中twoParameter,将执行第 18 行、第 20 行或第 22 行中的语句。

因此,要涵盖所有语句,您必须调用每个函数 3 次。控制所采用的实际分支的参数在这两种情况下都是shape参数。这意味着,其他参数的值与将执行哪个语句无关。一组简单的调用可能是:

oneParameter("A", 0.0);
oneParameter("B", 0.0);
oneParameter("any other", 0.0);
twoParameter("N", 0.0, 0.0);
twoParameter("M", 0.0, 0.0);
twoParameter("any other", 0.0, 0.0);

这是实现 100% 语句覆盖率的最小调用集的示例。令人惊讶的是,这些只是调用——甚至没有对结果进行任何评估。当我们谈论测试覆盖率时,隐含的假设是,相应的代码行不仅被执行,而且相应的结果作为测试的一部分被评估。这可能如下所示:

assertEquals(0.0, oneParameter("A", 0.0));
assertEquals(0.0, oneParameter("B", 0.0));
assertEquals(-1.0, oneParameter("any other", 0.0));
assertEquals(0.0, twoParameter("N", 0.0, 0.0));
assertEquals(0.0, twoParameter("M", 0.0, 0.0));
assertEquals(-1.0, twoParameter("any other", 0.0, 0.0));

尽管它现在具有 100% 的语句覆盖率并且还执行结果评估,但它仍然远不是一个高质量的测试套件。原因如下: 执行单元测试的主要目标是发现代码中的错误。然而,上面的一组测试并不适合发现任何有趣的错误。为您提供一些此测试套件找不到的可能错误示例:

  • 错误地,函数oneParameter"A"的计算"B"被交换了。
  • 操作中的twoParameter函数被错误地交换了。"N"*+
  • 在函数twoParameterfor中,表达式与"N"相乘,而不是与x1相乘。x2x1x1
  • 在函数twoParameter"M",常量被设置为0.05而不是正确的0.5

这些只是可能的错误的示例。因此,认真寻找可能的错误的目标需要超越覆盖范围。实际上,甚至可能有部分代码根本不适合使用单元测试进行测试——尽管在您的简单示例中并非如此。此类代码部分的示例是无法访问的代码(例如,为提高健壮性而添加的 switch 语句的默认分支),或仅包含与其他组件交互的代码,在这种情况下,集成测试是更适合的方法。因此,达到 100% 覆盖率的目标通常是没有意义的,即使您真诚地努力追求质量卓越的单元测试套件。

然而,对于有兴趣确保他们在代码中处理所有相关场景的开发人员来说,覆盖率是一个有价值的信息。可悲的是,从管理的角度判断测试套件的质量时,覆盖率远没有那么有价值:在这种情况下,它通常会降低到仅仅一个百分比,并且开发人员被迫创建测试,直到达到一定的覆盖率百分比- 但通常没有给他们足够的培训、时间和鼓励来正确地进行测试。因此,为了达到 80% 的覆盖率,所有琐碎的代码(getter 和 setter 等)都可能会被“测试”以增加覆盖率。然而,测试最复杂和最难测试的 20% 的代码,由于没有时间而被推迟(尽管这很可能是隐藏错误的代码)。而且,即使是已经覆盖的 80%,也可能像我上面展示的最小测试套件一样进行了糟糕的测试。

于 2019-03-08T22:02:22.353 回答
0

您必须在每种方法中寻找分支才能获得 100% 的覆盖率。它是A, B,X作为方法的shape参数,, ,作为方法。oneParameterNMXtwoParameter

每种方法的 3 个测试用例将为您提供 100% 的覆盖率。

但是,它不会告诉您您的代码是 100% 正确的。

尝试例如null形状。(这将导致NullpointerException

您还需要定义计算所需的精度。(double返回类型与浮点计算。)

public void testOneParameterWithShapeB() {
  double result = sut.oneParameter("B", 1.0);
  //TODO check the result
}
于 2019-03-06T02:05:39.950 回答