-
Notifications
You must be signed in to change notification settings - Fork 1
Component Diagrams
TestTrackingDiagrams can aggregate all tracked interactions across your entire test suite to auto-generate a C4-style component diagram. This diagram shows every discovered participant (services, event brokers, databases) and their relationships — giving you a high-level architecture overview derived directly from real test traffic.
This is an opt-in feature.
- Quick Start
- How It Works
- Configuration
- Output Files
- Participant Classification
- Relationship Labels
- Customisation
- Example Output
- Integration with PlantUML IKVM
- Performance
- Limitations & Known Behaviours
- API Reference
Add GenerateComponentDiagram = true to your ReportConfigurationOptions:
var options = new ReportConfigurationOptions
{
GenerateComponentDiagram = true
};That's it. When your test run completes and reports are generated, a ComponentDiagram.puml and ComponentDiagram.html file will appear in the Reports/ directory alongside your existing report files.
RequestResponseLogger.RequestAndResponseLogs (all tests, already in memory)
│
▼
ComponentDiagramGenerator.ExtractRelationships()
│ Filters: ignores responses, override markers, action markers, TrackingIgnore
│ Groups by: (CallerName, ServiceName, Protocol)
│ Counts: total calls, distinct test IDs, distinct HTTP methods
▼
ComponentDiagramGenerator.GeneratePlantUml()
│ Classifies participants as Person() or System()
│ Generates C4 Component PlantUML syntax
▼
ComponentDiagramReportGenerator
│ Writes ComponentDiagram.puml (raw PlantUML)
│ Writes ComponentDiagram.html (HTML wrapper)
▼
Reports/ directory
-
Extract — All
RequestResponseLogentries accumulated during the test run are filtered to only include meaningful request logs (excluding responses, override markers, action start markers, and ignored logs). They are then grouped by the unique combination of(CallerName, ServiceName, Protocol)to discover relationships. -
Aggregate — For each relationship, the generator counts total calls, distinct test IDs (how many tests exercised this path), and the distinct HTTP methods or event types used.
-
Generate — The aggregated relationships are converted into PlantUML C4 Component diagram syntax. Participants are classified as
Person()(pure callers, typically your test client) orSystem()(everything else). -
Write — The PlantUML source is written to a
.pumlfile and wrapped in an HTML page for easy viewing.
Set GenerateComponentDiagram = true on ReportConfigurationOptions:
var options = new ReportConfigurationOptions
{
GenerateComponentDiagram = true,
ComponentDiagramOptions = new ComponentDiagramOptions
{
Title = "My Service Architecture"
}
};When GenerateComponentDiagram is false (the default), no component diagram files are generated and there is zero overhead.
| Property | Type | Default | Description |
|---|---|---|---|
FileName |
string |
"ComponentDiagram" |
Base filename for the generated .puml and .html files |
EmbedInFeaturesReport |
bool |
true |
Reserved for future use — will embed the diagram in the FeaturesReport.html |
Title |
string |
"Component Diagram" |
The title displayed in the PlantUML diagram and HTML page |
PlantUmlTheme |
string? |
null |
Optional PlantUML theme name (e.g. "cerulean", "superhero") |
ParticipantFilter |
Func<string, bool>? |
null |
Predicate to include/exclude participants by name |
RelationshipLabelFormatter |
Func<ComponentRelationship, string>? |
null |
Custom function to format relationship labels |
When enabled, two files are generated in the Reports/ directory:
| File | Description |
|---|---|
ComponentDiagram.puml |
Raw PlantUML C4 source. This is a plain text file that can be version-controlled and diffed to detect architectural changes between commits. |
ComponentDiagram.html |
A standalone HTML page containing the PlantUML source in a collapsible <details> element. Can be opened directly in a browser. |
The filenames can be customised via ComponentDiagramOptions.FileName.
Participants are automatically classified based on their role in the tracked interactions:
| Classification | PlantUML element | Rule |
|---|---|---|
| Person | Person(alias, "Name") |
The participant only appears as a CallerName and never as a ServiceName in any tracked log. This is typically your test client / SUT caller. |
| System | System(alias, "Name") |
The participant appears as a ServiceName in at least one tracked log. This includes your SUT, its downstream dependencies, event brokers, and databases. |
A service that both receives calls and makes downstream calls (e.g. your SUT calling a payment service) is rendered as a System because it appears as a ServiceName.
By default, each relationship label contains:
<Protocol>: <Methods> — <CallCount> calls across <TestCount> tests
Examples:
HTTP: GET, POST — 14 calls across 8 testsPublish: Publish — 3 calls across 2 testsCosmosDB: Query, Upsert — 5 calls across 3 tests
The protocol is determined automatically:
-
HTTP — For standard HTTP requests (
MetaType == Default). The distinct HTTP method names (GET, POST, PUT, etc.) are listed. -
Event/Custom — For non-HTTP interactions (
MetaType == Event), the protocol is the string value of theMethodproperty onRequestResponseLog(e.g."Publish","CosmosDB","SQL").
var options = new ComponentDiagramOptions
{
Title = "Order Service Architecture"
};Apply any built-in PlantUML theme:
var options = new ComponentDiagramOptions
{
PlantUmlTheme = "cerulean"
};This inserts !theme cerulean into the generated PlantUML.
Exclude specific participants from the component diagram:
var options = new ComponentDiagramOptions
{
// Exclude internal helper services and health check endpoints
ParticipantFilter = name => name != "InternalHelper" && name != "HealthCheck"
};The filter is a Func<string, bool> that receives the participant name. Return true to include, false to exclude. When a participant is excluded, all relationships involving that participant (as either caller or service) are removed.
Override the default label format with a custom formatter:
var options = new ComponentDiagramOptions
{
RelationshipLabelFormatter = rel =>
$"{rel.Protocol} ({rel.CallCount} calls)"
};The ComponentRelationship record passed to the formatter contains:
| Property | Type | Description |
|---|---|---|
Caller |
string |
The calling participant name |
Service |
string |
The receiving participant name |
Protocol |
string |
"HTTP" or the event/custom protocol name |
Methods |
HashSet<string> |
Distinct method names (e.g. GET, POST, Publish) |
CallCount |
int |
Total number of calls across all tests |
TestCount |
int |
Number of distinct tests that exercised this relationship |
Given a test suite that exercises an Order Service with downstream dependencies:
@startuml
!include <C4/C4_Component>
title Order Service Architecture
Person(webApp, "WebApp")
System(orderService, "OrderService")
System(paymentService, "PaymentService")
System(kafka, "Kafka")
System(cosmosDb, "CosmosDB")
Rel(webApp, orderService, "HTTP: GET, POST — 14 calls across 8 tests")
Rel(orderService, paymentService, "HTTP: POST — 6 calls across 4 tests")
Rel(orderService, kafka, "Publish: Publish — 3 calls across 2 tests")
Rel(orderService, cosmosDb, "CosmosDB: Query, Upsert — 5 calls across 3 tests")
@endumlThis diagram is derived entirely from actual test HTTP traffic and event tracking — it cannot drift from reality as long as your tests pass.
The component diagram feature works with the standard PlantUML server rendering. If you're using PlantUML IKVM for local rendering, the .puml file can still be rendered locally using the IKVM renderer, but the component diagram report itself currently outputs raw PlantUML source in the HTML file rather than a rendered image.
Future versions may add support for rendering the component diagram as an image via the local renderer.
The component diagram feature has negligible performance impact:
| Aspect | Impact |
|---|---|
| Data source | Reads the same RequestResponseLogger.RequestAndResponseLogs that are already in memory — no additional data collection |
| Processing | Single O(n) pass over log entries with GroupBy — microseconds for typical test suites (100–10,000 logs) |
| Memory | Aggregated relationships are O(unique participant pairs), typically < 50 entries |
| File I/O | Two small files (.puml + .html) written in parallel with existing report generation |
| When disabled | Zero cost — a single if guard at the entry point |
-
Request-only aggregation — Only request logs are counted. Response logs are excluded to avoid double-counting (a request and its response represent a single interaction).
-
Protocol detection — HTTP interactions (
MetaType == Default) are grouped under the"HTTP"protocol. Event/message interactions (MetaType == Event) use theMethodvalue as the protocol name. If multiple event types share the same method name but different service names, they are tracked as separate relationships. -
Override and action markers —
IsOverrideStart,IsOverrideEnd, andIsActionStartlog entries are excluded from aggregation, consistent with how they're handled in sequence diagrams. -
Static data — The component diagram is generated from
RequestResponseLogger.RequestAndResponseLogs, which is a static concurrent queue. In test runs where the queue is shared across frameworks or assemblies, all interactions are included. -
No rendered image — The current implementation outputs raw PlantUML source. You can paste it into plantuml.com or use a PlantUML VS Code extension to render it visually.
// Extract unique relationships from tracked logs
public static ComponentRelationship[] ExtractRelationships(
IEnumerable<RequestResponseLog> logs,
Func<string, bool>? participantFilter = null);
// Generate C4 PlantUML from relationships
public static string GeneratePlantUml(
ComponentRelationship[] relationships,
ComponentDiagramOptions? options = null);// Generate the .puml and .html report files
public static ComponentDiagramResult GenerateComponentDiagramReport(
IEnumerable<RequestResponseLog> logs,
ComponentDiagramOptions? options = null);public record ComponentDiagramResult(
string PumlFilePath, // Absolute path to the generated .puml file
string HtmlFilePath, // Absolute path to the generated .html file
string PlantUml); // The raw PlantUML stringpublic record ComponentRelationship(
string Caller, // Calling participant name
string Service, // Receiving participant name
string Protocol, // "HTTP" or custom protocol name
HashSet<string> Methods, // Distinct method names
int CallCount, // Total calls across all tests
int TestCount); // Distinct test countpublic record ComponentDiagramOptions
{
public string FileName { get; set; } = "ComponentDiagram";
public bool EmbedInFeaturesReport { get; set; } = true;
public string Title { get; set; } = "Component Diagram";
public string? PlantUmlTheme { get; set; }
public Func<string, bool>? ParticipantFilter { get; set; }
public Func<ComponentRelationship, string>? RelationshipLabelFormatter { get; set; }
}public bool GenerateComponentDiagram { get; set; } // Default: false
public ComponentDiagramOptions? ComponentDiagramOptions { get; set; } // Default: nullGetting 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 ClickHouse 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
- Merging Parallel Reports
Reference