Skip to content

feat: dependency graph visualization (Mermaid output)#4948

Closed
thomhurst wants to merge 1 commit into
mainfrom
feat/dependency-visualization
Closed

feat: dependency graph visualization (Mermaid output)#4948
thomhurst wants to merge 1 commit into
mainfrom
feat/dependency-visualization

Conversation

@thomhurst

Copy link
Copy Markdown
Owner

Closes #4889. Adds --export-dependency-graph option.

Add the ability to export test dependency graphs as Mermaid (.mmd) files
for visualization. When --export-dependency-graph is passed, a .mmd file
is generated after test execution showing DependsOn relationships as
directed arrows with color-coded nodes (green=passed, red=failed,
yellow=skipped, gray=not run).

Closes #4889

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Overall, this is a clean and well-structured implementation. The Mermaid export logic is clear, edge cases (no dependencies, no tests) are handled, and the opt-in CLI flag design is the right approach. Two issues were found.


Issue 1 — Unnecessary allocation: array passed as List to a method that accepts IReadOnlyList

In ExportDependencyGraphIfRequestedAsync, allTests is AbstractExecutableTest[] (arrays implement IReadOnlyList<T> in .NET), so creating a new List<AbstractExecutableTest>(allTests) just to pass it to GenerateMermaidDiagram allocates an entire new collection unnecessarily.

var testList = new List<AbstractExecutableTest>(allTests);
var mermaidContent = DependencyGraphExporter.GenerateMermaidDiagram(testList);

Fix: pass allTests directly:

var mermaidContent = DependencyGraphExporter.GenerateMermaidDiagram(allTests);

Issue 2 — Mermaid label sanitization misses backticks in generic type names

test.Metadata.TestClassType.Name returns the CLR internal name for generic types, e.g. MyTests1forMyTests. Backtick ( ) is a special character in Mermaid (used for markdown-formatted labels) and is not currently escaped by SanitizeMermaidLabel. This produces malformed or visually broken node labels for any test class that uses generics.

Note: the rest of the TUnit codebase already handles this — TestIdentifierService, MetadataFilterMatcher, and ReflectionExtensions.GetFormattedName all strip the ``N` arity suffix before display.

var className = test.Metadata.TestClassType.Name;
var methodName = test.Metadata.TestMethodName;
nodeLabels[testId] = $"{className}.{methodName}";
testStates[testId] = test.State;

Fix: strip the arity suffix from the class name (consistent with what the rest of TUnit does) and escape backticks in SanitizeMermaidLabel:

// When building the label:
var className = test.Metadata.TestClassType.Name;
// Remove generic arity suffix: 'MyClass`2' -> 'MyClass'
var genericSuffixIndex = className.IndexOf('`');
if (genericSuffixIndex >= 0)
    className = className[..genericSuffixIndex];

// In SanitizeMermaidLabel, add:
.Replace("`", "#96;")

@thomhurst thomhurst closed this Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: dependency graph visualization (Mermaid/GraphML output)

1 participant