Skip to main content

Upgrading to the next major version

This guide covers changes already merged into main for the next major release (3.x). It is not a claim that every roadmap item or package has been released. Keep all BDTest package versions aligned and use the documentation for your installed version. The roadmap tracks work still in progress; update this guide when another breaking change lands.

Packages and prerequisites​

Check the installation matrix before upgrading. The core and most adapters now offer netstandard2.0 and net8.0 assets. NUnit requires NUnit 5 and .NET 8 or later; the report host and file-system storage package require .NET 10. Delegate overload resolution needs C# 13 or later (.NET SDK 9 or later), even when selecting the .NET Standard asset. Compiler extensions still target their .NET Standard compiler host.

The source generator now ships inside BDTest and arrives automatically through adapters. Remove explicit BDTest.SourceGenerator package references and central version entries; the standalone package is no longer produced. See source generator migration.

Runtime package IDs stay the same, including BDTest.xUnit and BDTest.Razor.Reports. The latter's display name is BDTest - ASP.NET Core Reports. BDTest.ReportGenerator.RazorServer is a sample host, not a NuGet package. BDTest.Reports.Storage.FileSystem is an optional storage package; its addition does not require replacing an existing custom store.

The target migration guide explains internal compiler polyfills, nullable contracts and modern clock APIs. Nullable annotations may surface warnings in consumers without changing runtime signatures. Runtime packages retain their signing key. Starting with 3.x, assembly versions remain Major.0.0.0 across minor and patch releases; package and informational versions still identify the exact release. This does not permit mixing package versions.

Automatic framework cancellation​

Official NUnit, xUnit v3, MSTest, and TUnit bases now forward runner cancellation to scenarios, outlines, token-aware steps, and hooks without requiring a BDTest timeout. BDTestAsync(callerToken) combines both tokens. Cancellation prevents unreached steps and retries and records a cancellation reason as Failed; the framework may independently report a timeout or cancellation.

For composition, use the framework-specific factory (for example, MSTestBDTestScenario.For<TContext>(this, run) or TUnitBDTestScenario.For<TContext>(this, run)) with the existing lifecycle wiring. Core-only BDTestScenario.For hosts still require an explicit runner token. See the framework guides for the installed APIs.

Test code and execution​

Existing usageUpgrade action
Nested builder, base or attribute namespacesReplace test-authoring imports with using BDTest;; see consumer namespaces. Rebuild consumers and update reflection names.
Separate BDTest.Analyzers packageRemove the package reference. Analyzers and code fixes now come with BDTest, including through adapters. Rule IDs and suppression settings are unchanged.
Expression-tree step signaturesUse delegate steps. The bundled source generator preserves method metadata, attributes and supported argument capture. Use WithArgs for unsupported expressions.
Positional [StepText] placeholders and overridesUse parameter names: {amount} instead of {0}, and "user=an administrator" instead of "1:an administrator".
Synchronous BDTest()Return Task from the test and use await or BDTestAsync(); see async-only execution.
Global execution settings in adaptersBDTestSettings has been removed. Move settings into IBDTestConfiguration selected by the assembly's BDTestConfiguration attribute. Built-in adapters use a frozen assembly run.
JSON/HTML helpers, report descriptors or HTTP upload from coreAdd BDTest.Reporting at the same version and rebuild. Namespaces and signatures remain unchanged; see reporting package.
Reports without an explicit runObtain the adapter's assembly run and pass it to report helpers. Export after tests and teardown, then dispose through the assembly owner. Overloads without a run and the legacy default run have been removed. Standalone callers must own an explicit BDTestRun; follow explicit run migration.
Old fluent types, WithContext, report ID or parameter membersApply the public names and fluent builder replacements. Each step kind is sealed; use var for continuations.
Direct calls to text/version helpers, default constants or JSON convertersUse the supported helper replacements; implementation helpers are now internal on both core assets.
Pending results typed as List<BuildableTest>Use scenario definition summaries. Pending results are data snapshots, not executable builders.
A custom adapter relying on stack inspectionSupply the runner's exact MethodInfo during BeginTest; follow custom adapter migration.
Exact generated text snapshots or transitive Humanizer APIsReview generated name changes; add a direct Humanizer reference if your own code needs it.

