Skip to content

Commit d92872a

Browse files
Copilotstephentoub
andcommitted
Use ExclusiveExecution collection fixture to ensure DiagnosticTests don't run concurrently with any other tests
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
1 parent 92407d8 commit d92872a

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

tests/ModelContextProtocol.Tests/DiagnosticTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace ModelContextProtocol.Tests;
1111

12-
[Collection(nameof(DisableParallelization))]
12+
[Collection(nameof(ExclusiveExecution))]
1313
public class DiagnosticTests
1414
{
1515
[Fact]
Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,32 @@
1-
// Uncomment to disable parallel test execution for the whole assembly
2-
//[assembly: CollectionBehavior(DisableTestParallelization = true)]
1+
/// <summary>
2+
/// Test collection for tests that require exclusive execution (no parallel execution with any other tests).
3+
/// This is needed for tests that interact with global static state like ActivitySource in OpenTelemetry.
4+
/// </summary>
5+
/// <remarks>
6+
/// The fixture ensures mutual exclusion across ALL tests by using a static semaphore.
7+
/// Tests in this collection will acquire the semaphore before running and release it after,
8+
/// preventing any other test from running concurrently.
9+
/// </remarks>
10+
[CollectionDefinition(nameof(ExclusiveExecution))]
11+
public sealed class ExclusiveExecution : ICollectionFixture<ExclusiveExecutionFixture>;
312

413
/// <summary>
5-
/// Enables test classes to individually be attributed as [Collection(nameof(DisableParallelization))]
6-
/// to have those tests run non-concurrently with any other tests.
14+
/// Fixture that ensures only one test runs at a time across the entire test assembly.
715
/// </summary>
8-
[CollectionDefinition(nameof(DisableParallelization), DisableParallelization = true)]
9-
public sealed class DisableParallelization;
16+
public sealed class ExclusiveExecutionFixture : IAsyncLifetime
17+
{
18+
private static readonly SemaphoreSlim s_exclusiveLock = new(1, 1);
19+
20+
public async ValueTask InitializeAsync()
21+
{
22+
// Acquire the lock before any test in this collection starts
23+
await s_exclusiveLock.WaitAsync();
24+
}
25+
26+
public ValueTask DisposeAsync()
27+
{
28+
// Release the lock after the test completes
29+
s_exclusiveLock.Release();
30+
return default;
31+
}
32+
}

0 commit comments

Comments
 (0)