Useful attributes for xUnit

xUnit lacks useful functionalities, but the strength of a good framework is that one can easily implement needed features. Today I would like to present two examples, that I found useful in everyday work.

Repeating tests

There are different opinions on non-deterministic tests, some say that it is the rule that the tests should always have the same results, but for me, random seed for data in tests is an opportunity to find edge cases, that we haven't considered. It's one step closer to property testing known from QuickCheck. When I worked in NUnit I used RepeatAttribute for this, in xUnit there is no builtin, so we can provide it on our own.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class RepeatAttribute : DataAttribute
{
    private readonly int _count;

    public RepeatAttribute(int count)
    {
        if (count < 1)
        {
            throw new ArgumentOutOfRangeException(nameof(count),
                    "Repeat count must be greater than 0.");
        }
        _count = count;
    }

    public override IEnumerable<object[]> GetData(MethodInfo testMethod)
    {
        return Enumerable.Repeat(Array.Empty<object>(), _count);
    }
}

Timeout

Tests usually should be fast, but occasionally bugs that cause tests to hang up are introduced. Even worse if it occurs not locally, but in CI pipeline - we block the worker for no reason, instead of failing fast. For this case, where in NUnit we could use TimeoutAttribute, in xUnit there already is such an option available inside FactAttribute (and TheoryAttribute that inherits from it).

Test parallelization for the collection that the test is running in must be disabled for this to work as expected. More information how to proceed https://xunit.net/docs/running-tests-in-parallel
[Fact(Timeout = 1000)]
public async Task LongRunningTest()
{
    await Task.Delay(2000);
}

Sources