π Duplicate Code Detected: Report Extension Registration Boilerplate
Analysis of commit cf37d3b
Assignee: @copilot
Summary
Three *ReportExtensions.cs files β CtrfReportExtensions, JUnitReportExtensions, and HtmlReportExtensions β each contain an Add{X}ReportProvider extension method that follows an identical 11-parameter CompositeExtensionFactory construction pattern and an identical three-call registration block. Beyond simple repetition, there is a consistency defect: CtrfReportExtensions is missing the if (builder is not TestApplicationBuilder) guard that both JUnitReportExtensions and HtmlReportExtensions include.
Duplication Details
Pattern: Identical 11-parameter CompositeExtensionFactory construction + registration
- Severity: Medium
- Occurrences: 3 β one per report format
- Locations:
src/Platform/Microsoft.Testing.Extensions.CtrfReport/CtrfReportExtensions.cs (lines 24β48)
src/Platform/Microsoft.Testing.Extensions.JUnitReport/JUnitReportExtensions.cs (lines 27β55)
src/Platform/Microsoft.Testing.Extensions.HtmlReport/HtmlReportExtensions.cs (lines 27β55)
CtrfReportExtensions (missing guard):
public static void AddCtrfReportProvider(this ITestApplicationBuilder builder)
{
var commandLine = new CtrfReportGeneratorCommandLine();
var compositeCtrfReportGenerator =
new CompositeExtensionFactory<CtrfReportGenerator>(serviceProvider =>
new CtrfReportGenerator(
serviceProvider.GetConfiguration(),
serviceProvider.GetCommandLineOptions(),
serviceProvider.GetRequiredService<IFileSystem>(),
serviceProvider.GetTestApplicationModuleInfo(),
serviceProvider.GetMessageBus(),
serviceProvider.GetSystemClock(),
serviceProvider.GetEnvironment(),
serviceProvider.GetOutputDevice(),
serviceProvider.GetTestFramework(),
serviceProvider.GetTestApplicationProcessExitCode(),
serviceProvider.GetLoggerFactory().CreateLogger<CtrfReportGenerator>()));
builder.TestHost.AddDataConsumer(compositeCtrfReportGenerator);
builder.TestHost.AddTestSessionLifetimeHandler(compositeCtrfReportGenerator);
builder.CommandLine.AddProvider(() => commandLine);
}
JUnitReportExtensions / HtmlReportExtensions (same structure with guard):
public static void AddJUnitReportProvider(this ITestApplicationBuilder builder)
{
if (builder is not TestApplicationBuilder)
{
throw new InvalidOperationException(ExtensionResources.InvalidTestApplicationBuilderType);
}
// ... same 11-parameter factory construction and registration ...
}
Impact Analysis
- Maintainability: Adding a new report format means copy-pasting this entire block. Any change to the service-provider parameter list (e.g., adding a new injected service to
ReportGeneratorBase) requires updating all three files. This has already led to an inconsistency where CTRF lacks the TestApplicationBuilder guard.
- Bug Risk: The missing
builder is not TestApplicationBuilder guard in CtrfReportExtensions means CTRF report registration will silently succeed against custom ITestApplicationBuilder implementations that cannot honour the extension, while JUnit and HTML fail fast.
- Code Bloat: ~36 lines of near-identical factory construction repeated 3 times across 3 files.
Refactoring Recommendations
-
Immediate fix: add the missing TestApplicationBuilder guard to CtrfReportExtensions
public static void AddCtrfReportProvider(this ITestApplicationBuilder builder)
{
if (builder is not TestApplicationBuilder)
{
throw new InvalidOperationException(ExtensionResources.InvalidTestApplicationBuilderType);
}
// ...
}
- Estimated effort: < 15 minutes
- Benefits: consistent guard behavior across all three report extensions
-
Extract shared factory helper to SharedExtensionHelpers or ReportGeneratorBase
- Consider a static factory helper method in
SharedExtensionHelpers that encapsulates the 11-parameter construction:
// Conceptual β actual generic constraints must accommodate all three generators
internal static CompositeExtensionFactory<TGenerator> CreateReportGeneratorFactory<TGenerator>(...)
where TGenerator : ReportGeneratorBase<TGenerator, CapturedTestResult>
- Estimated effort: 2β4 hours
- Benefits: adding a fourth report format or changing the service-parameter list becomes a one-file change
Implementation Checklist
Analysis Metadata
- Analyzed Files: 3 (
CtrfReportExtensions.cs, JUnitReportExtensions.cs, HtmlReportExtensions.cs)
- Detection Method: Semantic code analysis + structural comparison
- Commit: cf37d3b
- Analysis Date: 2026-06-15
π€ Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account β the account owner did not write or approve this content personally. Generated by the Duplicate Code Detector workflow. Β· 979.9 AIC Β· β 14.3 AIC Β· [β·]( Β· β·)
Add this agentic workflows to your repo
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/duplicate-code-detector.md@main
π Duplicate Code Detected: Report Extension Registration Boilerplate
Analysis of commit cf37d3b
Assignee:
@copilotSummary
Three
*ReportExtensions.csfiles βCtrfReportExtensions,JUnitReportExtensions, andHtmlReportExtensionsβ each contain anAdd{X}ReportProviderextension method that follows an identical 11-parameterCompositeExtensionFactoryconstruction pattern and an identical three-call registration block. Beyond simple repetition, there is a consistency defect:CtrfReportExtensionsis missing theif (builder is not TestApplicationBuilder)guard that bothJUnitReportExtensionsandHtmlReportExtensionsinclude.Duplication Details
Pattern: Identical 11-parameter
CompositeExtensionFactoryconstruction + registrationsrc/Platform/Microsoft.Testing.Extensions.CtrfReport/CtrfReportExtensions.cs(lines 24β48)src/Platform/Microsoft.Testing.Extensions.JUnitReport/JUnitReportExtensions.cs(lines 27β55)src/Platform/Microsoft.Testing.Extensions.HtmlReport/HtmlReportExtensions.cs(lines 27β55)CtrfReportExtensions (missing guard):
JUnitReportExtensions / HtmlReportExtensions (same structure with guard):
Impact Analysis
ReportGeneratorBase) requires updating all three files. This has already led to an inconsistency where CTRF lacks theTestApplicationBuilderguard.builder is not TestApplicationBuilderguard inCtrfReportExtensionsmeans CTRF report registration will silently succeed against customITestApplicationBuilderimplementations that cannot honour the extension, while JUnit and HTML fail fast.Refactoring Recommendations
Immediate fix: add the missing
TestApplicationBuilderguard toCtrfReportExtensionsExtract shared factory helper to
SharedExtensionHelpersorReportGeneratorBaseSharedExtensionHelpersthat encapsulates the 11-parameter construction:Implementation Checklist
if (builder is not TestApplicationBuilder)guard toCtrfReportExtensions.AddCtrfReportProviderAnalysis Metadata
CtrfReportExtensions.cs,JUnitReportExtensions.cs,HtmlReportExtensions.cs)Add this agentic workflows to your repo
To install this agentic workflow, run