Skip to content

🏋️ File Diet: Refactor TestMethodInfo.cs (1113 lines) into focused modules #7984

@Evangelink

Description

@Evangelink

Overview

The file src/Adapter/MSTestAdapter.PlatformServices/Execution/TestMethodInfo.cs has grown to 1113 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/TestMethodInfo.cs
  • Size: 1113 lines
  • Language: C#
Structural Analysis

The file contains a single TestMethodInfo class that has accumulated several distinct responsibilities:

Lines Concern
~23–168 Core class definition, properties, InvokeAsync entry point
~169–329 Argument resolution (ResolveArguments, SetArguments)
~250–329 Timeout resolution (GetTestTimeout, ThrowMultipleAttributesException)
~330–521 Main test execution loop (ExecuteInternalAsync)
~522–597 Exception handling (HandleMethodException)
~598–782 TestCleanup lifecycle (RunTestCleanupMethodAsync, HasCleanupsToInvoke)
~705–857 TestInitialize lifecycle (RunTestInitializeMethodAsync, InvokeInitializeMethodAsync, InvokeGlobalInitializeMethodAsync)
~857–958 Global cleanup invocation (InvokeGlobalCleanupMethodAsync, CaptureExecutionContextAfterFixtureIfNeeded)
~959–1005 TestContext setup (SetTestContext)
~1006–1113 Timeout-aware execution (ExecuteInternalWithTimeoutAsync)

Refactoring Strategy

Since TestMethodInfo is a single class (not multiple classes) and C# supports partial class, the most idiomatic approach for this codebase is to split the implementation into partial class files, each focusing on a specific aspect of test method execution.

Proposed File Splits

  1. TestMethodInfo.cs (keep, trimmed)

    • Contents: Class declaration, fields, properties, constructor, public InvokeAsync entry point
    • Responsibility: Core identity and public API surface (~150 lines)
  2. TestMethodInfo.ArgumentResolution.cs (new partial class)

    • Contents: SetArguments, ResolveArguments
    • Responsibility: Mapping data-driven test arguments to method parameters (~160 lines)
  3. TestMethodInfo.Execution.cs (new partial class)

    • Contents: ExecuteInternalAsync, ExecuteInternalWithTimeoutAsync, GetTestTimeout, ThrowMultipleAttributesException
    • Responsibility: Core test body execution, timeout management (~300 lines)
  4. TestMethodInfo.ExceptionHandling.cs (new partial class)

    • Contents: HandleMethodException
    • Responsibility: Mapping raw exceptions to TestFailedException with proper messages (~75 lines)
  5. TestMethodInfo.Lifecycle.cs (new partial class)

    • Contents: RunTestInitializeMethodAsync, InvokeInitializeMethodAsync, InvokeGlobalInitializeMethodAsync, RunTestCleanupMethodAsync, InvokeCleanupMethodAsync, InvokeGlobalCleanupMethodAsync, HasCleanupsToInvoke, CaptureExecutionContextAfterFixtureIfNeeded
    • Responsibility: TestInitialize / TestCleanup fixture invocation (~430 lines)
  6. TestMethodInfo.TestContext.cs (new partial class)

    • Contents: SetTestContext
    • Responsibility: Wiring ITestContext onto the class instance before test execution (~50 lines)

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
  3. Use partial class: C# partial classes avoid any need to change access modifiers or visibility
  4. Test After Each Split: Run the test suite after each incremental file move
  5. One File at a Time: Split one partial at a time to make review easier

Acceptance Criteria

  • Original file is split into focused partial class files (one per concern)
  • Each new file is under 300 lines
  • All tests pass after refactoring
  • No breaking changes to public API
  • No changes to method signatures or access modifiers

Priority: Medium
Effort: Medium
Expected Impact: Improved code navigability, easier per-concern testing, reduced merge conflicts on busy test execution code

Generated by Daily File Diet · ● 267.4K ·

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions