You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Once the assertion refactorings for RFC 012 are complete, every public method on Assert, CollectionAssert, and StringAssert will already be touched. That is a good moment to annotate them with [StackTraceHidden] so the runtime omits MSTest framework frames from Exception.StackTrace on .NET 6+.
Doing this in a single pass after RFC 012 lands keeps the diff localized and avoids re-touching files later.
What
Add [StackTraceHidden] (TFM-gated for net6.0+; polyfill via internal attribute on older TFMs if desired but with no runtime effect) to:
All public methods on Microsoft.VisualStudio.TestTools.UnitTesting.Assert (and all its partial-class files: Assert.AreEqual.cs, Assert.IComparable.cs, Assert.IsNull.cs, Assert.Contains.cs, Assert.IsInstanceOfType.cs, Assert.ThrowsException.cs, Assert.That.cs, Assert.StartsWith.cs, Assert.Matches.cs, Assert.IsTrue.cs, Assert.AreSame.cs, Assert.Inconclusive.cs, Assert.Fail.cs, Assert.Count.cs, Assert.EndsWith.cs, …).
All public methods on CollectionAssert (and its partials: CollectionAssert.Membership.cs, CollectionAssert.Equivalence.cs, CollectionAssert.Equality.cs, CollectionAssert.Type.cs, CollectionAssert.Subset.cs, CollectionAssert.Helpers.cs).
All public methods on StringAssert.
Internal helpers that exclusively serve the assertion call path (StructuredAssertionMessage.Format, AssertionValueRenderer.*, AssertScope notification path, EvidenceBlock.Format, …) so the hidden span is contiguous.
Any Assert*Exception constructors that we want to hide as a frame.
Why
Fixes the AzDO reporter heuristic at the source. Today the AzureDevOpsReporter walks Exception.StackTrace looking for the first frame that isn't an assertion implementation, using a brittle filename heuristic (EndsWith("Assert.cs")) — see Assert.IComparable not compatible with AzDoReport extension #6925. With [StackTraceHidden], those frames are not produced by the CLR in the first place, so the reporter naturally points at user code.
Improves every other stack-trace consumer at the same time. Terminal reporter, IDE test explorer, TRX writer, and any third-party consumer all stop showing the framework's assertion internals.
Cleans up user-visible stacks. Users no longer see noise like at MSTest...Assert.AreEqual[T](T, T, String) above their own test code.
Language-agnostic. The runtime honors [StackTraceHidden] regardless of source language (C# / F# / VB).
Limitations
[StackTraceHidden] only takes effect on .NET 6+. On netstandard2.0 / .NET Framework consumers, the attribute is a no-op and stack frames remain visible. The reporter-side filename fix (separate issue) covers that case.
Acceptance
Every public assertion method on Assert / CollectionAssert / StringAssert carries [StackTraceHidden] on supported TFMs.
A test under Microsoft.Testing.Extensions.UnitTests (or TestFramework.UnitTests) verifies that an AssertFailedException thrown from a partial-class file (e.g., Assert.IComparable.cs, Assert.AreEqual.cs) does not include the framework frame in Exception.StackTrace on .NET 6+.
AzDO reporter test exercises a real assertion failure and asserts the annotation points at the test method file, not the framework file.
Sequencing
Blocked on completion of RFC 012 implementation so the changes stay in a single mechanical pass.
Background
Once the assertion refactorings for RFC 012 are complete, every public method on
Assert,CollectionAssert, andStringAssertwill already be touched. That is a good moment to annotate them with[StackTraceHidden]so the runtime omits MSTest framework frames fromException.StackTraceon .NET 6+.Doing this in a single pass after RFC 012 lands keeps the diff localized and avoids re-touching files later.
What
Add
[StackTraceHidden](TFM-gated fornet6.0+; polyfill via internal attribute on older TFMs if desired but with no runtime effect) to:Microsoft.VisualStudio.TestTools.UnitTesting.Assert(and all its partial-class files:Assert.AreEqual.cs,Assert.IComparable.cs,Assert.IsNull.cs,Assert.Contains.cs,Assert.IsInstanceOfType.cs,Assert.ThrowsException.cs,Assert.That.cs,Assert.StartsWith.cs,Assert.Matches.cs,Assert.IsTrue.cs,Assert.AreSame.cs,Assert.Inconclusive.cs,Assert.Fail.cs,Assert.Count.cs,Assert.EndsWith.cs, …).CollectionAssert(and its partials:CollectionAssert.Membership.cs,CollectionAssert.Equivalence.cs,CollectionAssert.Equality.cs,CollectionAssert.Type.cs,CollectionAssert.Subset.cs,CollectionAssert.Helpers.cs).StringAssert.StructuredAssertionMessage.Format,AssertionValueRenderer.*,AssertScopenotification path,EvidenceBlock.Format, …) so the hidden span is contiguous.Assert*Exceptionconstructors that we want to hide as a frame.Why
AzureDevOpsReporterwalksException.StackTracelooking for the first frame that isn't an assertion implementation, using a brittle filename heuristic (EndsWith("Assert.cs")) — see Assert.IComparable not compatible with AzDoReport extension #6925. With[StackTraceHidden], those frames are not produced by the CLR in the first place, so the reporter naturally points at user code.at MSTest...Assert.AreEqual[T](T, T, String)above their own test code.[StackTraceHidden]regardless of source language (C# / F# / VB).Limitations
[StackTraceHidden]only takes effect on .NET 6+. Onnetstandard2.0/ .NET Framework consumers, the attribute is a no-op and stack frames remain visible. The reporter-side filename fix (separate issue) covers that case.Acceptance
Assert/CollectionAssert/StringAssertcarries[StackTraceHidden]on supported TFMs.Microsoft.Testing.Extensions.UnitTests(orTestFramework.UnitTests) verifies that anAssertFailedExceptionthrown from a partial-class file (e.g.,Assert.IComparable.cs,Assert.AreEqual.cs) does not include the framework frame inException.StackTraceon .NET 6+.Sequencing
Blocked on completion of RFC 012 implementation so the changes stay in a single mechanical pass.
Related: #6925