我想编写一个可调用函数,它接受两个对象,并将这些对象的 30 多个属性与断言进行比较。问题是这需要对大约 20 个现有的单元测试和大多数未来的测试进行,并且每次写出 30 多个断言既费时又费空间。
我目前有一个非单元测试函数,可以比较对象,并返回带有“通过”或失败消息的字符串,并使用断言在每个单元测试中验证它。然而,它非常混乱,我觉得我正在违背正确的单元测试方法。
有没有办法创建一个可从单元测试内部调用的函数,并使用断言来检查条件?
如果您使用的是 NUnit 2.5.5 或更高版本,则可以使用 TestCase 属性。
普通的单元测试会用 [Test] 修饰,但我们可以将其替换为:
[TestCase("0", 1)]
[TestCase("1", 1)]
[TestCase("2", 1)]
public void UnitTestName(string input, int expected)
{
//Arrange
//Act
//Assert
}
这种类型的事情将是做到这一点的方法 - 显然采用不同的参数。
查看以下内容寻求帮助:http://nunit.org/?p=testCase&r=2.5
为了回答最后一部分,您当然可以在另一个函数中使用断言。断言通过引发测试运行程序捕获的异常来工作,并将其解释为失败,因此像这样进行测试会正常工作:
public void CheckAsserts(string value)
{
Assert.IsNotNull(value);
}
[TestCase("yes!")]
public void MyTest(string value)
{
CheckAsserts(value);
}
您可以使用
TestCase
属性:
[TestCase("hostname1parameter")]
[TestCase("hostname2parameter")]
public void Example_TestHostName(string hostname)
{
...
}
您需要 TestCase 属性:
[TestCase("string1",...)
public void test_UnitTest(string Parameter)
{
...
Assert.AreEqual(Parameter, result)
}
请注意,这仅适用于字符串和整数等基本数据类型 - 您无法实例化自己的类并将其用作参数。
NUnit [TestCase] 属性提供使用一组不同的参数运行单个测试,您不必为每个参数编写单独的测试。假设我们有以下类并想要测试
IsLatitudeValid()
方法:
public class CoordinateValidator
{
public bool IsLatitudeValid(double latitude)
{
return latitude is >= -90 and <= 90;
}
public bool IsLongitudeValid(double longitude)
{
return longitude is >= -180 and <= 180;
}
}
我们可以使用以下测试方法:
[TestCase(-90, true)]
[TestCase(0, true)]
[TestCase(10, true)]
[TestCase(90, true)]
[TestCase(-91, false)]
[TestCase(91, false)]
public void TestLatitude(double latitude, bool expected)
{
// ARRANGE
var validator = new CoordinateValidator();
// ACT
bool valid = validator.IsLatitudeValid(latitude);
// ASSERT
Assert.AreEqual(expected, valid);
}
这种参数化测试一开始有点令人困惑,但诀窍是提供一个带有输入和输出/预期参数的测试方法(上述)。请注意,
[TestCase]
属性和方法参数的数据类型(即 double 和 bool)必须匹配,并且我们测试有效值和无效值。
对于更高级的参数化测试,您可以查看 NUnit 文档中的 [TestCaseSource] 和 [ValueSource] 属性。
您还可以从使用 C# 内省中受益。这允许您获取字段的名称,而无需在代码中指定它们。然后您可以通过名称调用它们。
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t);
这允许您编写某些类型的测试,这些测试将适用于您尚未编写的类。