Reputation: 21513
I've found a number of question regarding renaming tests in NUnit, but none that mention how to do so while using TestFixtureSource
.
I am using the [TestFixtureSource]
attribute to configure parameterized tests, like this:
[TestFixtureSource(nameof(GetTestParams))]
public class MyTestClass
{
private Mock<IMyDependency> _mockDependency;
private TestData _data;
private MyClass _objectUnderTest;
public MyTestClass(TestData data)
{
_data = data;
}
public static IEnumerable<TestData> GetTestParams()
{
yield return new TestData(1, 2, 3);
yield return new TestData(4, 5, 9);
yield return new TestData(7, 8, 15);
}
[SetUp]
public void SetUp()
{
_mockDependency = new Mock<IMyDependency>();
_mockDependency.Setup(d => d.GetNum()).Returns(_data.A);
_objectUnderTest = new MyClass(_mockDependency.Object);
}
[Test]
public void RunTest()
{
var result = _objectUnderTest.doSomething(_data.B);
Assert.That(result, Is.EqualTo(_data.C));
}
}
public class TestData
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
public TestData(int a, int b, int c)
{
A = a;
B = b;
C = c;
}
}
public class MyClass
{
private readonly IMyDependency _dependency;
public MyClass(IMyDependency dependency)
{
_dependency = dependency;
}
public int doSomething(int b)
{
return _dependency.GetNum() + b;
}
}
public interface IMyDependency
{
int GetNum();
}
My issue is that all test cases appear to have the same name in the results. They are all simply called "RunTest", which makes it difficult to determine which tests are failing other than simply counting the number of the test and then counting my yield return
s to find the correct one.
I would love to be able to set the test name programmatically using an additional property in the TestData
class. I attempted to do this using TestContext.CurrentContext.Test.Name = _data.Name
, but it turns out this property is readonly so I can't set it.
Is there a way to rename my tests programmatically while using TestFixtureSource
?
Upvotes: 1
Views: 1423
Reputation: 3285
If I understand correctly, you currently have something like this:
but you would prefer something like this:
This is achievable by overriding the ToString()
method of the class whose type is the test fixture's parameter - TestData
in your code. For example:
public class TestData
{
<...>
public override string ToString() => $"A: {A}, B: {B}, C: {C}";
}
Doing this (with NUnit 3.8 installed) produces the sample output above.
(Caveat: Charlie led the NUnit team for about 13 years and says this can't be done, so even if I've understood the question correctly it's possible that this technique is inadvisable; use at your own risk! But I hope it helps.)
Edit: Please see comments below, especially Charlie's note that this approach should only be taken with test classes, not production classes.
Upvotes: 2
Reputation: 13746
You need to consider the sequence of execution...
*** At this point, the structure of your tests (namespaces, fixtures, test cases) is completely defined and can't be changed. Any overridden test names are already in place.
At this point, the tests start to run. In the console runner, it happens immediately. In a GUI or under VS it happens when the user clicks run. In the second case, it may happen multiple times.
Any OneTimeSetup runs
For each test in the fixture
Any OneTimeTeardown runs
Key thing here is the break between loading (aka creating or discovering) the tests and running them. Nothing can happen in steps 4 - 6 to change what was done in steps 1 and 2.
Regarding changing the name... It's a constraint within NUnit that users may only change the name of test cases. The part that comes before the test name ... including the displayed name of the fixture ... is invariable because NUnit relies on it. Changing that would give us a different framework, or at least a version of NUnit with breaking changes.
Upvotes: 1