Testing "ALL" Scenarios with xUnit
Tags: csharp, testing, software, dotnet
Published: 2020-05-19 23:29:05

## Extending xUnit

If you've used xUnit, you've probably also used some other libraries that work well with it, or even add to its functionality. I've been using an extension library for a few years now and it's constantly in my tool-belt.

## Examples from [Xunit.Combinatorial](https://github.com/AArnott/Xunit.Combinatorial)

Suppose you have this test method:

```csharp
[Fact]
public void CheckFileSystem(bool recursive)
{
    // verifications here
}
```

To arrange for your test method to be invoked twice, once for each value
of its bool parameter, change the attributes to 

```csharp
[Theory, CombinatorialData]
public void CheckFileSystem(bool recursive)
{
    // verifications here
}
```

The `CombinatorialDataAttribute` will supply Xunit with both `true` and `false`
arguments to run the test method with, resulting in two invocations of your 
test method with individual results reported for each invocation.

To supply your own values to pass in for each parameter, use the
`CombinatorialValuesAttribute`:

```csharp
[Theory, CombinatorialData]
public void CheckValidAge([CombinatorialValues(5, 18, 21, 25)] int age)
{
    // verifications here
}
```

This will run your test method four times with each of the prescribed values.

### Extending Xunit.Combinatorial

Another library I've used for many years that always gets the job done is [Enumeration](https://github.com/HeadspringLabs/Enumeration) from [Headspring](https://headspring.com/open-source/).

By extending the `CombinatorialValuesAttribute` class, you can easily make a test method that injects every single Enumeration into your your test method.

If given this [Enumeration sample from GitHub](https://github.com/HeadspringLabs/Enumeration#helpful-query-methods)

```csharp
public class Role : Enumeration<Role, int>
{
    public static readonly Role System = new Role(999, "System", "System", true);
    public static readonly Role Manager = new Role(1, "Manager", "Michelle", false);
    public static readonly Role Employee = new Role(2, "Employee", "Eric", false);
    public static readonly Role HR = new Role(3, "Human Resources", "Harry", false);

    private Role(int value, string displayName, string personaName, bool testrole)
        : base(value, displayName)
    {
        PersonaName = personaName;
        TestRole = testrole;
    }

    public string PersonaName { get; private set; }
    public bool TestRole { get; private set; }

    public static IEnumerable<Role> GetAllProductionRoles()
    {
        return GetAll().Where(r => !r.TestRole);
    }
}
```

... we could create two small types that let us test the different roles, and make different assertions.

```csharp
public class AllRolesAttribute : CombinatorialValuesAttribute
{
    public AllRolesAttribute() :
        base(Role.GetAll())
    {
    }
}

public class AllProductionRolesAttribute : CombinatorialValuesAttribute
{
    public AllProductionRolesAttribute()
        :base(Role.GetAllProductionRoles().ToArray())
    {
    }
}
```

Pretty simple, yeah? But this now readily lets us [TEST ALL THE THINGS](https://knowyourmeme.com/memes/all-the-things):

```csharp
public class RolesTests
{
    [Theory]
    [CombinatorialData]
    public void Some_test_for_all_Roles([AllRoles] Role role)
    {
        // test method will execute for each role in the Enumeration
    }

    [Theory]
    [CombinatorialData]
    public void Some_test_for_all_production_Roles([AllProductionRoles] Role role)
    {
        // test method will execute for each non-test role in the Enumeration
    }
}
```

That's about it, if you have questions or want to chat more, please reach out!