Apply structured assertion messages (RFC 012) to Assert.HasCount / IsEmpty / IsNotEmpty#8262
Apply structured assertion messages (RFC 012) to Assert.HasCount / IsEmpty / IsNotEmpty#8262Evangelink wants to merge 5 commits into
Conversation
…Empty / IsNotEmpty Migrates Assert.HasCount, Assert.IsEmpty, and Assert.IsNotEmpty (and their interpolated-string-handler overloads) to the structured assertion message format defined in RFC 012. The HasCount/IsEmpty evidence block surfaces 'expected count:' and 'actual count:' so the size mismatch is visible at a glance; IsNotEmpty omits the expected line because the only actionable count is the actual zero. The interpolated-string-handler now passes the user-built message directly to the structured report and lets FormatCallSiteExpression reconstruct the call-site (e.g. Assert.HasCount(1, Array.Empty<int>())) so the literal expected count remains visible even on the interpolated path. Updates the affected message-format tests in AssertTests.Items.cs to assert against the new layout. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Migrates Assert.HasCount / Assert.IsEmpty / Assert.IsNotEmpty (including interpolated-string-handler overloads) to the RFC 012 structured assertion message format, updating both resources and unit-test expectations accordingly.
Changes:
- Updated
Assert.Countfailure paths to buildStructuredAssertionMessageinstances with evidence blocks and call-site expressions. - Added new localized summary resource entries (
HasCountFailedSummary,IsEmptyFailedSummary,IsNotEmptyFailedSummary) and regenerated XLFs. - Updated
AssertTests.Itemsexpectations to validate the new structured multiline message layout (including interpolated handler scenarios).
Show a summary per file
| File | Description |
|---|---|
| test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Items.cs | Updates message assertions to the new structured multiline format for count/empty assertions. |
| src/TestFramework/TestFramework/Assertions/Assert.Count.cs | Switches HasCount/IsEmpty/IsNotEmpty failure reporting to StructuredAssertionMessage with evidence + call-site. |
| src/TestFramework/TestFramework/Resources/FrameworkMessages.resx | Adds new summary resource strings for the migrated assertions. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf | Regenerated localization entries for new summary strings. |
| src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf | Regenerated localization entries for new summary strings. |
Copilot's findings
- Files reviewed: 16/16 changed files
- Comments generated: 2
Evangelink
left a comment
There was a problem hiding this comment.
Review: RFC 012 migration for HasCount / IsEmpty / IsNotEmpty
The change is correct, well-structured, and consistent with the RFC 012 series. All 21 review dimensions were applied; most are clean. Two minor points are flagged inline:
Findings
| Severity | Area | Summary |
|---|---|---|
| MODERATE | Code structure | ReportAssertCountFailed dispatches on assertionName == "IsEmpty" (magic string, twice). Consider splitting into two reporters or using an enum. |
| NIT | Resources | HasCountFailMsg / IsNotEmptyFailMsg are now dead strings; still present in .resx + all 14 .xlf files. |
Everything else is clean
- Correctness:
ReportAssertIsNotEmptyFailedhardcoding"0"is correct (only called when the collection is empty). HasCountcall-site reconstruction: usingexpectedText(the captured integer value) asexpression1inFormatCallSiteExpressionis intentional and correct — the literal expected count is always visible even without aCallerArgumentExpressionfor it.- XLF files: regenerated via
UpdateXlfas stated; not hand-edited. Consistent with localization guidelines. FrameworkMessages.Designer.csduplicate hunk in the diff: the file is auto-generated and not tracked in git — the duplicate is a diff artifact, not an actual duplicate in the file.- Test quality: the HEAD of
AssertTests.Items.csuses"Assertion failed."prefix with raw string literals (platform-neutral). No\r\nor fragile assertions. - API surface: no new public API;
BuildUserMessageForCollectionExpressioncleanly removed. NoPublicAPI.Unshipped.txtentry needed. - No threading, security, performance, cross-TFM, or flakiness concerns.
Generated by Expert Code Review (on open) for issue #8262 · ● 17.1M
Use invariant formatting for HasCount call-site arguments while keeping evidence culture-aware, and replace magic assertion-name strings with nameof usage. Add a regression test covering culture-specific negative-sign formatting for the displayed call site. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@copilot resolve the merge conflicts in this pull request |
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Addressed in 9ff9009: the dead
Resolved in 9ff9009. I merged |
| EvidenceBlock evidence = EvidenceBlock.Create() | ||
| .AddLine("actual count:", "0"); |
There was a problem hiding this comment.
Done — the evidence value is now formatted via 0.ToString(CultureInfo.CurrentCulture) and reused for the new WithExpectedAndActual(...) call so the evidence respects non-Latin digit cultures, matching the other count-based assertions.
|
|
||
| StructuredAssertionMessage structured = new(FrameworkMessages.IsNotEmptyFailedSummary); | ||
| structured.WithUserMessage(userMessage); | ||
| structured.WithEvidence(evidence); |
There was a problem hiding this comment.
Done — added structured.WithExpectedAndActual("> 0", actualText) so ExpectedText/ActualText (and the assert.expected/assert.actual data entries) are populated for IsNotEmpty failures, matching the other count-based assertions.
…for IsNotEmpty Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Continues the rollout of RFC 012 — Structured Assertion Messages by migrating
Assert.HasCount/Assert.IsEmpty/Assert.IsNotEmpty(including their interpolated-string-handler overloads) to the structured-message format. Follows the patterns established by previously merged work (#8170, #8187, #8210, #8214) and the in-flight series (#8258, #8259, #8260).Output format
Assert.HasCount(3, collection)(collection has 1 element):Assert.IsEmpty(collection)(collection has 1 element):Assert.IsNotEmpty(Array.Empty<int>()):Notes
HasCountFailedSummary/IsEmptyFailedSummary/IsNotEmptyFailedSummaryresource entries (XLF files regenerated viaUpdateXlf).HasCountreconstructs the call-site asAssert.HasCount(<expected>, <collection>)so the literal expected count remains visible in the call-site line even though it is not captured byCallerArgumentExpression.AssertTests.Items.csto assert against the new layout.Validation
dotnet build src/TestFramework/TestFramework/TestFramework.csproj -c Debug— clean.dotnet test test/UnitTests/TestFramework.UnitTests/TestFramework.UnitTests.csproj -c Debug— 3535/3535 passed.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com