2023/11/05 - Coenraad Stijne
Summary:
MSTestandNUnitsupport greater levels of Parallelism Granularity thenxUnit.- When
NUnitis configured to useMethod, the documentation recommends changing theTest Classinstantiation behavior fromSingle InstancetoInstance Per Testfor thread safety.
Personal Learnings:
MSTestandNUnitboth supportctor/disposepattern tosetup/teardowntests, similar toxUnit.
Code Examples
Framework Overview
| Framework | Version | Default Parallelism | Maximum Parallelism |
|---|---|---|---|
| MSTest | 3.1.1 | None | Method |
| NUnit | 4.5.0 | None | Method |
| xUnit | 2.6.1 | Collection (class) | Collection (class) |
Note: When using Method level of parallelism, it is the developer’s responsibility to ensure the tests are thread safe.
Configuring MSTest
ParallelizeAttribute Documentation
The Parallelize attribute can be set to configure the default strategy.
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
This will parallelize all methods, including DataRow and DynamicData.
✅ Thread Safety:
MSTest creates a new instance per test by default. Unless using static, fields/properties will be thread safe.
Configuring NUnit
ParallelizableAttribute Documentation
FixtureLifeCycle Documentation
The Parallelizable attribute can be set to configure the default strategy.
NUnit also recommends to set the FixtureLifeCycle attribute.
[assembly: Parallelizable(ParallelScope.Children)]
[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
This will parallelize all methods, including TestCase and TestCaseSource.
⚠️ Thread Safety:
The FixtureLifeCycle attribute was added so that NUnit will create a new instance of the test class for each test method executed.
This is to ensure that fields/properties of the class will not be accessed by multiple tests at the same time.
Important Notes about FixtureLifeCycle:
-
When using
LifeCycle.InstancePerTestCase, theOneTimeSetUpandOneTimeTearDownmethods must bestatic, and each are only called once. This is required so that thesetuporteardownmethods do not access instance fields or properties that are reset for every test. -
When using
LifeCycle.InstancePerTestCase, a class’sconstructorwill be called before every test is executed andIDisposabletest fixtures will be disposed after the test is finished. -
SetUpandTearDownmethods are called before and after every test. -
The
Orderattribute is respected.
Configuring xUnit
xUnitdoes not support method level parallelism natively- It is being considered for
v3, see the Roadmap - There is a community solution, see https://github.com/xunit/xunit/issues/1986#issuecomment-1028299919
- Since it is not officially supported, it will not be covered in this post