C# 访问TestCaseSource中的NUnit测试名称
我有一系列的测试,我想使用相同的测试用例数据进行一系列不同的测试 例如: 这导致了一系列的测试,报告如下:C# 访问TestCaseSource中的NUnit测试名称,c#,unit-testing,nunit,C#,Unit Testing,Nunit,我有一系列的测试,我想使用相同的测试用例数据进行一系列不同的测试 例如: 这导致了一系列的测试,报告如下: Namespace.That.Is.Very.Long.TestClass.Test1(Namespace.That.Is.Very.Long.Foo) Namespace.That.Is.Very.Long.TestClass.Test1(Namespace.That.Is.Very.Long.Foo) Namespace.That.Is.Very.Long.TestClass.
Namespace.That.Is.Very.Long.TestClass.Test1(Namespace.That.Is.Very.Long.Foo)
Namespace.That.Is.Very.Long.TestClass.Test1(Namespace.That.Is.Very.Long.Foo)
Namespace.That.Is.Very.Long.TestClass.Test2(Namespace.That.Is.Very.Long.Foo)
Namespace.That.Is.Very.Long.TestClass.Test2(Namespace.That.Is.Very.Long.Foo)
…如果你不知道“foo”失败了什么,这就没有多大意义
如果我这样设置名称:
data = new TestCaseData(new Foo("aaa"));
data.SetName("foo=aaa");
yield return data;
foo=aaa
foo=bbb
foo=aaa
foo=bbb
…然后我所有的测试结果都是这样的:
data = new TestCaseData(new Foo("aaa"));
data.SetName("foo=aaa");
yield return data;
foo=aaa
foo=bbb
foo=aaa
foo=bbb
因此,我试图找出如何获得当前的测试方法名。这似乎是通过TestContext完成的
但是,当TestContext.Current.Test存在时,所有属性(如Name)在尝试访问它们时都会引发NullReferenceException
是否有其他方法可以实现在测试名称中提供更多有用信息的目标?如何
[TestCase("aaa")]
[TestCase("bbb")]
public void MainTest(string str)
{
Assert.DoesNotThrow(()=> Test1(new Foo(str)));
Assert.DoesNotThrow(()=> Test2(new Foo(str)));
}
public void Test1(Foo foo)
{
// test 1
}
public void Test2(Foo foo)
{
// test 2
}
UPD:
这不是一个完美的答案,但到目前为止,我找到的最好的解决方案是为TestData发射器创建一个包装器,作为TestCaseSource传入
[Test, TestCaseSource("TestData_Test1")]
public void Test1(Foo foo)
{
// test 1
}
[Test, TestCaseSource("TestData_Test2")]
public void Test2(Foo foo)
{
// test 2
}
private static IEnumerable TestData_Test1()
{
return TestData_Base("Test1");
}
private static IEnumerable TestData_Test2()
{
return TestData_Base("Test2");
}
private static IEnumerable TestData_Base(string testName)
{
TestCaseData data;
data = new TestCaseData(new Foo("aaa"));
data.SetName(string.Format("{0}(Foo=aaa)", testName));
yield return data;
data = new TestCaseData(new Foo("bbb"));
data.SetName(string.Format("{0}(Foo=bbb)", testName));
yield return data;
}
这意味着我的测试现在由NCrunch、TeamCity等发出
Test1(Foo=aaa)
Test1(Foo=bbb)
Test2(Foo=aaa)
Test2(Foo=bbb)
这至少比完全无用的违约要好 好吧,如果您幸运地使用了.NET 4.5,您可以在扩展TestCaseSource的新TestCaseSourceX属性的构造函数的最后一个参数上使用[CallerMemberName]属性,这将在属性构造函数中为您提供测试方法名 以下是一个工作示例:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TestCaseSourceEx : TestCaseSourceAttribute
{
public TestCaseSourceEx(Type sourceType, string sourceName, [CallerMemberName] string methodName = null)
: base(sourceType, sourceName)
{
}
public TestCaseSourceEx(string sourceName, [CallerMemberName] string methodName = null)
: base(sourceName)
{
}
}
[TestFixture]
public class SampleTests
{
public IEnumerable List = new[] { new string[] { "test-username", "test-password" } };
[Test, TestCaseSourceEx("List")]
public void SampleTests_LoginTest(string username, string password)
{
}
}
经过长时间的谷歌搜索,我找到了比上面发布的解决方案简单得多的解决方案: 第一。在测试用例中,我添加了另一个参数:string testName:
[Test, TestCaseSource("TestData")]
public void Test1(string testName, Foo foo)
{
// test 1
}
[Test, TestCaseSource("TestData")]
public void Test2(String testName, Foo foo)
{
// test 2
}
第二。在TestCaseData中,我添加了另一个参数,它显示了Foo对象的唯一属性,例如name
private static IEnumerable TestData()
{
TestCaseData data;
Foo data1 = new Foo("aaa");
data = new TestCaseData(data1.name, data1);
yield return data;
Foo data2 = new Foo("bbb");
data = new TestCaseData(data2.name, data2);
yield return data;
}
在NUnit runner中,结果如下所示:
Namespace.That.Is.Very.Long.TestClass.Test1("aaa", Namespace.That.Is.Very.Long.Foo)
Namespace.That.Is.Very.Long.TestClass.Test1("bbb", Namespace.That.Is.Very.Long.Foo)
这使得测试在输出窗口中独立,而我仍然能够准确地看到正在运行的测试。属性
TestName
在NUnit 3中支持字符串格式设置
下面是一个示例用法:
private static IEnumerable TestData()
{
TestCaseData data;
data = new TestCaseData(new Foo("aaa"))
.SetName("case 1 {m}");
yield return data;
data = new TestCaseData(new Foo("bbb"));
yield return data;
}
将生成以下输出:
如您所见,第一个案例的测试名称包含自定义前缀+方法名称
有关NUnit的字符串格式化功能的更多信息,请使用
2个类可负责此操作和
TestNameGenerator
方法.GetDisplayName()
您不使用失败的断言提供的信息、缺少异常等的原因是什么?我可以使用失败的断言提供的信息,但它不会告诉我提供了什么测试用例数据。此外,在TeamCity等CI平台上,具有相同输出名称的测试用例被聚合并显示为一个。“Test{x}运行了7次,失败了1次”(或类似的)@JamesFaix对我来说,TestContext.CurrentContext.Test.Name
工作正常,在所提供的案例中输出foo=aaa
,所以我认为这是固定的。因此,您可以只使用SetName
+TestContext.CurrentContext.Test.Name
。这可能是版本上的差异。我在NUnit3.6上。从我尝试过的每个实验来看,当测试运行者读取测试用例列表时,测试上下文数据不可用。在测试开始之前读取案例,因此还没有任何测试上下文。您可以访问TestContext.CurrentContext
,但大多数属性都为null,在这种特殊情况下,我在尝试引用测试用例列表属性中的TestContext.CurrentContext.Test.Name
时会遇到NullReferenceException
。可能还取决于运行程序。我使用了Resharpers测试运行程序和nuget包中的最新版本nunit(我想是3.7.1)。它正确显示所有测试名称,并且Console.WriteLine(TestContext.CurrentContext.test.Name)
将测试名称写入输出,没有任何异常。PS:刚降级到3.6.0,它在Resharper runner上仍然可以正常工作。这只会让我一次看到一个测试失败。是的,这不是你想要的。根据我在单元测试方面的经验,最佳实践是使单元测试尽可能明确。即使这意味着在不同的测试中重复一些代码。我知道这听起来有悖直觉,但在测试中,我更喜欢看一个测试,并了解那里发生了什么。因此,按照这个建议,您可以为每个测试复制测试用例。我编辑了答案。我们不使用TestCase,因为我们想要传递的实际内容更复杂(在本例中,是一个方法委托,但原则是用于无法在属性中传递的内容)。我添加了一个答案,其中显示了我实际使用的解决方法。这不太好,但比我找到的其他选择要好。谢谢——在为这个问题绞尽脑汁两天后,我也这样做了。这是对测试用例参数的滥用,如果许多测试使用相同的数据源,可能需要对测试用例签名进行大量更改,但在没有任何其他有效方法的情况下,它对我有效。您可以从要测试的Foo
实例的静态列表开始,然后在TestData\u-Base
方法中使用它从它们生成TestCaseData
实例。这将减少必须在Foo构造函数和SetName
方法中指定“aaa”的重复。(请参阅)我看不出这如何帮助您将methodName
放入TestCaseData Name属性中……除非我遗漏了一些明显的内容??CallerMemberName属性参数引入了方法名称。在4.5中引入。以前唯一的选择是深入调用堆栈。如果您观察代码,我们不会调用构造函数参数,它是由运行时调用的。我理解这一部分,我不理解的是,现在TestCaseSourceAttribute类中有可用的methodName
,我如何使用它来设置测试的名称?据我所知,我需要c