Overview
The file src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs has grown to 832 lines, making it harder to navigate and maintain. This task involves refactoring it into smaller, more focused partial-class files — following the same pattern already used throughout the Assert type.
Note: The technically-largest file (XxHashShared.cs, 911 lines) was intentionally skipped as it is a verbatim port of .NET runtime code and should not be modified here.
Current State
- File:
src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs
- Size: 832 lines
- Language: C#
Structural Analysis
The file contains four distinct concerns bundled into a single partial-class file:
| Lines |
Content |
| 28–157 |
AssertNonStrictThrowsInterpolatedStringHandler<TException> struct — lazy-evaluation ISH for Assert.Throws |
| 159–290 |
AssertThrowsExactlyInterpolatedStringHandler<TException> struct — lazy-evaluation ISH for Assert.ThrowsExactly |
| 291–388 |
Public Throws<TException> sync overloads (string, Func<Exception?,string>, interpolated-string-handler forms) |
| 389–482 |
Public ThrowsExactly<TException> sync overloads (same three forms) |
| 483–610 |
Public ThrowsAsync<TException> and ThrowsExactlyAsync<TException> overloads |
| 611–789 |
Private implementation: ThrowsException, ThrowsExceptionAsync, IsThrowsFailing, IsThrowsAsyncFailingAsync, ReportThrowsFailed, GetDisplayTypeName |
| 790–832 |
Private support types: ThrowsFailureKind enum, ThrowsExceptionState struct, GetTrackedThrowsName helper |
The interpolated-string-handler structs alone account for ~270 lines and are the primary driver of file size.
Refactoring Strategy
Proposed File Splits
Split the file into three focused partial-class files inside src/TestFramework/TestFramework/Assertions/:
-
Assert.ThrowsException.InterpolatedStringHandlers.cs (~270 lines)
- Contents:
AssertNonStrictThrowsInterpolatedStringHandler<TException>, AssertThrowsExactlyInterpolatedStringHandler<TException>
- Responsibility: Compiler-facing interpolated-string-handler structs that enable deferred message formatting; these are purely infrastructure and benefit from being read in isolation
-
Assert.ThrowsException.cs (~270 lines, trimmed from current 832)
- Contents: All public
Throws<TException> and ThrowsExactly<TException> sync overloads, all public ThrowsAsync<TException> and ThrowsExactlyAsync<TException> overloads
- Responsibility: The public assertion API surface — what test authors actually call
-
Assert.ThrowsException.Core.cs (~220 lines)
- Contents:
ThrowsException / ThrowsExceptionAsync private dispatch helpers, IsThrowsFailing / IsThrowsAsyncFailingAsync, ReportThrowsFailed, GetDisplayTypeName, ThrowsFailureKind enum, ThrowsExceptionState struct, GetTrackedThrowsName
- Responsibility: Private implementation shared by all public overloads; keeping it separate makes the public API file noise-free
Implementation Guidelines
- Preserve Behavior: All existing functionality must work identically after the split
- Maintain Public API: Keep all public
AssertNonStrictThrowsInterpolatedStringHandler<TException> and AssertThrowsExactlyInterpolatedStringHandler<TException> symbols exactly as-is (they are referenced in [InterpolatedStringHandlerArgument] attributes in callers)
- Partial class continuity: Each new file must declare
public sealed partial class Assert in namespace Microsoft.VisualStudio.TestTools.UnitTesting
- No import changes needed: All files share the same namespace; no
using directives reference these types from the outside
- Test After Each Split: Run
./build.sh -test after each incremental move to confirm nothing breaks
- One File at a Time: Move the ISH structs first, then the core helpers, to keep diffs reviewable
Acceptance Criteria
Priority: Medium
Effort: Small
Expected Impact: Improved code navigability, easier code review, reduced cognitive load when working on a single concern (e.g., only the ISH structs or only the async overloads)
🤖 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 Daily File Diet workflow. · 159.7 AIC · ⌖ 13.1 AIC · [◷]( · ◷)
Overview
The file
src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cshas grown to 832 lines, making it harder to navigate and maintain. This task involves refactoring it into smaller, more focused partial-class files — following the same pattern already used throughout theAsserttype.Current State
src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.csStructural Analysis
The file contains four distinct concerns bundled into a single partial-class file:
AssertNonStrictThrowsInterpolatedStringHandler<TException>struct — lazy-evaluation ISH forAssert.ThrowsAssertThrowsExactlyInterpolatedStringHandler<TException>struct — lazy-evaluation ISH forAssert.ThrowsExactlyThrows<TException>sync overloads (string,Func<Exception?,string>, interpolated-string-handler forms)ThrowsExactly<TException>sync overloads (same three forms)ThrowsAsync<TException>andThrowsExactlyAsync<TException>overloadsThrowsException,ThrowsExceptionAsync,IsThrowsFailing,IsThrowsAsyncFailingAsync,ReportThrowsFailed,GetDisplayTypeNameThrowsFailureKindenum,ThrowsExceptionStatestruct,GetTrackedThrowsNamehelperThe interpolated-string-handler structs alone account for ~270 lines and are the primary driver of file size.
Refactoring Strategy
Proposed File Splits
Split the file into three focused partial-class files inside
src/TestFramework/TestFramework/Assertions/:Assert.ThrowsException.InterpolatedStringHandlers.cs(~270 lines)AssertNonStrictThrowsInterpolatedStringHandler<TException>,AssertThrowsExactlyInterpolatedStringHandler<TException>Assert.ThrowsException.cs(~270 lines, trimmed from current 832)Throws<TException>andThrowsExactly<TException>sync overloads, all publicThrowsAsync<TException>andThrowsExactlyAsync<TException>overloadsAssert.ThrowsException.Core.cs(~220 lines)ThrowsException/ThrowsExceptionAsyncprivate dispatch helpers,IsThrowsFailing/IsThrowsAsyncFailingAsync,ReportThrowsFailed,GetDisplayTypeName,ThrowsFailureKindenum,ThrowsExceptionStatestruct,GetTrackedThrowsNameImplementation Guidelines
AssertNonStrictThrowsInterpolatedStringHandler<TException>andAssertThrowsExactlyInterpolatedStringHandler<TException>symbols exactly as-is (they are referenced in[InterpolatedStringHandlerArgument]attributes in callers)public sealed partial class Assertinnamespace Microsoft.VisualStudio.TestTools.UnitTestingusingdirectives reference these types from the outside./build.sh -testafter each incremental move to confirm nothing breaksAcceptance Criteria
./build.sh -test)PublicAPI.Unshipped.txtunchanged or updated correctly)#pragma warning disable RS0026at the top of the original file is retained in the file(s) that still carry the affected overloadsPriority: Medium
Effort: Small
Expected Impact: Improved code navigability, easier code review, reduced cognitive load when working on a single concern (e.g., only the ISH structs or only the async overloads)