Skip to content

Taking control over xUnit test names

Unit Testing naming conventions are almost as conflicting as spaces versus tabs. I've never worked on a project where everyone has the same preferences.

Often, you even find multiple practices in the same codebase. They go from Given_When_Then to MethodUnderTest_Scenario_ExpectedResult or even variances where one person may use Pascal and another Snake case.

Often, we forget that the most important thing is expressing clearly the test intent. So, it's the question of how to make the most of those shapes or forms.

xUnit Test name customization

The good news is that you have some ways to control xUnit behaviour in terms of test display names.

The simplest one is defining a custom Display Name through the Fact attribute.

[Fact(DisplayName = "Get the max number of an array")]
public void GivenAnArray_WhenApplyMax_ThenGetThenBiggerOne()
{
new[] { 12, 10, 20, 42 }
.Max()
.Should()
.Be(42);
}

That will give you a higher degree of freedom, but it's an extra effort, difficult to keep consistent across the code. We already need to craft a meaningful method name, so having an extra-label may lead to out of sync text. We already know what happens to code comments. We don't need to deal with the same problem in tests.

So, what can we do?

One interesting thing from xUnit is the configuration files.

There, you can find many options to change the default behaviours of xUnit. One of them is related to Display Name.

xUnit in .net will display names based on class and method name by default. With the configuration file, you can define the display name to be the Method name.

To do it, create a xunit.runner.json file in the xUnit project root, make sure it's included and add the following snippet.

{
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
"methodDisplay": "method"
}

To include, add to the csproj:

<ItemGroup>
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Besides that, the most interesting thing is the method display name options, where you can find options to:

  • Replace underscores with spaces;
  • Replace operators with matching symbols (example: eq becomes =);
  • Replace periods with a comma and a space.

To enable them, go to the xunit.runner.json file and add a new key.

"methodDisplayOptions": "replaceUnderscoreWithSpace,useOperatorMonikers"

So, for the following tests:

public class DisplayNameTests
{
[Fact]
public void Given10_WhenMultiplyBy2_ThenGet20()
{
var result = 10 * 2;

result.Should().Be(20);
}

[Fact]
public void Is_20_gt_10()
{
20.Should().BeGreaterThan(10);
}
}

Once you run the tests, you will see:

xUnit / Result after changing method display name configuration

Instead of:

xUnit / Result before changing method display name configuration

Wrapping up

I don't say you must use this, but knowing that these features exist may be helpful to improve the readability of your tests when analysing the results. In some cases, the existing conventions may help achieve better results, like if you are using Snake casing, enabling the "replaceUnderscoreWithSpace" is a quick improvement.

Now it's time to take a look into your codebase, look into the existing configuration options, and you may find a quick win.

🔗 You can find the source code used here.

I hope that this was useful! To get more tips like this, follow me on Twitter (@gsferreira) and let's keep in touch!