原文: https://howtodoinjava.com/junit/junit-parameterized-testcases-with-theory-and-datapoints/

在我之前关于该主题的文章中,介绍了如何编写带有@Parameters注解的参数化测试用例。 如果我选择了正确的单词,那么这种方法会很混乱并且不太可读。 不必要地需要大量关注。 嗯,还有另一种方法,您可以借助@Theory@DataPoints等注解在 Junit 中编写参数化测试用例。

我将以以前的帖子为例,并将其转换为新方法。 这是有道理的,因为在此之后我们将能够比较哪些变化以及与以前的方法有何不同。

1)使用@DataPoints馈送输入数据

在此,仅注解已从@Parameters更改为@DataPoints。 其余的概念是相同的。

以前,提供输入的方法是:

  1. @Parameters(name = "Run #Square of : {0}^2={1}")
  2. public static Iterable<Object []> data() {
  3. return Arrays.asList(new Object[][] { { 1, 1 }, { 2, 4 }, { 3, 19 },
  4. { 4, 16 }, { 5, 25 } });
  5. }

现在它是:

  1. @DataPoints
  2. public static int[][] integers()
  3. {
  4. return new int[][]{{1, 1}, {2, 4}, {3, 9}, {4, 16}, {5, 25}, {}};
  5. }

请注意,您可以使用@DataPoint注解分别编写输入。

  1. @DataPoint
  2. public static int[] input6 = new int[]{6, 36};
  3. @DataPoint
  4. public static int[] input7 = new int[]{7, 49};

我将返回类型从“Iterable<object[]>”更改为“int[][]”,因为这些输入馈送到测试用例的方式略有不同。 您将在下一部分中看到不同之处。

2)用@Theory编写测试用例

从结构上讲,基于理论的类比参数化测试类简单。 类声明应使用@RunWith(Theories.class)进行注解,并且必须提供两个实体:

  1. 生成并返回测试数据的数据方法
  2. 一个理论

数据方法必须使用@DataPoints进行注解,每个理论都必须使用@Theory进行注解。 与普通的单元测试一样,每个理论都应至少包含一个断言。

在以前的方法中,我们编写了如下的测试用例:

  1. @Test
  2. public void testUserMapping() {
  3. // You can use here assert also
  4. Assert.assertEquals(resultExpected, MathUtils.square(input));
  5. }

其中inputresultExpected被声明为类成员,并使用参数化构造器进行填充。 如您所见,上面的testUserMapping()方法没有任何参数。

在新方法中,测试使用@Theory注解进行注解。 例如:

  1. @Theory
  2. public void testSquares(final int[] inputs)
  3. {
  4. Assume.assumeTrue(inputs[0] > 0 && inputs[1] > 0);
  5. Assert.assertEquals(inputs[1], MathUtils.square(inputs[0]));
  6. }

您会看到参数现在已成为测试用例的一部分,这是概念的最佳组成部分。 假定True()确保参数为正数,并且assertEquals()检查我们需要测试的函数逻辑。

要调整上述测试用例,请按以下方式用@RunWith注解类。

  1. @RunWith(Theories.class)
  2. public class JunitTestsWithParameters
  3. {
  4. //Testcases
  5. }

如果您认为某些测试用例在执行操作时可能会引发异常,请使用@Rule注解和ExpectedException类对其进行处理。 下面给出一个更完整的工作示例:

  1. package test.junit.theory;
  2. import org.junit.Assert;
  3. import org.junit.Assume;
  4. import org.junit.Rule;
  5. import org.junit.experimental.theories.DataPoint;
  6. import org.junit.experimental.theories.DataPoints;
  7. import org.junit.experimental.theories.Theories;
  8. import org.junit.experimental.theories.Theory;
  9. import org.junit.rules.ExpectedException;
  10. import org.junit.runner.RunWith;
  11. @RunWith(Theories.class)
  12. public class JunitTestsWithParameters
  13. {
  14. @Rule
  15. public ExpectedException expectedException = ExpectedException.none();
  16. @DataPoints
  17. public static int[][] integers()
  18. {
  19. return new int[][]{{1, 1}, {2, 4}, {3, 9}, {4, 16}, {5, 25}, {}};
  20. }
  21. @DataPoint
  22. public static int[] input6 = new int[]{6, 36};
  23. @DataPoint
  24. public static int[] input7 = new int[]{7, 49};
  25. @Theory
  26. public void testSquares(final int[] inputs)
  27. {
  28. Assume.assumeTrue(inputs.length == 2);
  29. Assume.assumeTrue(inputs[0] > 0 && inputs[1] > 0);
  30. Assert.assertEquals(inputs[1], MathUtils.square(inputs[0]));
  31. }
  32. @Theory
  33. public void testBlankArrays(final int[] inputs)
  34. {
  35. Assume.assumeTrue(inputs.length == 0);
  36. expectedException.expect(ArrayIndexOutOfBoundsException.class);
  37. Assert.assertEquals(inputs[1], MathUtils.square(inputs[0]));
  38. }
  39. }

运行上述测试用例,结果将如下所示:

Junit 参数化测试 – `@Theory`和`@DataPoints` - 图1

Junit 理论示例输出

请注意,将测试数据从测试/理论实现中分离出来,除了简洁以外,还可以带来另一个积极影响:您可能会开始考虑独立于要测试的实际内容的测试数据。

但是同时,您应该已经注意到,没有办法将特定结果与特定数据点配对。 当您可以以断言的形式表达数据点与预期结果之间的一般关系时,以及当该关系对于所有数据都成立时,应该使用理论。

因此,应在适当考虑的情况下在理论和参数化测试用例之间谨慎选择。 它们不是参数化测试用例的精确替代,而是它们的补充。

祝您学习愉快!