Repository navigation
[Bug]: Keyed NotInParallel tests bypass the max parallelism cap #7074
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Bug report checklist
- I've searched existing issues to ensure this isn't a duplicate
- I've read the documentation and this isn't expected behavior
- I'm using the latest version of TUnit
Description
Tests with distinct NotInParallel constraint keys ignore the global parallelism cap. Unkeyed tests and [ParallelGroup] tests respect it, so the problem is specific to the NotInParallel constraint scheduler. Suspected cause: ConstraintKeyScheduler never applies GetMaxParallelism.
An explicit [assembly: ParallelLimiter<...>] does constrain keyed tests, so that is the current workaround.
Expected Behavior
all three classes stay at <= 2 concurrent tests.
Actual Behavior
UnkeyedTests and GroupedTests pass. KeyedTests fails with max concurrent = 8 (every key runs at once).
Steps to Reproduce
Run and compare:
dotnet run -- --maximum-parallel-tests 2dotnet run
public sealed class ConcurrencyProbe
{
int _current, _max;
public async Task Run()
{
var now = Interlocked.Increment(ref _current);
int seen;
while (now > (seen = Volatile.Read(ref _max)))
Interlocked.CompareExchange(ref _max, now, seen);
await Task.Delay(500);
Interlocked.Decrement(ref _current);
}
public int Max => Volatile.Read(ref _max);
}
// Control 1: no constraints
public class UnkeyedTests
{
static readonly ConcurrencyProbe P = new();
[Test] public Task T1() => P.Run();
[Test] public Task T2() => P.Run();
[Test] public Task T3() => P.Run();
[Test] public Task T4() => P.Run();
[Test] public Task T5() => P.Run();
[Test] public Task T6() => P.Run();
[Test] public Task T7() => P.Run();
[Test] public Task T8() => P.Run();
[After(Class)]
public static void Check()
{
if (P.Max > 2) throw new Exception($"Unkeyed max concurrent = {P.Max}, expected <= 2");
}
}
// Control 2: keyed via ParallelGroup
[ParallelGroup("Group1")]
public class GroupedTests
{
static readonly ConcurrencyProbe P = new();
[Test] public Task T1() => P.Run();
[Test] public Task T2() => P.Run();
[Test] public Task T3() => P.Run();
[Test] public Task T4() => P.Run();
[Test] public Task T5() => P.Run();
[Test] public Task T6() => P.Run();
[Test] public Task T7() => P.Run();
[Test] public Task T8() => P.Run();
[After(Class)]
public static void Check()
{
if (P.Max > 2) throw new Exception($"Grouped max concurrent = {P.Max}, expected <= 2");
}
}
// Bug: distinct NotInParallel keys
public class KeyedTests
{
static readonly ConcurrencyProbe P = new();
[Test, NotInParallel("k1")] public Task T1() => P.Run();
[Test, NotInParallel("k2")] public Task T2() => P.Run();
[Test, NotInParallel("k3")] public Task T3() => P.Run();
[Test, NotInParallel("k4")] public Task T4() => P.Run();
[Test, NotInParallel("k5")] public Task T5() => P.Run();
[Test, NotInParallel("k6")] public Task T6() => P.Run();
[Test, NotInParallel("k7")] public Task T7() => P.Run();
[Test, NotInParallel("k8")] public Task T8() => P.Run();
[After(Class)]
public static void Check()
{
if (P.Max > 2) throw new Exception($"Keyed max concurrent = {P.Max}, expected <= 2");
}
}TUnit Version
1.75.0
.NET Version
.NET 10.0
Operating System
Windows
IDE / Test Runner
dotnet CLI (dotnet test / dotnet run)
Error Output / Stack Trace
Additional Context
No response
IDE-Specific Issue?
- I've confirmed this issue occurs when running via
dotnet testordotnet run, not just in my IDE
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
fix(engine): apply max parallelism cap to keyed NotInParallel tests (#…
fix(engine): end fail-fast runs without crashing the test host (#7115)