Skip to content

[duplicate-code] Duplicate Code: CIEnvironmentDetector Duplicated Across TestFramework and Platform #8985

@Evangelink

Description

@Evangelink

🔍 Duplicate Code Detected: CIEnvironmentDetector Class

Analysis of commit 3e056b0

Assignee: @copilot

Summary

The CIEnvironmentDetector class is nearly identically duplicated in two separate namespaces: Microsoft.VisualStudio.TestTools.UnitTesting (TestFramework) and Microsoft.Testing.Platform.Helpers (MTP). Both classes contain the same arrays of CI environment variable names and the same IsCIEnvironment() detection logic (~100 lines each).

Duplication Details

Pattern: Near-identical CIEnvironmentDetector class

  • Severity: Medium
  • Occurrences: 2 instances
  • Locations:
    • src/TestFramework/TestFramework/Internal/CIEnvironmentDetector.cs (lines 23–114)
    • src/Platform/Microsoft.Testing.Platform/Helpers/CIEnvironmentDetector.cs (lines 15–110)
  • Code Sample (same arrays in both files):
// Same CI-system variable arrays in both files:
private static readonly string[] BooleanVariables = [
    "TF_BUILD",
    "GITHUB_ACTIONS",
    "APPVEYOR",
    "CI",
    "TRAVIS",
    "CIRCLECI",
];

private static readonly string[][] AllNotNullVariables = [
    ["CODEBUILD_BUILD_ID", "AWS_REGION"],
    ["BUILD_ID", "BUILD_URL"],
    ["BUILD_ID", "PROJECT_ID"],
];

private static readonly string[] IfNonNullVariables = [
    "TEAMCITY_VERSION",
    "JB_SPACE_API_URL",
];

// Same IsCIEnvironment() logic in both files
public bool IsCIEnvironment() { ... }

Differences are minimal:

  • Namespace (Microsoft.VisualStudio.TestTools.UnitTesting vs Microsoft.Testing.Platform.Helpers)
  • [Embedded]/[ExcludeFromCodeCoverage] attributes only on the Platform version
  • A static Instance property only in the TestFramework version
  • string.IsNullOrEmpty vs global::Microsoft.Testing.Platform.RoslynString.IsNullOrEmpty

Impact Analysis

  • Maintainability: Any CI system addition/removal requires changing two files. The current lists are already out of sync — the Platform version has XML docs on the constructor while the TestFramework version marks it internal /* for testing purposes */.
  • Bug Risk: If a new CI provider is added to one file but not the other, the two assemblies will behave differently when detecting the CI environment.
  • Code Bloat: ~100 lines of near-identical code maintained in two places.

Refactoring Recommendations

  1. Use a source-linked file (preferred for embedded classes):

    • Keep the canonical copy in the Platform project (or TestFramework) and add a linked file in the other project via <Compile Include="..." Link="..." />
    • Adjust RoslynString.IsNullOrEmpty vs string.IsNullOrEmpty differences via a #if guard or a shared helper
  2. Move to a shared helper project:

    • Add to SharedExtensionHelpers or a similar internal shared project
    • Reference from both TestFramework and Platform
  3. Add a comment documenting the intentional copy if sharing is impractical:

    • At minimum add a comment pointing to the authoritative copy

Implementation Checklist

  • Review duplication findings
  • Decide on sharing strategy (linked file vs shared package vs documented copy)
  • Unify the CI variable arrays and detection logic
  • Update tests that use IEnvironment mocks against this class
  • Verify no functionality broken after consolidation

Analysis Metadata

  • Analyzed Files: 2
  • Duplicated Lines: ~90 lines per file (180 lines total, ~90 lines redundant)
  • Detection Method: Semantic code analysis + diff comparison
  • Commit: 3e056b0
  • Analysis Date: 2026-06-10

🤖 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.{ai_credits_suffix} · [◷]( · )

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 12, 2026, 5:55 AM 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