Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share state between tests that run in parallel with XUnit.net

Tags:

xunit.net

I have a set of xunit.net tests that need to share state. Hopefully, I would like these tests to run in parallel. So I would want the runner to do:

  • Create the shared fixture
  • Run in parallel all the tests using that fixture

When reading the the xunit doc, it says that to share state between test classes, I need to define a 'collection fixture' and then but all my test classes into that new collection (ex: [Collection("Database collection")]). But when, I put my test class in the same fixture, they don't run in parallel anymore so it beats the purpose :(

Is there a built-in way to do what I want in XUnit?

My fallback will be to put my shared state into a static class.

like image 206
mabead Avatar asked Jan 26 '17 17:01

mabead


People also ask

Does xUnit run tests in parallel?

Running unit tests in parallel is a new feature in xUnit.net version 2. There are two essential motivations that drove us to not only enable parallelization, but also for it to be a feature that's enabled by default: As unit testing has become more prevalent, so too have the number of unit tests.

Do xUnit tests run in order?

Each test class is a unique test collection and tests under it will run in sequence, so if you put all of your tests in the same collection then it will run sequentially.

Which is better xUnit or NUnit?

MSTest is concerned, the biggest difference between xUnit and the other two test frameworks (NUnit and MSTest) is that xUnit is much more extensible when compared to NUnit and MSTest. The [Fact] attribute is used instead of the [Test] attribute.

Does xUnit create a new instance for each test?

For every test, xUnit creates a new instance of the test class, which implies that the codes in the class constructor are run for each test. Oftentimes, it is desirable for unit test classes to share a test context because it can be expensive to create and clean up test contexts.


1 Answers

You can extend xUnit using the AssemblyFixture example from the samples pasted below to create a fixture which can the accesses by tests while running in parallel.

Using this method the fixture is created before the tests and then injected into the tests which reference it. I use this to create a user which is then shared for that specific set run.

There is also a nuget package xunit.assemblyfixture:

using System;
using Xunit;

// The custom test framework enables the support
[assembly: TestFramework("AssemblyFixtureExample.XunitExtensions.XunitTestFrameworkWithAssemblyFixture", "AssemblyFixtureExample")]

// Add one of these for every fixture classes for the assembly.
// Just like other fixtures, you can implement IDisposable and it'll
// get cleaned up at the end of the test run.
[assembly: AssemblyFixture(typeof(MyAssemblyFixture))]

public class Sample1
{
    MyAssemblyFixture fixture;

    // Fixtures are injectable into the test classes, just like with class and collection fixtures
    public Sample1(MyAssemblyFixture fixture)
    {
        this.fixture = fixture;
    }

    [Fact]
    public void EnsureSingleton()
    {
        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);
    }
}

public class Sample2
{
    MyAssemblyFixture fixture;

    public Sample2(MyAssemblyFixture fixture)
    {
        this.fixture = fixture;
    }

    [Fact]
    public void EnsureSingleton()
    {
        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);
    }
}

public class MyAssemblyFixture : IDisposable
{
    public static int InstantiationCount;

    public MyAssemblyFixture()
    {
        InstantiationCount++;
    }

    public void Dispose()
    {
        // Uncomment this and it will surface as an assembly cleanup failure
        //throw new DivideByZeroException();
    }
}
like image 110
J.D. Cain Avatar answered Oct 16 '22 06:10

J.D. Cain