Skip to content

[duplicate-code] Duplicate Code: Banner building logic duplicated between BannerMessageHelper and OutputDeviceBannerHelper #9472

Description

@Evangelink

Summary

BannerMessageHelper.BuildBannerMessage (src/Adapter/Shared/BannerMessageHelper.cs) and OutputDeviceBannerHelper.BuildBannerText (src/Platform/Microsoft.Testing.Platform/OutputDevice/OutputDeviceBannerHelper.cs) implement structurally identical banner-building logic: both assemble a string via StringBuilder using the pattern [name] v[version] (UTC [date]) [[arch] - [framework]]. Any format change (e.g. date format, bracket style, separator) must be applied to both files independently.

Duplication Details

Pattern: Structural duplication — banner string construction

  • Severity: Medium
  • Occurrences: 2 instances of the same ~28-line structure
  • Locations:
    • src/Adapter/Shared/BannerMessageHelper.cs (lines 14–41)
    • src/Platform/Microsoft.Testing.Platform/OutputDevice/OutputDeviceBannerHelper.cs (lines 17–43)

Side-by-side structure:

Step BannerMessageHelper.BuildBannerMessage OutputDeviceBannerHelper.BuildBannerText
Name sb.Append(productName) sb.Append(platformInformation.Name)
Version sb.Append(" v"); sb.Append(version) sb.Append($" v{version}")
Commit hash (absent) Appends +<10-char hash> if present
Build date "(UTC " + date.ToShortDateString() + ')' $"(UTC {date:d})"
Dynamic-code guard #if NETCOREAPP RuntimeFeature.IsDynamicCodeCompiled runtimeFeature.IsDynamicCodeSupported
Arch RuntimeInformation.RuntimeIdentifier / ProcessArchitecture (direct) longArchitecture (injected)
Framework RuntimeInformation.FrameworkDescription (direct) runtimeFramework (injected)

Callers:

  • BuildBannerMessage is called by MSTestBannerCapability.GetBannerMessageAsync() to provide an MSTest-branded override banner via IBannerMessageOwnerCapability
  • BuildBannerText is called by TerminalOutputDevice and SimplifiedConsoleOutputDeviceBase to render the MTP default banner when no framework capability overrides it

Impact Analysis

  • Maintainability: If the banner format changes (e.g. switching from (UTC ...) to a different date style, or modifying the [arch - framework] block), both files must be updated separately. The current mismatch between ToShortDateString() and {date:d} formatting is one example of existing drift.
  • Bug Risk: The date formatting is already inconsistent (ToShortDateString() is culture-sensitive; {date:d} with CultureInfo.InvariantCulture is not). A future bug fix in one method could silently leave the other method with the wrong behavior.
  • Code Bloat: ~28 lines of parallel structure that could be extracted into a shared utility.

Refactoring Recommendations

  1. Extract a shared banner-format core into OutputDeviceBannerHelper.BuildBannerText (or a new shared helper)

    • Align the date format (prefer CultureInfo.InvariantCulture with {date:d} for consistency)
    • Accept name, version, buildDate, and an optional [arch - framework] string as parameters
    • Have BannerMessageHelper.BuildBannerMessage pre-compute its arch/framework string (matching the existing TestApplication.cs / CommandLineHandler.cs pattern) and delegate to the shared core
  2. Alternatively, have MSTestBannerCapability use OutputDeviceBannerHelper.BuildBannerText directly by passing productName, the version, and the pre-computed architecture strings — removing the need for a separate BannerMessageHelper entirely.

  3. Estimated effort: Small (1–2 hours). The logic change is mechanical; the main work is choosing where the shared implementation lives given the layering constraints (Adapter cannot depend on Platform internals, so the shared helper must live in a mutually accessible location or the Platform must expose the helper as internal).

Implementation Checklist

  • Review the date formatting difference (ToShortDateString() vs {date:d}) and pick a consistent format
  • Extract the shared banner-format logic to a single location
  • Update BannerMessageHelper and/or OutputDeviceBannerHelper to delegate to the shared logic
  • Update tests / acceptance test snapshot expectations if banner output changes
  • Verify no regressions in --help / --info output

Analysis Metadata

  • Analyzed Files: src/Adapter/Shared/, src/Platform/Microsoft.Testing.Platform/OutputDevice/
  • Detection Method: Semantic code analysis + structural comparison
  • Commit: d8c1e43
  • Analysis Date: 2026-06-27

🤖 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. · 1.3K AIC · ⌖ 24.7 AIC · ⊞ 43.5K · [◷]( · )

Add this agentic workflows to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/duplicate-code-detector.md@main
  • expires on Jun 29, 2026, 5:39 AM UTC

Metadata

Metadata

Assignees

No one assigned

    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