Skip to content

[file-diet] Refactor AzureDevOpsTestResultsPublisher.cs (828 lines) into focused partial classes #8832

@Evangelink

Description

@Evangelink

Overview

The file src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsTestResultsPublisher.cs has grown to 828 lines, making it harder to navigate and maintain. This task involves splitting it into smaller, single-responsibility partial classes.

Note: XxHashShared.cs (911 lines) is the technically larger file, but it is a verbatim port of dotnet/runtime code and is not a candidate for refactoring.

Current State

  • File: src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsTestResultsPublisher.cs
  • Size: 828 lines
  • Language: C#
Structural Analysis

The file contains a single internal sealed class AzureDevOpsTestResultsPublisher that implements IDataConsumer, ITestSessionLifetimeHandler, and IDisposable. It mixes four distinct concerns in one file:

Lines Responsibility
1–286 Class declaration, fields, constructors, properties, lifecycle methods (Dispose, IsEnabledAsync, OnTestSessionStartingAsync, ConsumeAsync, OnTestSessionFinishingAsync)
288–477 Test result & attachment factoryCreateTestCaseResult, BuildAttachmentsFromTestNode, TruncateInline, GetUtf8ByteCount, TryCreateRunAttachment, CreateResult, BuildTimeoutMessage
473–673 Background flush & batch upload engineBackgroundFlushLoopAsync, FlushPendingResultsAsync, BatchHasAttachments, ShouldFlushUnsafe, UploadPendingRunAttachmentsAsync, UploadResultAttachmentsAsync
675–828 Publish configuration & environment resolutionTryCreatePublishConfiguration, GetRequiredEnvironmentVariable, GetRunName, SanitizeRunNameComponent, GetTargetFrameworkMoniker

Refactoring Strategy

Because the type is sealed, the idiomatic C# approach is partial classes — no visibility changes required and no callers need updating.

Proposed File Splits

  1. AzureDevOpsTestResultsPublisher.cs (~250 lines)

    • Contents: all fields, both constructors, all properties, Dispose, IsEnabledAsync, OnTestSessionStartingAsync, ConsumeAsync, OnTestSessionFinishingAsync
    • Responsibility: Public contract entry-points — lifecycle coordination and data consumption
  2. AzureDevOpsTestResultsPublisher.ResultFactory.cs (~190 lines)

    • Contents: CreateTestCaseResult, BuildAttachmentsFromTestNode, TruncateInline, GetUtf8ByteCount, TryCreateRunAttachment, CreateResult, BuildTimeoutMessage
    • Responsibility: Transform TestNode / SessionFileArtifact data into Azure DevOps API model objects
  3. AzureDevOpsTestResultsPublisher.Flush.cs (~200 lines)

    • Contents: BackgroundFlushLoopAsync, FlushPendingResultsAsync, BatchHasAttachments, ShouldFlushUnsafe, UploadPendingRunAttachmentsAsync, UploadResultAttachmentsAsync
    • Responsibility: Batching, back-pressure, and upload scheduling
  4. AzureDevOpsTestResultsPublisher.Configuration.cs (~155 lines)

    • Contents: TryCreatePublishConfiguration, GetRequiredEnvironmentVariable, GetRunName, SanitizeRunNameComponent, GetTargetFrameworkMoniker
    • Responsibility: Resolve ADO environment variables and build the AzureDevOpsPublishConfiguration value

Implementation Guidelines

  1. Preserve Behavior: All existing functionality must work identically after the split
  2. Maintain Public API: No change to any public or internal symbol names or accessibility
  3. Add partial modifier: Add partial to the class declaration in each new file and in the existing file
  4. No new files elsewhere: No changes needed outside src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/
  5. Test After Each Split: Run ./build.sh -test after splitting each partial file to catch compile errors early
  6. One file at a time: Split one partial at a time to keep reviews manageable

Acceptance Criteria

  • AzureDevOpsTestResultsPublisher.cs is split into four focused partial-class files
  • Each new file is under 300 lines
  • All unit and integration tests pass after refactoring (./build.sh -test)
  • No breaking changes to public or internal API
  • No files modified outside the AzureDevOpsReport project directory

Priority: Medium
Effort: Small (mechanical partial-class split; no logic changes required)
Expected Impact: Improved code navigability, easier code review, reduced merge conflicts on the publisher class

Generated by Daily File Diet · sonnet46 1M ·

  • expires on Jun 6, 2026, 7:41 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