Using it in your tests (auto)
Experimental. This project is an experiment: the public API, defaults and packaging can change between prereleases, and there is no production support guarantee.
Using it in your tests (auto)
Section titled “Using it in your tests (auto)”The zero-configuration shape: one project, no backend choice in your code or environment. The same tests run on WSL Containers on a Windows developer machine and on Docker on a Linux CI runner (or a Mac) — nothing changes between them.
The project
Section titled “The project”<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net10.0</TargetFramework> </PropertyGroup> <ItemGroup> <!-- the services you want --> <PackageReference Include="Purview.Containers.Redis" Version="1.0.0-prerelease.2" /> <PackageReference Include="Purview.Containers.PostgreSql" Version="1.0.0-prerelease.2" /> <!-- one backend reference: the umbrella brings the abstractions and both backends --> <PackageReference Include="Purview.Containers" Version="1.0.0-prerelease.2" /> </ItemGroup></Project>Three things make this work, and nothing else is required:
- A platform-neutral target framework (
net10.0).Purview.Containers.Wslis multi-target; anet10.0project binds its portable facade, which runs the WSLC implementation on Windows and reportswslunavailable everywhere else. (A Windows target framework still works — it binds the implementation directly — but it cannot run on a Linux CI runner.) - The umbrella package (
Purview.Containers), which bringsPurview.Containers.Core(the abstractions) and both backends. WSLC is preferred where it is usable and Docker is the fallback, so the one project runs everywhere. Prefer to be explicit? ReferencePurview.Containers.CoreplusPurview.Containers.Wsland/orPurview.Containers.Dockerindividually — a Linux-only CI job can skip the WSL backend and its ~19 MB payload withCore+.Dockeronly. - No registration line, no environment variable. Each backend package ships
buildTransitiveassets that generate a module initializer in your assembly, so the process discovers the registered backends by itself. Those assets flow transitively through the umbrella.
The test
Section titled “The test”using Npgsql;using Purview.Containers.PostgreSql;using Purview.Containers.Redis;using StackExchange.Redis;
public class CacheAndDatabaseTests{ [Test] public async Task PostgreSql_is_usable() { await using var postgres = new PostgreSqlBuilder().WithDatabase("app").Build(); await postgres.StartAsync(); // returns once pg_isready succeeds
await using var connection = new NpgsqlConnection(postgres.GetConnectionString()); await connection.OpenAsync(); // ...your assertions against a real database... }
[Test] public async Task Redis_is_usable() { await using var redis = new RedisBuilder().Build(); await redis.StartAsync(); // returns once redis-cli ping succeeds
await using var cache = await ConnectionMultiplexer.ConnectAsync(redis.GetConnectionString()); await cache.GetDatabase().PingAsync(); // ...your assertions against a real cache... }}That is the whole story: no image names, no ports, no Testcontainers, no docker, no wslc. The
builder default image, the port mapping (a random host port), and the readiness check all come from the
module; GetConnectionString() points at the mapped host port.
What happens on each host
Section titled “What happens on each host”| Host | Selected backend | Why |
|---|---|---|
| Windows with WSL Containers | wsl | The facade loads the WSLC implementation and WSLC is preferred. |
| Windows without WSL Containers, with Docker | docker | The facade reports wsl unavailable, so selection falls through. |
| Linux / macOS (any CI runner) | docker | The facade only ever activates on Windows. |
Automatic selection probes the registered backends in priority order (wsl is 0, docker is 100) and
returns the first one that is both available and compatible. When none is usable, the exception
lists each backend’s availability, version and missing components — see
Backends: WSLC or Docker.
Pinning, and seeing what it picked
Section titled “Pinning, and seeing what it picked”Auto is the default and needs no configuration. Two things help while debugging:
// Which backends can this machine run, and what version?foreach (var backend in await ContainerBackends.ProbeAllAsync()){ Console.WriteLine($"{backend.Name}: usable={backend.IsUsable} version={backend.Version}");}# Fail loudly instead of falling back (the usual choice in CI).PURVIEW_CONTAINERS_BACKEND=docker # or: wslA named backend never silently falls back: if it cannot run, the test fails with that backend’s own diagnostics.
Requirements
Section titled “Requirements”- The abstractions and every service module are portable
net10.0; see Consumer Requirements for the exact target-framework contract, thePCC0001/PCC0002guards and theEnableWindowsTargetingworkaround for non-Windows build agents. - The per-module connection-string shapes (Redis, PostgreSQL, SQL Server, MySQL, RabbitMQ, Azurite, NATS) are in Modules.
- A live sample of this shape is
samples/getting-started/AutoSample(just sample-auto).
Related
Section titled “Related”- Getting Started — install and the first container.
- Backends: WSLC or Docker — the comparison, side-by-side setup and CI examples.
- Modules — the service modules and their connection strings.
- Consumer Requirements — the target-framework contract and the guards.