我有一系列测试,我想在一堆不同的测试中使用相同的测试用例数据。
例如:
[Test, TestCaseSource("TestData")]
public void Test1(Foo foo)
{
// test 1
}
[Test, TestCaseSource("TestData")]
public void Test2(Foo foo)
{
// test 2
}
private static IEnumerable TestData()
{
TestCaseData data;
data = new TestCaseData(new Foo("aaa"));
yield return data;
data = new TestCaseData(new Foo("bbb"));
yield return data;
}
这会导致一系列测试报告如下:
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'失败时,这并没有多大意义..
如果as suggested in this SO question我将名称设置为:
data = new TestCaseData(new Foo("aaa"));
data.SetName("foo=aaa");
yield return data;
...然后我的所有测试看起来都像这样:
foo=aaa
foo=bbb
foo=aaa
foo=bbb
所以我想弄清楚如何获取当前的测试方法名称。看来,as described in this other SO question可以通过TestContext完成。
但是,当TestContext.Current.Test存在时,所有属性(如Name)在尝试访问它们时都会抛出NullReferenceException。
是否有其他方法可以实现在测试名称中提供更多有用信息的目标?
答案 0 :(得分:25)
属性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;
}
将产生以下输出:
如您所见,第一个案例的测试名称包含自定义前缀+方法名称。
使用this link了解有关NUnit的字符串格式化功能的更多信息。
此行为NUnitTestCaseBuilder (line 83)和TestNameGenerator
方法.GetDisplayName()
可以使用2个类。
答案 1 :(得分:1)
这不是一个完美的答案,但到目前为止我找到的最佳解决方案是我为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)
这至少比完全无用的默认值更好。
答案 2 :(得分:1)
好吧,如果你幸运使用.NET 4.5,你可以在扩展TestCaseSource的新TestCaseSourceEx属性的构造函数的最后一个参数上使用[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)
{
}
}
答案 3 :(得分:1)
经过长时间的谷歌搜索后,我发现我的解决方案比上面发布的解决方案更容易:
第一。在测试用例中,我添加了另一个参数:string testName:
+
第二。在TestCaseData中我添加了另一个参数,它显示了Foo对象的唯一属性,例如。名称
"script": "doc['userPermissions.id'].values + doc['pSPermissions.id'].values",
在NUnit跑步者中,结果显示如下:
[Test, TestCaseSource("TestData")]
public void Test1(string testName, Foo foo)
{
// test 1
}
[Test, TestCaseSource("TestData")]
public void Test2(String testName, Foo foo)
{
// test 2
}
这使测试在输出窗口中分开,而我仍然能够确切地看到正在运行的测试。
答案 4 :(得分:-1)
这个怎么样?
[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:
[TestCase("aaa")]
[TestCase("bbb")]
public void Test1(string str)
{
var foo = new Foo(str);
// rest of the test
}
[TestCase("aaa")]
[TestCase("bbb")]
public void Test2(string str)
{
var foo = new Foo(str);
// rest of the test
}