The*_*des 4 c# nunit unit-testing
我正在使用nunit在C#中编写一些单元测试.请考虑以下代码:
[Test ()]
public void TestCarCost () {
for (int i = 0; i < Examples.exampleCount; i++) {
Car car = new Car(Examples[i]);
Assert.AreEqual (car.getCost (), Examples[i].cost, "Test " + (i + 1) + " failed");
}
}
Run Code Online (Sandbox Code Playgroud)
假设Examples是一个带有一些静态数据的类,用于测试汽车类型的不同可能输入,你可以看到我试图测试car.getCost()函数中的任何错误.现在在循环中使用它会在某种程度上感觉不对,因为例如当任何断言失败时它总是会将您发送到同一行代码.此外,据我所知,只要[Test()]中的断言失败,nunit会立即终止其余的测试代码.这意味着如果我在循环中拥有所有内容并且断言nr 1失败,我不会看到其他断言是否失败.明确地编写所有测试本质上是编写copypeasted代码,所以它也感觉不对.在这种情况下,什么是良好做法?是否可以在单元测试中使用大量类似的代码?我缺少一些优雅的解决方案吗?
NUnit内置了对参数化测试的支持.如果你的示例数据很简单(即值可以出现在属性中,比如a string),那么你的测试可以使用TestCase属性,看起来像这样:
[TestCase("Example Value 1", ExpectedResult=123.4)]
[TestCase("Example Value 2", ExpectedResult=567.8)]
[TestCase("Example Value 3", ExpectedResult=901.2)]
public void TestCarCost (string exampleValue) {
Car car = new Car(exampleValue);
return car.GetCost();
}
Run Code Online (Sandbox Code Playgroud)
如果您的示例值(实际上是测试输入)不能出现在属性中,您可以使用TestCaseSource属性来指示将为您提供值的成员:
[TestCaseSource(nameof(Examples))]
public void TestCarCost (ExampleInput exampleValue) {
Car car = new Car(exampleValue);
return car.GetCost();
}
public IEnumerable<ITestCaseData> Examples {
get {
yield return new TestCaseData(new ExampleInput(1,2)).Returns(123.4);
yield return new TestCaseData(new ExampleInput(3,4)).Returns(567.8);
yield return new TestCaseData(new ExampleInput(5,6)).Returns(901.2);
}
}
Run Code Online (Sandbox Code Playgroud)
最好使用TestCaseAttribute替代循环.请在以下链接中阅读更多信息.
在你的情况下应该是:
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
public void TestCarCost (int id)
{
Car car = new Car(Examples[id]);
Assert.AreEqual (car.getCost (), Examples[id].cost, "Test " + (i + 1) + " failed");
}
Run Code Online (Sandbox Code Playgroud)
在这里,您可以为单个测试方法创建多个测试用例.对于每个测试用例,您可以在TestCase()属性中提供参数并传递id给您的测试方法.
基于id您可以访问您的资源`示例[id].
我宁愿使用这种方式,因为我可以监控每个案例,而且不需要额外的逻辑.
此外,如果您在单元测试中添加其他逻辑,则会增加失败的可能性,并且您将依赖于该逻辑的准确性.
| 归档时间: |
|
| 查看次数: |
1117 次 |
| 最近记录: |