4-3 Configuration des serveurs de test
Comme mentionné en introduction, les tests d'intégration utilisaient un serveur en mémoire, c'est-à-dire qu'il n'est pas réellement accessible de l'extérieur. Playwright nécessite que l'application soit exécutée normalement afin qu'un navigateur externe puisse y accéder.
Pour ce faire, il est nécessaire de configurer des serveurs de test pouvant être lancés par les tests xUnit Playwright.
Configuration pour les tests E2E MVC
Créer SnowfallMvcKestrelApplicationFactory
Comme Playwright doit ouvrir un vrai navigateur, il a besoin d'une instance accessible de l'application sur un "vrai" port. Kestrel est le serveur HTTP intégré et par défaut d'ASP .NET Core, il faut donc partir manuellement une instance de ce serveur.
- Sous
Snowfall.Tests/Web.Mvc
->Add
->Class/Interface
- Nommer la classe
SnowfallMvcApplicationServeurTest
- Faites hériter la classe de
SnowfallMvcApplicationFactory
Snowfall.Tests/Web.Mvc/SnowfallMvcKestrelApplicationFactory.cspublic class SnowfallMvcKestrelApplicationFactory : SnowfallMvcApplicationFactory
{
} - Faites en sorte que cette dernière hérite de la classe
WebMvcIntegrationTestBase
Snowfall.Tests/Web.Mvc/SnowfallMvcApplicationServeurTest.cspublic class SnowfallMvcApplicationServeurTest : WebMvcIntegrationTestBase
{
public SnowfallMvcApplicationServeurTest(
SnowfallMvcApplicationFactory application,
TestDatabaseFixture database) : base(application, database)
{
}
} - Mettre le code suivant dans la classe pour construire et démarrer un serveur de test:
Snowfall.Tests/TestsMvc/SnowfallMvcApplicationServeurTest.cs
public class SnowfallMvcKestrelApplicationFactory : SnowfallMvcApplicationFactory
{
private IHost? _host;
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Test")
.UseUrls("http://127.0.0.1:0");
}
protected override IHost CreateHost(IHostBuilder builder)
{
// Construit le serveur de test en mémoire (requis)
var testHost = builder.Build();
// Configure et construit le serveur Kestrel
builder.ConfigureWebHost(web => web.UseKestrel());
_host = builder.Build();
_host.Start();
// Récupère l'adresse du serveur Kestrel
var server = _host.Services.GetRequiredService<IServer>();
var address = server.Features.Get<IServerAddressesFeature>()
.Addresses.Last();
// Assigne comme adresse de base celle du serveur Kestrel
ClientOptions.BaseAddress = new Uri(address);
// Démarre le serveur de test
testHost.Start();
return testHost;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_host?.StopAsync().GetAwaiter().GetResult();
_host?.Dispose();
}
}
}
Créer WebMvcE2ETestBase
Cette classe servira de base pour les tests. Elle servira entre autres à réinitialiser la base de données à chaque exécution de test, tout comme les tests d'intégration MVC et d'API.
public abstract class WebMvcE2ETestBase : IClassFixture<SnowfallMvcKestrelApplicationFactory>, IClassFixture<TestDatabaseFixture>, IAsyncLifetime, IDisposable
{
protected readonly SnowfallMvcKestrelApplicationFactory Application;
protected readonly TestDatabaseFixture Database;
protected IPage Page { get; private set; } = null!;
protected readonly IVilleRepository VilleRepository;
protected readonly IEvenementRepository EvenementRepository;
private IBrowser? _browser;
private readonly IServiceScope _scope;
protected WebMvcE2ETestBase(SnowfallMvcKestrelApplicationFactory application, TestDatabaseFixture database)
{
Application = application;
Database = database;
_scope = Application.Services.CreateScope();
VilleRepository = _scope.ServiceProvider.GetRequiredService<IVilleRepository>();
EvenementRepository = _scope.ServiceProvider.GetRequiredService<IEvenementRepository>();
}
public async Task InitializeAsync()
{
// Réinitialise la base de données
await Database.ResetDatabaseAsync();
// Démarre le serveur
var client = Application.CreateClient();
// Lance Playwright et crée une nouvelle page
var playwright = await Playwright.CreateAsync();
_browser = await playwright.Chromium.LaunchAsync(new
BrowserTypeLaunchOptions
{
Headless = false
});
var context = await _browser.NewContextAsync();
Page = await context.NewPageAsync();
}
public async Task DisposeAsync()
{
if (_browser is not null)
await _browser.CloseAsync();
}
public void Dispose()
{
}
}
Configuration pour les tests E2E API
Créer SnowfallApiKestrelApplicationFactory
Blazor et le serveur Kestrel fonctionnent mal avec l'environnement Test. C'est pourquoi nous allons démarrer le projet normalement en environnement Development
, mais allons forcer la récupération de appsettings.Test.json
pour que la bd utilisée soit celle de test!
- Sous
Snowfall.Tests/Web.Api
->Add
->Class/Interface
- Nommer la classe
SnowfallApiKestrelApplicationFactory
- Utilisez un code similaire à MVC, mais légèrement différent puisque la façon de partir l'API n'est pas tout à fait la même.
Snowfall.Tests/Web.Api/SnowfallApiKestrelApplicationFactory.cs
public class SnowfallApiKestrelApplicationFactory : WebApplicationFactory<Program>
{
private IHost? _host;
protected override IHost CreateHost(IHostBuilder builder)
{
// Force l'utilisation de la configuration de test
builder.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile(
"appsettings.Test.json",
optional: true,
reloadOnChange: false);
});
var testHost = builder.Build();
// Configure le vrai serveur Kestrel
builder.ConfigureWebHost(web => web.UseKestrel());
_host = builder.Build();
_host.Start();
// Alloue un port aléatoire à Kestrel
var server = _host.Services.GetRequiredService<IServer>();
var address = server.Features.Get<IServerAddressesFeature>()!
.Addresses.Last();
// Faire pointer l'adresse de base vers celle de Kestrel
ClientOptions.BaseAddress = new Uri(address);
// Démarrer le serveur de test
testHost.Start();
return testHost;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
if (_host is not null)
{
_host.StopAsync().GetAwaiter().GetResult();
_host.Dispose();
}
}
}
}
Créer WebApiE2ETestBase
Cette classe servira de base pour les tests. Elle servira entre autres à réinitialiser la base de données à chaque exécution de test, tout comme les tests d'intégration MVC et d'API.
- Sous le dossier
Snowfall.Tests/Web.Api/TestsE2E
, créez la classeWebApiE2ETestBase
- Mettez-y le code suivant
Snowfall.Tests/Web.Api/TestsE2E/WebApiE2ETestBase.cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Playwright;
using Snowfall.Data.Repositories;
namespace Snowfall.Tests.Web.Api.TestsE2E;
[Collection("Test Database Collection")]
public abstract class WebApiE2ETestBase : IClassFixture<SnowfallApiKestrelApplicationFactory>, IClassFixture<TestDatabaseFixture>, IAsyncLifetime, IDisposable
{
protected readonly SnowfallApiKestrelApplicationFactory Application;
protected readonly TestDatabaseFixture Database;
protected IPage Page { get; private set; } = null!;
protected readonly IVilleRepository VilleRepository;
protected readonly IEvenementRepository EvenementRepository;
private IBrowser? _browser;
private readonly IServiceScope _scope;
protected WebApiE2ETestBase(SnowfallApiKestrelApplicationFactory application, TestDatabaseFixture database)
{
Application = application;
Database = database;
_scope = Application.Services.CreateScope();
VilleRepository = _scope.ServiceProvider.GetRequiredService<IVilleRepository>();
EvenementRepository = _scope.ServiceProvider.GetRequiredService<IEvenementRepository>();
}
public async Task InitializeAsync()
{
// Réinitialise la base de données
await Database.ResetDatabaseAsync();
// Démarre le serveur
var client = Application.CreateClient();
// Lance Playwright et crée une nouvelle page
var playwright = await Playwright.CreateAsync();
_browser = await playwright.Chromium.LaunchAsync(new
BrowserTypeLaunchOptions
{
Headless = false
});
var context = await _browser.NewContextAsync();
Page = await context.NewPageAsync();
}
public async Task DisposeAsync()
{
if (_browser is not null)
await _browser.CloseAsync();
}
public void Dispose()
{
}
}