Skip to content

[file-diet] Refactor TestDependencyGraph.cs (967 lines) into focused modules #10296

Description

@github-actions

Overview

The file src/Adapter/MSTestAdapter.PlatformServices/Execution/TestDependencyGraph.cs has grown to 967 lines, making it harder to navigate and maintain. This task involves refactoring it into smaller, more focused files.

Current State

  • File: src/Adapter/MSTestAdapter.PlatformServices/Execution/TestDependencyGraph.cs
  • Size: 967 lines
  • Language: C#
Structural Analysis

The file contains a single internal sealed class TestDependencyGraph that handles multiple distinct algorithmic responsibilities:

  1. Edge resolution (ResolveEdges, ~lines 236–340): Resolves [DependsOn] attributes into a prerequisite index array, matching test names to indices and emitting warnings for unresolved dependencies.

  2. Cycle detection (FindCycles, FindCyclePathWithin, ~lines 341–512): Tarjan/DFS-based strongly-connected-component analysis and per-test cycle message generation. ~170 lines of pure graph algorithms.

  3. Sequential set computation (ComputeSequentialSet, PropagateSequential, ~lines 513–588): Marks which tests must be moved to the sequential phase and propagates that flag through the prerequisite graph.

  4. Chunk building (BuildChunks, BuildChunkArrays, HasChunkCycle, FindChunksOnCycle, ~lines 589–881): Projects test-level edges onto scheduling chunks, builds chunk prerequisite arrays, detects and recovers from class-level projection cycles. ~290 lines of the heaviest logic.

  5. Topological ordering & utilities (OrderTopologically, SelectIndices, ~lines 882–967): Kahn's algorithm topological sort and a small index-selection helper.

  6. Data/model (BrokenTest nested class, properties, constructor, ~lines 28–133): The public surface — constructor, properties, and the BrokenTest nested record-like class.

Refactoring Strategy

Proposed File Splits

Based on the file's structure, split it into the following modules:

  1. TestDependencyGraph.cs (data + entry point, ~120 lines)

    • Contents: constructor, public properties, BrokenTest nested class, Build factory method
    • Responsibility: Public API surface and data holder; delegates all computation to the helpers below
  2. TestDependencyGraph.EdgeResolution.cs (partial class, ~120 lines)

    • Contents: ResolveEdges
    • Responsibility: Translates [DependsOn] attribute strings into prerequisite index arrays
  3. TestDependencyGraph.CycleDetection.cs (partial class, ~175 lines)

    • Contents: FindCycles, FindCyclePathWithin
    • Responsibility: SCC/DFS cycle detection and per-test cycle message generation
  4. TestDependencyGraph.SequentialSet.cs (partial class, ~80 lines)

    • Contents: ComputeSequentialSet, PropagateSequential
    • Responsibility: Determines which tests must run in the sequential phase
  5. TestDependencyGraph.ChunkBuilding.cs (partial class, ~300 lines)

    • Contents: BuildChunks, BuildChunkArrays, HasChunkCycle, FindChunksOnCycle
    • Responsibility: Projects test-level edges onto scheduling chunks and recovers from chunk-level cycles
  6. TestDependencyGraph.Ordering.cs (partial class, ~90 lines)

    • Contents: OrderTopologically, SelectIndices
    • Responsibility: Kahn's topological sort and index-selection utilities

Implementation Guidelines

  1. Preserve Behavior: All existing functionality must work identically after the split
  2. Maintain Public API: Keep exported/public symbols accessible with the same names (all members are internal, so partial class is the natural vehicle)
  3. Use partial class: All split files should declare internal sealed partial class TestDependencyGraph in the same namespace — no new types needed
  4. Test After Each Split: Run the test suite after each incremental move (./build.sh -test or the targeted unit-test project)
  5. One File at a Time: Move one logical group at a time to make review easier

Acceptance Criteria

  • Original file is split into focused partial-class files
  • Each new file is under 300 lines
  • All tests pass after refactoring (./build.sh -test)
  • No breaking changes to the internal API
  • The partial keyword is added to the class declaration in every split file

Priority: Medium
Effort: Medium
Expected Impact: Improved code navigability, easier testing of individual algorithm phases, reduced merge conflicts when the dependency-graph feature evolves

🤖 Automated content by GitHub Copilot. Generated by the Daily File Diet workflow. · sonnet46 30.5 AIC · ⌖ 5.81 AIC · ⊞ 8K · [◷]( · )

  • expires on Jul 30, 2026, 7:18 PM UTC

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions