Skip to main content

Integrations overview

Each integration is a NuGet package that joins the foundation: most bring a client to ProtoExecutionContext, others contribute collectors, resources or host capabilities. They all share the foundation — lifecycle, attributes, attachments, tracing, coverage — so using several in one test doesn't mean learning several models. Every library and runner package targets .NET 8, 9 and 10 and is stable on NuGet, so dotnet add package lines install directly.

Quick start

Compose one application and give it a protocol:

builder.AddApplication("Api", app => app
.AddAspNetCoreServer<Program>()
.AddRest(rest => rest.AddClient("Api")));
[Application("Api")]
public sealed class ApiTests
{
[ProtoTest]
public async Task Orders_are_created()
{
using var response = await Proto.Context.Rest()
.Body(new { product = "notebook", quantity = 2 })
.PostAsync("/api/orders");

response.Should.HaveHttpStatus(HttpStatusCode.Created)
.ShouldMatchShape(new { id = JsonValue.GreaterThan(0), product = "notebook" });
}
}

Run this with any runner, then add AddGraphQL, AddWeb, AddMessaging, … to the same application: the same context hands each protocol its client, and everything lands in one trace and one report.

COMPOSE YOUR SUITE

Start with what the scenario crosses

Pick capabilities, not a bundle. They meet again in the same execution context and trace.

1. What does the test cross?
2. Which runner do you use?

Going further: several integrations in one test

Adapted from samples/ProtoTest.Demo/SheetsJourney.cs — data through one package, an HTTP download through another, and a spreadsheet assertion through a third, all in one test:

[ProtoTest]
[SignedInAs]
public async Task TheMonthlyReport_ShouldMatchItsModel()
{
var project = await Proto.Context.Data()
.For<CreateProjectRequest>()
.With(request => request.Name, "report-atlas")
.CreateAsync<ProjectResponse>();

using var response = await Proto.Context.Rest().GetAsync("/api/v1/reports/monthly.xlsx");
response.Should.HaveHttpStatus(HttpStatusCode.OK);
var report = Proto.Context.Sheets().Open(response).Model<ProjectReportRow>();

report.Verify();
report.Column(row => row.Environments).ShouldAll(count => count >= 0);
}

The same pattern works across protocols: change something through REST and check it through GraphQL in the same test, with one [Auth<T>] authenticator serving both. The recipes walk through scenarios like these end to end.

Complete package reference

The composer above gives a suite its direct starting packages. This reference includes the adapters, infrastructure helpers and supporting packages you may add as the suite grows.

Integration packages

PackageInstallWhat it addsReach it with
ProtoTest.Restdotnet add package ProtoTest.RestHTTP/REST client, status and shape assertions, [Auth<T>], REST coverageProto.Context.Rest()
ProtoTest.GraphQLdotnet add package ProtoTest.GraphQLqueries, mutations, WebSocket/SSE subscriptions, uploads, schema coverageProto.Context.GraphQL()
ProtoTest.Grpcdotnet add package ProtoTest.Grpcunary and streaming gRPC clients, metadata auth, shape/status assertions, method coverageProto.Context.Grpc()
ProtoTest.Messagingdotnet add package ProtoTest.Messagingpublish and await messages, with an in-memory default brokerProto.Context.Messaging()
ProtoTest.Messaging.RabbitMqdotnet add package ProtoTest.Messaging.RabbitMqRabbitMQ adapter for the messaging clientmessaging.UseRabbitMq()
ProtoTest.Sheetsdotnet add package ProtoTest.Sheets.xlsx cell, column, range, table and typed-model assertions, range coverageProto.Context.Sheets()
ProtoTest.Datadotnet add package ProtoTest.Datadeterministic data, member defaults, provisioners and the Ref<T> identity mapProto.Context.Data()
ProtoTest.Sqldotnet add package ProtoTest.Sqlone database connection per test, optional transaction isolationProto.Context.SqlConnection()
ProtoTest.Sql.EntityFrameworkCoredotnet add package ProtoTest.Sql.EntityFrameworkCoreEF Core context over the per-test connection, enlisted in its transactionProto.Context.Sql<TContext>()
ProtoTest.Webdotnet add package ProtoTest.Webbackend-neutral sessions, page objects, flows, login and page coverageProto.Context.Web()
ProtoTest.Web.Playwrightdotnet add package ProtoTest.Web.PlaywrightPlaywright backend, browser pool and [RequiresPlaywrightBrowser] probebuilder.AddWeb()
ProtoTest.Web.Seleniumdotnet add package ProtoTest.Web.SeleniumSelenium backend with its own actionability loopbuilder.AddWeb(createDriver)
ProtoTest.AspNetCoredotnet add package ProtoTest.AspNetCorein-process ASP.NET Core application, server DI access, page inventoryProto.Context.ServerFactory<TProgram>()
ProtoTest.OpenApidotnet add package ProtoTest.OpenApiOpenAPI contract coverage over REST response and shape observations.AddCollector<OpenApiCoverageCollector>()
ProtoTest.Sql.Testcontainersdotnet add package ProtoTest.Sql.Testcontainersa PostgreSQL container owned by the runbuilder.AddInfrastructure(PostgresDatabase.Container(), "ConnectionStrings:Northstar")
ProtoTest.Messaging.RabbitMq.Testcontainersdotnet add package ProtoTest.Messaging.RabbitMq.Testcontainersa RabbitMQ container owned by the runbuilder.AddInfrastructure(RabbitMqBroker.Container(), RabbitMqOptions.ConnectionStringSetting, …)

Foundation and supporting packages

PackageInstallWhat it addsReach it with
ProtoTest.Coredotnet add package ProtoTest.Corehost, execution context, hooks, attributes, test ids, tracing, run gates and resourcesProto.Context, Proto.Host
ProtoTest.Httpdotnet add package ProtoTest.Httpshared HTTP client plumbing and the [Auth<T>] model behind REST, GraphQL and gRPC; an extension point, normally transitiveProto.Context.Client<HttpClient>(name)
ProtoTest.Jsondotnet add package ProtoTest.Jsonpartial JSON shape matching and JsonValue constraints; normally transitiveJsonShapeMatcher.AssertMatch, JsonValue
ProtoTest.Testcontainersdotnet add package ProtoTest.TestcontainersProtoContainerResource<TContainer> base for run-scoped containers: start-once, release-once, TryStartbuilder.AddInfrastructure(…)
ProtoTest.Reportingdotnet add package ProtoTest.ReportingJSON and HTML report sinksbuilder.AddSink<JsonReportSink>(), AddSink<HtmlReportSink>()
ProtoTest.OpenTelemetrydotnet add package ProtoTest.OpenTelemetryexport ProtoTest operations as OpenTelemetry spanstracerBuilder.AddProtoTestInstrumentation()

Runners and templates

PackageInstallWhat it addsReach it with
ProtoTest.NUnitdotnet add package ProtoTest.NUnitNUnit lifecycle adapter and attachment publisher[ProtoTest], ProtoTestAssembly
ProtoTest.Xunitdotnet add package ProtoTest.XunitxUnit v2 adapter (one collection for the suite)[ProtoTestFact], [ProtoTestTheory]
ProtoTest.Xunit3dotnet add package ProtoTest.Xunit3xUnit v3 adapter[ProtoTestFact], [ProtoTestTheory], assembly fixture
ProtoTest.MSTestdotnet add package ProtoTest.MSTestMSTest lifecycle adapter and attachment publisher[ProtoTest]
ProtoTest.TUnitdotnet add package ProtoTest.TUnitTUnit executor and attachment publisher[assembly: TestExecutor<ProtoTestExecutor>()]
ProtoTest.Templatesdotnet new install ProtoTest.Templatesthe prototest starter solution: an API and a suite for it, already composeddotnet new prototest -n Shop

Container-backed dependencies

When a suite should run against a real server instead of an in-memory one, a container package owns it for the run: ProtoTest.Sql.Testcontainers starts PostgreSQL, and ProtoTest.Messaging.RabbitMq.Testcontainers starts RabbitMQ. Register the container with AddInfrastructure(...) so the host starts it before the run, fills its connection string into configuration for the application and the tests, and releases it after the reports are written. Both build on ProtoTest.Testcontainers, whose TryStart lets a fixture fall back when no container runtime is available — see Infrastructure.

The same suite can then run in-process, container-backed or against a published environment without a code change; Environments explains what changes in each, including why environment-specific journeys skip rather than fail.