Overview
The file src/Adapter/MSTestAdapter.PlatformServices/Execution/TestClassInfo.cs has grown to 832 lines, making it harder to navigate and maintain. This task involves refactoring it into smaller, more focused files that separate distinct responsibilities.
Current State
- File:
src/Adapter/MSTestAdapter.PlatformServices/Execution/TestClassInfo.cs
- Size: 832 lines
- Language: C#
Structural Analysis
TestClassInfo manages the entire lifecycle of test class execution in MSTest:
-
Class metadata and configuration (lines 21-251)
- Properties:
ClassType, Constructor, TestContextProperty, ClassInitializeMethod, ClassCleanupMethod, TestInitializeMethod, TestCleanupMethod
- Collections:
BaseClassInitMethods, BaseClassCleanupMethods, BaseTestInitializeMethodsQueue, BaseTestCleanupMethodsQueue
- Timeout dictionaries for initialize/cleanup methods
-
Class initialization orchestration (lines 268-529)
RunClassInitializeAsync() - main entry point for class initialization
GetResultOrRunClassInitializeAsync() - caching and STA thread handling
TryGetClonedCachedClassInitializeResult() - result cloning logic
InvokeInitializeMethodAsync() - individual initialize method invocation
-
Class cleanup orchestration (lines 578-799)
ExecuteClassCleanupAsync() - main cleanup execution
RunClassCleanupAsync() - STA thread handling for cleanup
InvokeCleanupMethodAsync() - individual cleanup method invocation
-
Utility methods (lines 806-831)
ResolveTestContext() - static helper for resolving TestContext property
The class also manages:
- Concurrency control via
_testClassExecuteSyncSemaphore
- Result caching for class initialize
- STA apartment state handling for both initialize and cleanup
- Exception handling and wrapping
- Execution context capturing for async locals propagation
Refactoring Strategy
Proposed File Splits
Based on the file's structure, split it into the following modules:
-
TestClassInfo.cs (core class, ~200 lines)
- Core class definition and properties
- Constructor
- Simple property accessors
- Public API surface
- Responsibility: Central metadata and configuration holder for test classes
-
TestClassInitializer.cs (~250 lines)
RunClassInitializeAsync()
GetResultOrRunClassInitializeAsync()
TryGetClonedCachedClassInitializeResult()
InvokeInitializeMethodAsync()
- All initialization-related logic including STA thread handling
- Responsibility: Orchestrate class initialization lifecycle with caching and threading support
-
TestClassCleanup.cs (~250 lines)
ExecuteClassCleanupAsync()
RunClassCleanupAsync()
InvokeCleanupMethodAsync()
- All cleanup-related logic including STA thread handling
- Responsibility: Orchestrate class cleanup lifecycle with threading support
-
TestContextResolver.cs (~50 lines)
ResolveTestContext() static utility
- Any future test context-related utilities
- Responsibility: Resolve and validate TestContext property via reflection
Implementation approach: Use partial classes to maintain the existing public API while splitting the implementation across files. This is idiomatic in .NET and already used extensively in the MSTest codebase (e.g., Assert class has 33 partial files).
Implementation Guidelines
- Use partial classes: Declare
TestClassInfo as internal sealed partial class TestClassInfo in each file
- Preserve Behavior: All existing functionality must work identically after the split
- Maintain Public API: Keep all public/internal members accessible with the same signatures
- Update Imports: Ensure each new file has the necessary using directives
- Test After Each Split: Run unit tests after each incremental change
- One File at a Time: Split one module at a time to make review easier
- Keep concurrency control: The
_testClassExecuteSyncSemaphore should remain in the core TestClassInfo.cs file as it's shared across initialization and cleanup
Acceptance Criteria
Priority: Medium
Effort: Medium (requires careful extraction while maintaining thread-safety and async behavior)
Expected Impact: Improved code navigability, easier maintenance, clearer separation of concerns between initialization and cleanup lifecycles
Generated by Daily File Diet · ● 5.1M · ◷
Overview
The file
src/Adapter/MSTestAdapter.PlatformServices/Execution/TestClassInfo.cshas grown to 832 lines, making it harder to navigate and maintain. This task involves refactoring it into smaller, more focused files that separate distinct responsibilities.Current State
src/Adapter/MSTestAdapter.PlatformServices/Execution/TestClassInfo.csStructural Analysis
TestClassInfomanages the entire lifecycle of test class execution in MSTest:Class metadata and configuration (lines 21-251)
ClassType,Constructor,TestContextProperty,ClassInitializeMethod,ClassCleanupMethod,TestInitializeMethod,TestCleanupMethodBaseClassInitMethods,BaseClassCleanupMethods,BaseTestInitializeMethodsQueue,BaseTestCleanupMethodsQueueClass initialization orchestration (lines 268-529)
RunClassInitializeAsync()- main entry point for class initializationGetResultOrRunClassInitializeAsync()- caching and STA thread handlingTryGetClonedCachedClassInitializeResult()- result cloning logicInvokeInitializeMethodAsync()- individual initialize method invocationClass cleanup orchestration (lines 578-799)
ExecuteClassCleanupAsync()- main cleanup executionRunClassCleanupAsync()- STA thread handling for cleanupInvokeCleanupMethodAsync()- individual cleanup method invocationUtility methods (lines 806-831)
ResolveTestContext()- static helper for resolving TestContext propertyThe class also manages:
_testClassExecuteSyncSemaphoreRefactoring Strategy
Proposed File Splits
Based on the file's structure, split it into the following modules:
TestClassInfo.cs(core class, ~200 lines)TestClassInitializer.cs(~250 lines)RunClassInitializeAsync()GetResultOrRunClassInitializeAsync()TryGetClonedCachedClassInitializeResult()InvokeInitializeMethodAsync()TestClassCleanup.cs(~250 lines)ExecuteClassCleanupAsync()RunClassCleanupAsync()InvokeCleanupMethodAsync()TestContextResolver.cs(~50 lines)ResolveTestContext()static utilityImplementation approach: Use partial classes to maintain the existing public API while splitting the implementation across files. This is idiomatic in .NET and already used extensively in the MSTest codebase (e.g.,
Assertclass has 33 partial files).Implementation Guidelines
TestClassInfoasinternal sealed partial class TestClassInfoin each file_testClassExecuteSyncSemaphoreshould remain in the coreTestClassInfo.csfile as it's shared across initialization and cleanupAcceptance Criteria
./build.sh -teston Linux/macOS or.uild.cmd -teston Windows)Priority: Medium
Effort: Medium (requires careful extraction while maintaining thread-safety and async behavior)
Expected Impact: Improved code navigability, easier maintenance, clearer separation of concerns between initialization and cleanup lifecycles