Version: 6000.3
语言: 中文
14. 保持测试状态
16. 自定义属性

15. 测试用例

学习目标

本节将介绍[TestCase]以及类似的 NUnit 属性以及如何在 UnityTests 中使用它们。

介绍和动机

NUnit 有一些用于参数化测试的工具,可用于指定具有可变参数的测试用例。这可以大大减少重复代码的数量,并使测试更易于使用。

使用[TestCase]属性:

[Test]
[TestCase(49, "a string", true)]
[TestCase(9, "something", false)]
public void MyTest(int firstValue, string secondValue, bool expectedOutcome)
{
 ...
}  

这将生成两个测试,每个测试对方法主体的输入不同。

除了[TestCase]属性,NUnit 也有一个[Values]属性,该属性在每个单独的输入上指定一组值。例如:

[Test]
public void MyTest([Values(49, 9)]int firstValue, [Values("a string", "something")]string secondValue)
{
 ...
}  

指定多个输入参数时,它们被视为组合参数。这意味着它们的每种组合都将经过测试。对于上面的示例,这将导致总共 4 个情况:

MyTest(49, "a string")
MyTest(49, "something")
MyTest(9, "a string")
MyTest(9, "something") 

这很容易爆发成许多组合。这些组合可能并不全部有价值,只会浪费时间,因此请谨慎使用。

对于[TestCase][Values]属性,有一个更动态的版本,称为[TestCaseSource][ValueSource]因此。它们都采用静态方法或数组,返回对象的集合。

在这 4 种方法中,[ValueSource]属性是目前唯一支持的属性[UnityTest].由于这将产生组合测试,如果多个参数[ValueSource],那么如果测试需要多个参数,建议制作一个测试用例结构。这样的示例可能如下所示:

[UnityTest]
public IEnumerator AddAsyncCalculatesCorrectValue([ValueSource(nameof(TestCases))] TestCase testCase)
{
 ...
}

private static IEnumerable TestCases()
{
 yield return new TestCase {value1 = 4, value2 = "a string"};
 yield return new TestCase {value1 = 8, value2 = "another string"};
}

public struct TestCase
{
 public int value1;
 public string value2;

 public override string ToString()
 {
  return $"{value1}, {value2}";
 }
}

锻炼

示例 15_TestCases一个班级设置了一些基本的数学。它有两种方法:

  • Add它取两个整数并将它们相加。

  • AddAsync还将两个整数相加在一起,但这样做是异步的,从而返回一个IEnumerator

任务是为这两种方法添加测试。这AddAsync方法首先在几帧后返回结果,因此最适合[UnityTest].请注意,仅仅让回IEnumerator,因为测试框架目前不支持嵌套产量。相反,创建一个循环以在每个元素上移动,直到完成。在 while 循环的每个步骤中,让测试返回 null。

提示

  • ToString()结构中的实现是为了在测试运行程序测试框架包(以前称为测试运行程序)是一个 Unity 工具,可在编辑模式和播放模式下测试代码,也可以在目标平台(如独立、Android 或 iOS)上测试代码。更多信息
    请参阅术语表
    树视图。如果没有它,它只会将结构名称显示为每个情况的测试参数。

溶液

示例中提供了练习的解决方案15_TestCases_Solution.两种方法的测试可以按如下方式实现:

[Test]
[TestCase(24, 80, 104)]
[TestCase(10, -15, -5)]
[TestCase(int.MaxValue, 10, int.MinValue + 9)]
public void AddCalculatesCorrectValue(int valueA, int valueB, int expectedResult)
{
 var myClass = new MyClass();

 var result = myClass.Add(valueA, valueB);
 
 Assert.That(result, Is.EqualTo(expectedResult));
}

[UnityTest]
public IEnumerator AddAsyncCalculatesCorrectValue([ValueSource(nameof(AdditionCases))] AddCase addCase)
{
 var myClass = new MyClass();

 var enumerator = myClass.AddAsync(addCase.valueA, addCase.valueB);
 while (enumerator.MoveNext())
 {
  yield return null;
 }
 var result = enumerator.Current;
 
 Assert.That(result, Is.EqualTo(addCase.expectedResult));
}

private static IEnumerable AdditionCases()
{
 yield return new AddCase {valueA = 24, valueB = 80, expectedResult = 104};
 yield return new AddCase {valueA = 10, valueB = -15, expectedResult = -5};
 yield return new AddCase {valueA = int.MaxValue, valueB = 10, expectedResult = int.MinValue + 9};
}

public struct AddCase
{
 public int valueA;
 public int valueB;
 public int expectedResult;

 public override string ToString()
 {
  return $"{valueA} + {valueB} = {expectedResult}";
 }
}
14. 保持测试状态
16. 自定义属性