-
Notifications
You must be signed in to change notification settings - Fork 1
Phase Aware Tracking
Phase-aware tracking lets you configure tracking behavior differently for the Setup phase (BDD Given/Arrange) vs the Action phase (BDD When-Then/Act-Assert). This is useful for reducing diagram noise — e.g. suppressing verbose database seeding calls during setup while keeping full detail for the action under test.
Every tracking extension reads the current test phase from an ambient AsyncLocal context (TestPhaseContext.Current). Based on the phase, each tracker decides:
-
Whether to track at all —
TrackDuringSetup/TrackDuringAction(default: bothtrue) -
What verbosity to use —
SetupVerbosity/ActionVerbosityoverride the defaultVerbosityduring that phase
If no phase is set (the default for non-BDD frameworks that don't call StartSetup()), the phase is Unknown. In this case, the TrackDuringSetup / TrackDuringAction toggles have no effect, and GetEffectiveVerbosity returns the base Verbosity.
However, verbosity overrides still work for non-BDD users via a deferred variant mechanism (see Non-BDD Phase-Aware Verbosity below). When overrides are configured and the phase is Unknown, each tracker captures both a Setup and an Action variant at log time. The diagram renderer then picks the correct variant based on the position of StartAction() — entries before that boundary use the Setup variant, entries after use the Action variant.
| Source | How phase is set |
|---|---|
| BDDfy | Automatically from ExecutionOrder — SetupState/ConsecutiveSetupState/Assertion → Setup; others → Action |
| LightBDD | Automatically from GetTopLevelStepType() — Given/And/But → Setup; When/Then → Action |
| ReqNRoll | Automatically in BeforeStep hook — Given/And/But → Setup; When/Then → Action |
| StepTracking | Automatically from step attributes — [GivenStep]/[ButStep] → Setup; [WhenStep]/[ThenStep] → Action (see Step Tracking) |
| Non-BDD | Call TrackingDiagramOverride.StartAction() to define the boundary. StartSetup() is also available but optional. Verbosity overrides work via deferred variants when only StartAction() is used. |
new SqlTrackingInterceptorOptions
{
ServiceName = "OrdersDb",
Verbosity = SqlTrackingVerbosity.Detailed,
TrackDuringSetup = false // ← no SQL tracking during Given/Arrange
}new SqlTrackingInterceptorOptions
{
ServiceName = "OrdersDb",
Verbosity = SqlTrackingVerbosity.Detailed, // default for Unknown phase
SetupVerbosity = SqlTrackingVerbosity.Summarised, // less detail during setup
ActionVerbosity = SqlTrackingVerbosity.Raw // maximum detail during action
}services.TrackDependenciesForDiagrams(
new XUnitTestTrackingMessageHandlerOptions
{
CallerName = "My API",
PortsToServiceNames = { { 80, "My API" } },
TrackDuringSetup = false // ← no HTTP tracking during setup
});For non-BDD tests, you only need StartAction() to define the boundary between setup and action. Everything before that call is treated as setup; everything after is treated as action.
[Fact]
public async Task Create_order_stores_in_database()
{
// Setup phase — seeding, config, etc.
await client.PostAsync("/api/seed-data", seedContent);
TrackingDiagramOverride.StartAction();
// Action phase — the actual behavior under test
var response = await client.PostAsync("/api/orders", orderContent);
response.StatusCode.Should().Be(HttpStatusCode.Created);
}You can optionally call StartSetup() first if you want explicit control, but it is not required:
[Fact]
public async Task Create_order_stores_in_database()
{
TrackingDiagramOverride.StartSetup();
// Explicit setup phase
await client.PostAsync("/api/seed-data", seedContent);
TrackingDiagramOverride.StartAction();
// Action phase
var response = await client.PostAsync("/api/orders", orderContent);
response.StatusCode.Should().Be(HttpStatusCode.Created);
}BDD frameworks: You don't need to call
StartSetup()orStartAction()— phase detection is automatic based on the step keyword.
v2.27.5+ — Verbosity overrides (SetupVerbosity / ActionVerbosity) now work correctly for non-BDD test frameworks that don't use StartSetup().
When the test phase is Unknown (the normal state for non-BDD tests) and at least one verbosity override is configured, each tracker captures two phase variants alongside the main log entry:
-
SetupVariant — the log entry as it would look at
SetupVerbosity -
ActionVariant — the log entry as it would look at
ActionVerbosity
The diagram renderer then uses StartAction() as the boundary: entries logged before StartAction() render using their SetupVariant; entries logged after render using their ActionVariant.
This happens automatically — no additional configuration is needed. The only requirement is a call to StartAction() in your test to define the boundary.
Variants are only computed when:
- The test phase is
Unknownat capture time, and - At least one of
SetupVerbosity/ActionVerbosityis set
For BDD frameworks (where the phase is always Setup or Action), or when no verbosity overrides are configured, there is zero additional overhead.
// Configure SQL tracking with different verbosity per phase
var options = new SqlTrackingInterceptorOptions
{
ServiceName = "OrdersDb",
Verbosity = SqlTrackingVerbosity.Detailed,
SetupVerbosity = SqlTrackingVerbosity.Other, // suppress setup SQL from diagram
ActionVerbosity = SqlTrackingVerbosity.Raw // full SQL detail during action
};
[Fact]
public async Task Create_order_stores_in_database()
{
// These SQL calls will use SetupVerbosity (suppressed)
await SeedTestData();
TrackingDiagramOverride.StartAction();
// These SQL calls will use ActionVerbosity (raw detail)
var order = await CreateOrder();
order.Should().NotBeNull();
}If a variant's verbosity resolves to a level that would normally suppress the log entry (e.g. Other for SQL), the variant is marked with Skip = true. The renderer will omit that entry entirely for that phase. This means you can use verbosity to suppress specific log entries in one phase while showing them in another.
Every extension options class (except OpenTelemetry) supports these four phase-aware properties:
| Property | Type | Default | Description |
|---|---|---|---|
TrackDuringSetup |
bool |
true |
When false, tracking is completely suppressed during the Setup phase |
TrackDuringAction |
bool |
true |
When false, tracking is completely suppressed during the Action phase |
SetupVerbosity |
{ExtVerbosity}? |
null |
Verbosity override for the Setup phase. null = use default Verbosity
|
ActionVerbosity |
{ExtVerbosity}? |
null |
Verbosity override for the Action phase. null = use default Verbosity
|
Where {ExtVerbosity} is the extension-specific verbosity enum (e.g. SqlTrackingVerbosity, RedisTrackingVerbosity, CosmosTrackingVerbosity, etc.).
The core HTTP tracking handler supports TrackDuringSetup and TrackDuringAction but does not have verbosity overrides (HTTP tracking doesn't use an enum-based verbosity system):
| Property | Type | Default | Description |
|---|---|---|---|
TrackDuringSetup |
bool |
true |
When false, HTTP requests during Setup are not tracked |
TrackDuringAction |
bool |
true |
When false, HTTP requests during Action are not tracked |
The MediatR extension uses TrackingProxy internally and supports TrackDuringSetup / TrackDuringAction only (no verbosity overrides):
| Property | Type | Default | Description |
|---|---|---|---|
TrackDuringSetup |
bool |
true |
When false, MediatR send/publish tracking is suppressed during Setup |
TrackDuringAction |
bool |
true |
When false, MediatR send/publish tracking is suppressed during Action |
The DispatchProxy extension takes a TrackingProxyOptions directly, which has TrackDuringSetup and TrackDuringAction:
| Property | Type | Default | Description |
|---|---|---|---|
TrackDuringSetup |
bool |
true |
When false, proxy interaction logging is suppressed during Setup |
TrackDuringAction |
bool |
true |
When false, proxy interaction logging is suppressed during Action |
The following extensions support both the enable/disable toggle (TrackDuringSetup/TrackDuringAction) and per-phase verbosity overrides (SetupVerbosity/ActionVerbosity):
| Extension | Options Class | Verbosity Enum |
|---|---|---|
| EF Core (Relational) | SqlTrackingInterceptorOptions |
SqlTrackingVerbosity |
| Redis | RedisTrackingDatabaseOptions |
RedisTrackingVerbosity |
| Kafka | KafkaTrackingOptions |
KafkaTrackingVerbosity |
| gRPC | GrpcTrackingOptions |
GrpcTrackingVerbosity |
gRPC note: If your gRPC calls run inside the SUT's request pipeline (SUT → downstream), phase-aware tracking will only work if test identity can be resolved. v2.26.0+:
AddTrackedGrpcClient<TClient>()auto-resolvesIHttpContextAccessorfrom DI. For older versions, setHttpContextAccessoronGrpcTrackingOptionsmanually. See Integration Grpc Extension#Dual-Resolution Test Identity (HttpContextAccessor).
| MassTransit | MassTransitTrackingOptions | MassTransitTrackingVerbosity |
| MongoDB | MongoDbTrackingOptions | MongoDbTrackingVerbosity |
| CosmosDB | CosmosTrackingMessageHandlerOptions | CosmosTrackingVerbosity |
| Elasticsearch | ElasticsearchTrackingOptions | ElasticsearchTrackingVerbosity |
| Dapper | DapperTrackingOptions | DapperTrackingVerbosity |
| BigQuery | BigQueryTrackingMessageHandlerOptions | BigQueryTrackingVerbosity |
| BlobStorage | BlobTrackingMessageHandlerOptions | BlobTrackingVerbosity |
| CloudStorage | CloudStorageTrackingMessageHandlerOptions | CloudStorageTrackingVerbosity |
| DynamoDB | DynamoDbTrackingMessageHandlerOptions | DynamoDbTrackingVerbosity |
| EventBridge | EventBridgeTrackingMessageHandlerOptions | EventBridgeTrackingVerbosity |
| S3 | S3TrackingMessageHandlerOptions | S3TrackingVerbosity |
| SNS | SnsTrackingMessageHandlerOptions | SnsTrackingVerbosity |
| SQS | SqsTrackingMessageHandlerOptions | SqsTrackingVerbosity |
| StorageQueues | StorageQueueTrackingMessageHandlerOptions | StorageQueueTrackingVerbosity |
| EventHubs | EventHubsTrackingOptions | EventHubsTrackingVerbosity |
| PubSub | PubSubTrackingOptions | PubSubTrackingVerbosity |
| ServiceBus | ServiceBusTrackingOptions | ServiceBusTrackingVerbosity |
Phase-aware tracking works independently from Diagram Customisation#Setup Separation (SeparateSetup = true). They complement each other:
| Feature | Purpose |
|---|---|
| Setup Separation | Visual — wraps setup calls in a coloured partition in the diagram |
| Phase-Aware Tracking | Functional — controls whether calls are tracked and at what verbosity |
You can use both together: suppress noisy setup database calls (TrackDuringSetup = false on the DB extension) while still showing setup HTTP calls in a partition (SeparateSetup = true).
Each RequestResponseLog entry now includes a Phase property (TestPhase enum) indicating which phase produced it. This is available in:
- Custom report generators that consume
RequestResponseLogdirectly - The JSON/YAML/XML export formats
Test Step Executes
│
├── BDD adapter (BDDfy/LightBDD/ReqNRoll)
│ └── Calls PhaseConfiguration.ResolvePhaseFromStepType("Given")
│ └── Sets TestPhaseContext.Current = Setup
│
├── OR: Non-BDD test
│ └── Optionally calls TrackingDiagramOverride.StartSetup()
│ └── Calls TrackingDiagramOverride.StartAction()
│ └── Sets TestPhaseContext.Current = Action
│ └── Inserts IsActionStart marker into log queue
│
▼
Tracker intercepts operation (SQL, Redis, HTTP, etc.)
│
├── PhaseConfiguration.ShouldTrack(trackDuringSetup, trackDuringAction)
│ └── Reads TestPhaseContext.Current
│ └── Returns false → skip tracking entirely
│
├── PhaseConfiguration.GetEffectiveVerbosity(default, setupOverride, actionOverride)
│ └── Reads TestPhaseContext.Current
│ └── Known phase → returns phase-appropriate verbosity
│ └── Unknown phase → returns default verbosity
│
├── [If phase is Unknown AND overrides configured]
│ └── AttachVariants() computes SetupVariant + ActionVariant
│ └── Each variant captures method, URI, content, headers, skip flag
│ └── Variant verbosity determines content shaping and skip
│
└── Logs with Phase = TestPhaseContext.Current on RequestResponseLog
▼
Renderer (PlantUmlCreator) processes log entries
│
├── Tracks isInActionPhase (starts false, set true at IsActionStart)
│
├── If entry has variants:
│ └── Before IsActionStart → use SetupVariant
│ └── After IsActionStart → use ActionVariant
│ └── If active variant has Skip = true → omit entry
│
└── Renders with effective method, URI, content, headers
| Step Keyword | Phase |
|---|---|
Given, And, But
|
Setup |
When, Then
|
Action |
null / unrecognised |
Unknown |
Note:
AndandButalways map toSetupbecause in BDD conventions they typically continue the Given context. If yourAnd/Butsteps follow aWhenorThen, you can override by callingTrackingDiagramOverride.StartAction()explicitly.
- OpenTelemetry Extension: The OpenTelemetry extension is a pass-through that captures spans from the OpenTelemetry SDK. It does not have its own tracking loop, so phase-aware configuration does not apply.
Getting Started
Common Tasks
Integration Guides
- Integration xUnit3
- Integration xUnit2
- Integration NUnit
- Integration MSTest
- Integration TUnit
- Integration BDDfy xUnit3
- Integration LightBDD xUnit2
- Integration LightBDD xUnit3
- Integration LightBDD TUnit
- Integration ReqNRoll xUnit2
- Integration ReqNRoll xUnit3
- Integration ReqNRoll TUnit
Extensions
- Integration AtlasDataApi Extension
- Integration BigQuery Extension
- Integration Bigtable Extension
- Integration BlobStorage Extension
- Integration CloudStorage Extension
- Integration CosmosDB Extension
- Integration Dapper Extension
- Integration DynamoDB Extension
- Integration EF Core Relational Extension
- Integration Elasticsearch Extension
- Integration EventBridge Extension
- Integration EventHubs Extension
- Integration Grpc Extension
- Integration Kafka Extension
- Integration MassTransit Extension
- Integration MongoDB Extension
- Integration MySqlConnector Extension
- Integration Npgsql Extension
- Integration Oracle Extension
- Integration PubSub Extension
- Integration Redis Extension
- Integration S3 Extension
- Integration ServiceBus Extension
- Integration SNS Extension
- Integration Spanner Extension
- Integration SqlClient Extension
- Integration Sqlite Extension
- Integration SQS Extension
- Integration StorageQueues Extension
- Integration OpenTelemetry Extension
- Integration DispatchProxy Extension
- Integration MediatR Extension
- Integration PlantUML IKVM
Configuration
- Tracking Dependencies
- Tracking Custom Dependencies
- HTTP Tracking Setup
- Report Configuration
- Diagram Customisation
- Phase-Aware Tracking
- Content Formatting
- PlantUML Server Configuration
Features
- Generated Reports
- Search Syntax
- Component Diagrams
- PlantUML Browser Rendering
- Inline SVG Rendering
- Internal Flow Tracking
- Tags and Attributes
- Excluding Requests
- Excluded Headers
- Multi-Host Test Architectures
- Event-Driven Architecture Testing
- Service Bus Tracking Patterns
- Background Thread Correlation
- Parallel-Safe Background Correlation
- Event & Message Tracking
- Assertion Tracking
- Step Tracking
- Tabular Attributes
- Large Response and Diagram Handling
- Diagnostics and Debugging
- CI Summary Integration
- CI Artifact Upload
Reference