Reputation:
I have a series of tests where I want to use the same testcase data for a bunch of different tests.
eg:
[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;
}
This leads to a series of tests that report like so:
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)
...which isn't hugely meaningful when you don't know what 'foo' failed..
If as suggested in this SO question I set the name like this:
data = new TestCaseData(new Foo("aaa"));
data.SetName("foo=aaa");
yield return data;
...then all my tests come out looking like this:
foo=aaa
foo=bbb
foo=aaa
foo=bbb
So I'm trying to figure out how to get the current test method name. That would appear, as described in this other SO question be done via TestContext.
However, while TestContext.Current.Test exists, all the properties (like Name) throw a NullReferenceException when trying to access them.
Is there some other way to achieve this goal of providing more useful information in the test name?
Upvotes: 31
Views: 20619
Reputation: 8725
The property TestName
has a support in NUnit 3 for string formatting.
Here's an example usage:
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;
}
Will generate the following out put:
As you can see the test names the of the first case contains the custom prefix + the method name.
Use this link for more information about NUnit's string formating capability.
2 classes are resposable for this action NUnitTestCaseBuilder (line 83) and TestNameGenerator
method .GetDisplayName()
.
Upvotes: 55
Reputation: 19
After long googling i've found my solution which was alot easier than those posted above:
1st. In test case I've added another parameter: 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
}
2nd. in TestCaseData I've added another parameter which shows unique property of Foo object eg. 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;
}
In NUnit runner the result are displayed like this:
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)
This makes tests separate in output window, while i'm still able to see exactly which test is being runned.
Upvotes: 1
Reputation: 138
Well, if you are lucky to use .NET 4.5, you can use the [CallerMemberName] attribute on the last argument of the constructor of a new TestCaseSourceEx attribute extending TestCaseSource, which will give you the test method name inside the attribute constructor.
Here's a working sample:
[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)
{
}
}
Upvotes: 1
Reputation:
This isn't a perfect answer, but the best solution I've found so far is that I create a wrapper for the TestData emitter that gets passed in as the 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;
}
This means that my tests are now emitted from NCrunch, TeamCity, etc as
Test1(Foo=aaa)
Test1(Foo=bbb)
Test2(Foo=aaa)
Test2(Foo=bbb)
Which is at least better than the completely useless default.
Upvotes: 1
Reputation: 3099
How about this?
[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
}
Upvotes: -1