Use context factories and lifetime hooks for async initialization, retry recreation and owned disposal. An inline context you construct yourself remains yours to dispose. Native adapters now share the composition lifecycle; remove manual lifecycle calls when opting into native registration.

Retry and scenario skip policies​

Retry attributes now replace run retry rules instead of extending their limits. Precedence is test method, concrete fixture class, assembly, then run defaults. Remove an attribute to opt into run rules; use [BDTestRetry(0)] to opt out of all retries. Keep method attributes on the actual adapter-supplied test method, not helper methods.

A retry predicate error now stops retrying and records an output diagnostic while preserving the original test exception. Scenario skip predicates run once before initial context initialization and scenario hooks, not on every attempt. Move skip decisions that need execution-time state into steps using the framework's skip exception. A throwing scenario skip predicate fails immediately without retries. Step skip predicates retain their per-attempt behavior.

Framework adapters​

  • xUnit now requires xUnit v3. Replace v2 packages, use an executable test project, remove constructors that only pass ITestOutputHelper to the base class, and preserve base async cleanup.
  • NUnit uses NUnit 5. Composition requires [BDTestFixture] and INUnitBDTest; inheritance remains available.
  • MSTest requires [BDTestClass] on concrete BDTest fixtures, including inherited ones. Native context injection and invocation completion replace the former setup/cleanup hooks.
  • TUnit uses global lifecycle hooks. Composition implements IBDTestTUnitTest; reserve the documented final hook order for report export and run disposal.

Use the adapter guide's runner configuration; an adapter's .NET Standard asset does not establish that the framework or runner supports .NET Framework.

Reports and hosting​

AreaUpgrade action
Status handlingHandle NotRun and Pending; reserve Inconclusive for its actual outcome. Store names, not new enum integers. See status migration.
SerializationUse BDTestJsonHelper and the source-generated System.Text.Json metadata instead of Newtonsoft settings or converters. Review the JSON shape and historical-reader rules.
ExceptionsReview structured exception fields and update consumers of exception details.
Host optionsReplace BDTestReportServerOptions and middleware configuration with AddBDTestReports, BDTestReportOptions, and DI registrations. Replace IAdminAuthorizer with a named policy. See options migration.
Storage and deletionImplement cancellable IReportStore and IRunIndexStore, or use the temporary legacy bridge. Replace the old delete route with DELETE /bdtest/reports/{id} and handle 204. See storage migration.
Authentication and uploadsConfigure report-read and admin policies separately from the upload key. Unconfigured reads are denied and blank upload keys disable uploads. See security.
Static report uploadReplace obsolete static calls with BDTestReportUploader.UploadAsync for a URL or UploadReportAsync for a typed URL/ID result. Streaming gzip, typed response negotiation and no warm-up now also apply to the one-release static forwarders. See upload migration.
URLs and proxiesUse MapBDTestReports and pass the full external report prefix to upload clients. See hosting.
Razor view overridesUpdate the Overview, Timings, Failures and Not run model types and replace layout scenario access with aggregates. See compact page model migration.
Capacity and custom renderingCheck upload/cache limits and standalone HTML security and the hosted HTTPS image policy.

The new BDTest.Contracts package is currently additive. Existing helpers and hosted APIs still use the legacy model; do not send the new versioned DTO JSON to those endpoints until their integration has shipped. Likewise, pending roadmap work is not a prerequisite for migrating the changes above.

Verify the upgrade​

Build with nullable diagnostics enabled, run each adapter's tests, and inspect a passing, failing, skipped and retried scenario in your report. Check that the export selects the owning run, that historical reports still load, and that your host's read/upload/delete permissions behave as configured.

For a new project, start with the compiled first-test walkthrough. For a SpecFlow conversion, use Coming from SpecFlow.