Skip to content

Commit 621883c

Browse files
committed
Add test throttling (reduces the duration of running all tests from 2:37 to 0:30 on my system)
1 parent 6616ee5 commit 621883c

File tree

5 files changed

+53
-29
lines changed

5 files changed

+53
-29
lines changed

test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using JetBrains.Annotations;
22
using Microsoft.Extensions.DependencyInjection;
33
using TestBuildingBlocks;
4+
using Xunit;
45

56
namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations;
67

78
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
8-
public sealed class AtomicOperationsFixture : IDisposable
9+
public sealed class AtomicOperationsFixture : IAsyncLifetime
910
{
1011
internal IntegrationTestContext<TestableStartup, OperationsDbContext> TestContext { get; }
1112

@@ -21,8 +22,13 @@ public AtomicOperationsFixture()
2122
TestContext.ConfigureServicesAfterStartup(services => services.AddSingleton<ResourceDefinitionHitCounter>());
2223
}
2324

24-
public void Dispose()
25+
public Task InitializeAsync()
2526
{
26-
TestContext.Dispose();
27+
return Task.CompletedTask;
28+
}
29+
30+
public async Task DisposeAsync()
31+
{
32+
await TestContext.DisposeAsync();
2733
}
2834
}

test/JsonApiDotNetCoreMongoDbTests/JsonApiDotNetCoreMongoDbTests.csproj

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@
33
<TargetFramework>$(TargetFrameworkName)</TargetFramework>
44
</PropertyGroup>
55

6-
<ItemGroup>
7-
<None Update="xunit.runner.json">
8-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
9-
</None>
10-
</ItemGroup>
11-
126
<ItemGroup>
137
<ProjectReference Include="..\TestBuildingBlocks\TestBuildingBlocks.csproj" />
148
<ProjectReference Include="..\..\src\JsonApiDotNetCore.MongoDb\JsonApiDotNetCore.MongoDb.csproj" />

test/JsonApiDotNetCoreMongoDbTests/xunit.runner.json

Lines changed: 0 additions & 4 deletions
This file was deleted.

test/TestBuildingBlocks/IntegrationTest.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,26 @@
22
using System.Text;
33
using System.Text.Json;
44
using JsonApiDotNetCore.Middleware;
5+
using Xunit;
56

67
namespace TestBuildingBlocks;
78

89
/// <summary>
9-
/// A base class for tests that conveniently enables to execute HTTP requests against JSON:API endpoints.
10+
/// A base class for tests that conveniently enables to execute HTTP requests against JSON:API endpoints. It throttles tests that are running in parallel
11+
/// to avoid exceeding the maximum active database connections.
1012
/// </summary>
11-
public abstract class IntegrationTest
13+
public abstract class IntegrationTest : IAsyncLifetime
1214
{
15+
private static readonly SemaphoreSlim ThrottleSemaphore;
16+
1317
protected abstract JsonSerializerOptions SerializerOptions { get; }
1418

19+
static IntegrationTest()
20+
{
21+
int maxConcurrentTestRuns = Environment.GetEnvironmentVariable("APPVEYOR") != null ? 32 : 64;
22+
ThrottleSemaphore = new SemaphoreSlim(maxConcurrentTestRuns);
23+
}
24+
1525
public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteGetAsync<TResponseDocument>(string requestUrl,
1626
Action<HttpRequestHeaders>? setRequestHeaders = null)
1727
{
@@ -99,4 +109,15 @@ public abstract class IntegrationTest
99109
throw new FormatException($"Failed to deserialize response body to JSON:\n{responseText}", exception);
100110
}
101111
}
112+
113+
public async Task InitializeAsync()
114+
{
115+
await ThrottleSemaphore.WaitAsync();
116+
}
117+
118+
public virtual Task DisposeAsync()
119+
{
120+
_ = ThrottleSemaphore.Release();
121+
return Task.CompletedTask;
122+
}
102123
}

test/TestBuildingBlocks/IntegrationTestContext.cs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace TestBuildingBlocks;
2828
/// <see cref="MongoDbContextShim" />.
2929
/// </typeparam>
3030
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
31-
public class IntegrationTestContext<TStartup, TMongoDbContextShim> : IntegrationTest, IDisposable
31+
public class IntegrationTestContext<TStartup, TMongoDbContextShim> : IntegrationTest
3232
where TStartup : class
3333
where TMongoDbContextShim : MongoDbContextShim
3434
{
@@ -125,19 +125,6 @@ private void ConfigureJsonApiOptions(JsonApiOptions options)
125125
options.SerializerOptions.WriteIndented = true;
126126
}
127127

128-
public void Dispose()
129-
{
130-
if (_lazyFactory.IsValueCreated)
131-
{
132-
_lazyFactory.Value.Dispose();
133-
}
134-
135-
if (_runner.IsValueCreated)
136-
{
137-
_runner.Value.Dispose();
138-
}
139-
}
140-
141128
public void ConfigureServicesAfterStartup(Action<IServiceCollection> servicesConfiguration)
142129
{
143130
_afterServicesConfiguration = servicesConfiguration;
@@ -151,6 +138,26 @@ public async Task RunOnDatabaseAsync(Func<TMongoDbContextShim, Task> asyncAction
151138
await asyncAction(mongoDbContextShim);
152139
}
153140

141+
public override async Task DisposeAsync()
142+
{
143+
try
144+
{
145+
if (_lazyFactory.IsValueCreated)
146+
{
147+
await _lazyFactory.Value.DisposeAsync();
148+
}
149+
150+
if (_runner.IsValueCreated)
151+
{
152+
_runner.Value.Dispose();
153+
}
154+
}
155+
finally
156+
{
157+
await base.DisposeAsync();
158+
}
159+
}
160+
154161
private sealed class IntegrationTestWebApplicationFactory : WebApplicationFactory<TStartup>
155162
{
156163
private Action<IServiceCollection>? _beforeServicesConfiguration;

0 commit comments

Comments
 (0)