Skip to content

[file-diet] Refactor CtrfReportEngine.cs (778 lines) into focused smaller files #9054

@Evangelink

Description

@Evangelink

Overview

The file src/Platform/Microsoft.Testing.Extensions.CtrfReport/CtrfReportEngine.cs has grown to 778 lines, making it harder to navigate and maintain. This task involves refactoring it into smaller, more focused files.

Current State

  • File: src/Platform/Microsoft.Testing.Extensions.CtrfReport/CtrfReportEngine.cs
  • Size: 778 lines
  • Language: C#
Structural Analysis

The file contains a single CtrfReportEngine class with four distinct responsibility groups:

  1. Orchestration (lines 1–87): Constructor, GenerateReportAsync, GenerateReportCoreAsync — the top-level entry point that wires the other groups together.

  2. File I/O (lines 89–174): WriteWithRetryAsync, SplitCtrfExtension, WriteAsync — collision-safe file writing with a retry loop.

  3. File naming (lines 175–421): BuildDefaultFileName, ResolveJsonFileName, GetTargetFrameworkMoniker, GetCtrfOsPlatform, ReplaceInvalidFileNameChars, IsInvalidFileNameChar, IsReservedFileName — composing output paths, sanitizing characters, and avoiding Windows reserved names.

  4. JSON serialization (lines 422–778): BuildCtrfJson, WriteTest, WriteRetryAttempt, HasSameKeyEarlier, WriteOutputLines, CollapseAttempts, CollapsedTestResult — the bulk of the file; converts CapturedTestResult[] to a CTRF-compliant JSON byte array.

Refactoring Strategy

Proposed File Splits

Based on the file's structure, split it into the following files (using partial class or companion static helpers to avoid API churn):

  1. CtrfReportEngine.cs (keep, trimmed to orchestration only)

    • Contents: constructor, fields, GenerateReportAsync, GenerateReportCoreAsync
    • Responsibility: Entry point — coordinates naming, serialisation, and I/O
  2. CtrfReportFileWriter.cs (new, extracted as private static helpers or partial class)

    • Contents: WriteWithRetryAsync, SplitCtrfExtension, WriteAsync
    • Responsibility: Collision-safe file persistence
  3. CtrfReportFileNaming.cs (new)

    • Contents: BuildDefaultFileName, ResolveJsonFileName, GetTargetFrameworkMoniker, GetCtrfOsPlatform, ReplaceInvalidFileNameChars, IsInvalidFileNameChar, IsReservedFileName
    • Responsibility: All output-path construction and sanitization rules, including Windows reserved-name detection
  4. CtrfJsonSerializer.cs (new)

    • Contents: BuildCtrfJson, WriteTest, WriteRetryAttempt, HasSameKeyEarlier, WriteOutputLines, CollapseAttempts, CollapsedTestResult
    • Responsibility: Converting CapturedTestResult[] to a CTRF-compliant JSON byte array; the largest cohesive concern (~350 lines)

Implementation Guidelines

  1. Preserve Behavior: All existing functionality must work identically after the split
  2. Maintain Internal API: CtrfReportEngine is internal sealed — no public surface change is needed, but the extracted helpers must remain accessible within the assembly (use internal static or partial class)
  3. Test After Each Split: Run the test suite (./build.sh -test) after each incremental extraction
  4. One File at a Time: Extract one group at a time to keep diffs reviewable
  5. No Namespace Changes: Keep everything in Microsoft.Testing.Extensions.CtrfReport

Acceptance Criteria

  • Original file is split into focused modules as proposed above
  • Each new file is under 300 lines
  • All tests pass after refactoring (./build.sh -test)
  • No breaking changes to the internal or public API
  • All cross-file references compile correctly

Priority: Medium
Effort: Small — the class is already well-structured; the methods have low coupling and clear groupings
Expected Impact: Improved code navigability, easier testing of individual concerns, reduced merge conflicts when CTRF spec evolves

🤖 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 Daily File Diet workflow. · 147.8 AIC · ⌖ 12.8 AIC · [◷]( · )

  • expires on Jun 13, 2026, 7:50 PM UTC

Metadata

Metadata

Labels

type/automationCreated or maintained by an agentic workflow.type/tech-debtCode health, refactoring, simplification.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions