使用
Visual Studio 2019
、C#和MSTest
单元测试框架(v2.2.10)。假设我在我的 C# MSTest
项目中定义了以下模板函数:
[TestMethod]
[DynamicData(nameof(TestData_Template), DynamicDataSourceType.Method)]
public void String_DoesSomething_ExpectsSomeResult<T>(T input, string expected)
{
// Testing a template test method in MSTest (C#)
// Arrange, act, assert
string expectedLibrary = SomeLibrary.SomeFunction(input);
Assert.AreEqual(expected, expectedLibrary);
}
// Generator method
private static IEnumerable<object[]> TestData_Template()
{
// Generate some dynamic test data
yield return new object[] { (int)7, "7" }; // Integer
yield return new object[] { 0.123f, "0.123" }; // Float
}
编译很好,但是
Test Explorer
没有选择测试方法。如果我专注于 int
或 float
如下,Test Explorer
选择这些方法并且它们起作用:
[TestMethod]
[DynamicData(nameof(TestData_Int), DynamicDataSourceType.Method)]
public void String_DoesSomething_ExpectsSomeResult_Int(int input, string expected)
{
// Arrange, act and assert
string expectedLibrary = SomeLibrary.SomeFunction(input);
Assert.AreEqual(expected, expectedLibrary);
}
private static IEnumerable<object[]> TestData_Int()
{
// Dynamic test data...but this time int only
yield return new object[] { (int)7, "7" };
}
正在测试的库方法(本例中的
SomeLibrary::SomeFunction
)已正确定义并且工作正常。我想使用一个独立的生成器方法,而不是使用 DataRow
属性(MSTest
)的长组常量输入数据。
MSTest
)单元测试项目中是否可以使用模板方法?NUnit
或 xUnit
?正如其中一个答案所建议的,
DataRow
可用于提供一组恒定的测试输入数据。这对我不起作用,所以答案可能针对不同版本的 MSTest
或 Visual Studio
.
但是,
DataRow
不是我要找的。即使假设 DataRow
使用模板方法,除了小的输入数据集之外的任何东西都会很笨拙。编写详细的注释来解释输入数据的内容和原因会很混乱且无法维护。
我正在寻找一种将生成器方法与模板单元测试方法结合使用的方法,如问题所示。
是的,模板方法在 MSTest 和其他 C# 单元测试框架(如 NUnit 和 xUnit)中是可能的。
在 MSTest 中,您可以使用 DataRow 属性指定测试方法的数据。例如:
[DataTestMethod]
[DataRow(7, "7")]
[DataRow(0.123f, "0.123")]
public void String_DoesSomething_ExpectsSomeResult<T>(T input, string expected)
{
// Testing a template test method in MSTest (C#)
// Arrange, act, assert
string expectedLibrary = SomeLibrary.SomeFunction(input);
Assert.AreEqual(expected, expectedLibrary);
}
注意:不适用于 MSTest v2.2.10 或 v3.0.2.
在 NUnit 中,您可以使用 TestCase 属性指定测试方法的数据。例如:
[Test]
[TestCase(7, "7")]
[TestCase(0.123f, "0.123")]
public void String_DoesSomething_ExpectsSomeResult<T>(T input, string expected)
{
// Testing a template test method in NUnit (C#)
// Arrange, act, assert
string expectedLibrary = SomeLibrary.SomeFunction(input);
Assert.AreEqual(expected, expectedLibrary);
}
注意:在 NUnit v3.13.3 中工作,具有常量和动态输入数据集。
在 xUnit 中,您可以使用 Theory 属性和 InlineData 属性来指定测试方法的数据。例如:
[Theory]
[InlineData(7, "7")]
[InlineData(0.123f, "0.123")]
public void String_DoesSomething_ExpectsSomeResult<T>(T input, string expected)
{
// Testing a template test method in xUnit (C#)
// Arrange, act, assert
string expectedLibrary = SomeLibrary.SomeFunction(input);
Assert.Equal(expected, expectedLibrary);
}
注意:在 xUnit v2.4.2 中工作,具有常量和动态输入数据集。
如果上述解决方案对您不起作用,请告诉我。
在检查最新的C#单元测试框架后,以下关于模板方法在撰写本文时是正确的:
NUnit
v3.13.3xUnit
v2.4.2MSTest
v3.0.2@weningen-MSFT 给出了
NUnit
和 xUnit
的工作示例,其中包含一组恒定的输入数据。这个答案演示了使用生成器方法使用动态输入测试数据的相同示例:
在 NUnit v3.13.3
[Test, TestCaseSource("TestData_Template")]
public void String_DoesSomething_ExpectsSomeResult<T>(T input)
{
// Testing a template test method in NUnit with dynamic test data
// Arrange, act, assert
string expectedLibrary = SomeLibrary.SomeFunction(input);
Assert.Equal(expected, expectedLibrary);
}
private static IEnumerable<object[]> TestData_Template()
{
// Generate some dynamic test data
yield return new object[] { (int)7, "7" }; // Integer
yield return new object[] { 0.123f, "0.123" }; // Float
}
在 xUnit v2.4.2
[Theory]
[MemberData(nameof(BankAccountTestData_Template))]
public void String_DoesSomething_ExpectsSomeResult<T>(T input)
{
// Same as the NUnit example
}
public static IEnumerable<object[]> TestData_Template()
{
// Same as the NUnit example
}
虽然这在
MSTest
(2023 年 2 月的 v3.0.2)中不起作用,但微软可能会在未来的版本中让它发挥作用。