Add structured assertion message infrastructure (RFC 012)#8170
Merged
Evangelink merged 5 commits intoMay 13, 2026
Merged
Conversation
Introduce the foundational types and helpers for structured multi-line assertion failure messages as described in RFC 012: - EvidenceLine: labeled line record struct for evidence blocks - EvidenceBlock: collection of labeled lines with automatic alignment - StructuredAssertionMessage: builder producing the new multi-line format (prefix + summary + user message + evidence block + call-site) - AssertionValueRenderer: renders values per RFC 012 rules (null, quoted strings with escape sequences, booleans, collections as JSON arrays) - AssertFailedException: add ExpectedText/ActualText public properties - Assert: add ReportAssertFailed/ThrowAssertFailed overloads accepting StructuredAssertionMessage No existing assertion methods are changed yet - this PR only introduces the infrastructure that subsequent PRs will use to migrate each assertion method to the new format.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces the initial infrastructure to support RFC 012 structured assertion failure messages in the MSTest TestFramework, including message composition, evidence block formatting, and value rendering, along with plumbing for carrying structured expected/actual values on AssertFailedException.
Changes:
- Added internal structured message builder and evidence formatting types (
StructuredAssertionMessage,EvidenceBlock,EvidenceLine) plus a value renderer (AssertionValueRenderer). - Extended
AssertFailedExceptionwithExpectedText/ActualTextand added structured-message overloads inAssertto populate them. - Added unit tests covering message layout, evidence alignment, and basic value rendering.
Show a summary per file
| File | Description |
|---|---|
| test/UnitTests/TestFramework.UnitTests/Assertions/StructuredAssertionMessageTests.cs | New tests validating multi-line structured message layout rules. |
| test/UnitTests/TestFramework.UnitTests/Assertions/EvidenceBlockTests.cs | New tests validating evidence label alignment and formatting. |
| test/UnitTests/TestFramework.UnitTests/Assertions/AssertionValueRendererTests.cs | New tests validating value rendering rules (null/strings/bools/chars/collections/etc.). |
| test/UnitTests/TestFramework.UnitTests/Assertions/AssertFailedExceptionTests.cs | New tests validating the new ExpectedText/ActualText properties. |
| src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt | Declares the new public API getters for ExpectedText/ActualText. |
| src/TestFramework/TestFramework/Exceptions/AssertFailedException.cs | Adds ExpectedText/ActualText properties to the exception type. |
| src/TestFramework/TestFramework/Assertions/StructuredAssertionMessage.cs | Implements the structured message builder and formatter. |
| src/TestFramework/TestFramework/Assertions/EvidenceLine.cs | Adds a line-level evidence representation (label/value). |
| src/TestFramework/TestFramework/Assertions/EvidenceBlock.cs | Implements evidence block formatting with per-block label alignment. |
| src/TestFramework/TestFramework/Assertions/AssertionValueRenderer.cs | Implements RFC-aligned rendering for strings/control chars/collections/etc. |
| src/TestFramework/TestFramework/Assertions/Assert.cs | Adds structured-message overloads and wires them to AssertFailedException. |
Copilot's findings
- Files reviewed: 11/11 changed files
- Comments generated: 4
…tionale, populate Data dictionary, fix EvidenceBlock comment
Contributor
There was a problem hiding this comment.
Copilot's findings
Comments suppressed due to low confidence (1)
src/TestFramework/TestFramework/Assertions/EvidenceBlock.cs:63
- RFC 012 specifies that multi-line evidence values should be formatted with the label on its own line (e.g.
expected:) and the value starting on the next line, flush-left. EvidenceBlock.Format currently always renderslabel + ' ' + value, which will produce malformed output whenvaluecontains newlines and doesn't meet the RFC/PR description ("multi-line values"). Please update the formatting logic (and add a test) to handle multi-line values explicitly.
/// <summary>
/// Formats the evidence block as aligned label: value lines.
/// Labels are right-padded so all values start at the same column.
/// </summary>
internal string Format()
{
if (_lines.Count == 0)
{
return string.Empty;
}
int maxLabelLength = 0;
foreach (EvidenceLine line in _lines)
{
if (line.Label.Length > maxLabelLength)
{
maxLabelLength = line.Label.Length;
}
}
StringBuilder sb = new();
for (int i = 0; i < _lines.Count; i++)
{
if (i > 0)
{
sb.Append(Environment.NewLine);
}
EvidenceLine line = _lines[i];
// Pad label (which includes trailing colon) to align values, then append a space and value
sb.Append(line.Label.PadRight(maxLabelLength));
sb.Append(' ');
sb.Append(line.Value);
}
- Files reviewed: 11/11 changed files
- Comments generated: 4
…ured-assertion-messages-infrastructure
…ocks, remove IDE0046 pragma, add Data tests - Changed EvidenceBlock from readonly struct to sealed class to avoid NullReferenceException on default instances - Changed StructuredAssertionMessage to support multiple evidence blocks (List<EvidenceBlock>) instead of replacing a single block - Removed file-level IDE0046 pragma from AssertionValueRenderer and converted RenderValue to a switch expression - Added tests verifying exception.Data["assert.expected"] and exception.Data["assert.actual"] are populated by ThrowAssertFailed(StructuredAssertionMessage) - Added test for multiple evidence blocks formatting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces the core building blocks for structured assertion messages as described in RFC 012. This is the first in a series of PRs that will migrate all
Assert.*methods to the new multi-line format.Changes
New types
EvidenceBlock— represents a labeled evidence section (e.g.expected: 42/actual: 37) with automatic column-alignment of labels.StructuredAssertionMessage— builder that composes the full multi-line message: assertion prefix, summary, optional user message, evidence blocks, and call-site expression.AssertionValueRenderer— renders values for evidence blocks following the RFC's value rendering rules (strings quoted, nulls unquoted, collections in[...]notation, control characters escaped).Updated types
AssertFailedException— addedExpectedTextandActualTextproperties to carry structured expected/actual values for IDE integration.Assert— addedReportAssertFailedandThrowAssertFailedoverloads that acceptStructuredAssertionMessage.Tests
StructuredAssertionMessageTests— verifies message layout, blank-line separators, multi-block formatting, and edge cases.EvidenceBlockTests— verifies label alignment, multi-line values, and single-line formatting.AssertionValueRendererTests— verifies rendering of nulls, strings, numbers, booleans, collections, and objects.AssertFailedExceptionTests— verifies the newExpectedText/ActualTextproperties.Public API
New public API entries added to
PublicAPI.Unshipped.txt.Follow-up PRs
IsTrue,IsFalse,IsNull,IsNotNull)AreEqual,AreNotEqual)AreSame,AreNotSame,IsInstanceOfType, etc.)Throws,ThrowsExactly,ThrowsAsync, etc.)Contains,StartsWith,EndsWith,MatchesRegex, etc.)Fail/Inconclusive