Often times, you find yourself in writing data-driven tests in xUnit (like Theory
tests) and you want to add a description to each test case. Let's explore how to do that.
The problem
Let's imagine you have a test as such:
[Theory]
[MemberData(nameof(InvalidFilters))]
public async Task ShouldNotAllowInvalidInvariants(LimitDesignerFilters filters)
...
public record LimitDesignerFilters(
string Description,
Guid? WorkpieceNumber,
IReadOnlyCollection<int>? DressingIds,
IReadOnlyCollection<int>? DressingTools,
IReadOnlyCollection<int>? LimitIds);
If we execute the test, then we get something like this in the test runner:
As we see it is really hard to understand what each test case is about, especially given that we have some collections and thanks to the record
this will internally use the ToString()
method to display the values. So - we can exactly use that to our advantage.
The solution - overriding ToString()
To make the test runner display a more meaningful description, we can override the ToString()
method in our LimitDesignerFilters
record. This way, we can format the output to be more readable and informative. So let's add a description field and override the ToString()
method:
public record LimitDesignerFilters(
string Description,
Guid? WorkpieceNumber,
IReadOnlyCollection<int>? DressingIds,
IReadOnlyCollection<int>? DressingTools,
IReadOnlyCollection<int>? LimitIds)
{
public override string ToString() => Description;
}
So we can set the Description
field to a meaningful value for each test case:
public static TheoryData<LimitDesignerFilters> InvalidFilters =>
[
new("Workpiece is null", null, [1], [1], [1]),
new("Param1 is null", Guid.NewGuid(), null, [1], [1]),
];
Still "filters" as the name of the passed in parameter is still there, but at least a better name.