Fix formatting exception when comparing strings containing braces#3151
Fix formatting exception when comparing strings containing braces#3151dennisdoomen merged 3 commits intomainfrom
Conversation
Co-authored-by: dennisdoomen <[email protected]>
Test Results 37 files ± 0 37 suites ±0 2m 43s ⏱️ -22s Results for commit e773f85. ± Comparison against base commit 4762446. This pull request removes 10 and adds 10 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
Pull Request Test Coverage Report for Build 21300676482Details
💛 - Coveralls |
Qodana for .NETIt seems all right 👌 No new problems were found according to the checks applied 💡 Qodana analysis was run in the pull request mode: only the changed files were checked Contact Qodana teamContact us at [email protected]
|
Co-authored-by: dennisdoomen <[email protected]>
233a12c to
e773f85
Compare
|
|
||
| if (IncludeFullDetails && wasTruncated) | ||
| { | ||
| sb.AppendFormat(CultureInfo.InvariantCulture, |
There was a problem hiding this comment.
If we polyfill StringBuilder.Append in StringBuilderExtensions we can avoid the intermediate string.
sb.Append(CultureInfo.InvariantCulture,
$"""
Full expectation:
{expected.RenderAsIndentedBlock()},
Full subject:
{subject.RenderAsIndentedBlock()}
""");For StringBuilderExtensions
public static StringBuilder AppendLine(this StringBuilder stringBuilder, IFormatProvider provider, FormattableString formattable) =>
stringBuilder.AppendLine(string.Create(provider, formattable));
public static StringBuilder Append(this StringBuilder stringBuilder, IFormatProvider provider, FormattableString formattable) =>
stringBuilder.Append(string.Create(provider, formattable));There was a problem hiding this comment.
Is that a suggestion? And why is that important? This code is only executed for a failing test and when the full details are requested.
There was a problem hiding this comment.
It's a suggestion and not blocking for approving the PR.
Be()assertion throwsFormatExceptioninstead of test failure when comparing strings containing{or}characters.Root Cause
StringEqualityStrategy.GetMismatchSegmentForLongStringsusedStringBuilder.AppendFormatwith an interpolated string literal containing user values:This causes double-interpretation: string interpolation inserts user values first, then
AppendFormatinterprets the result as a format string. Braces in user strings are mistaken for format placeholders.Changes
string.Create()to build the interpolated string, thenAppend()the result.AsNonFormattable()calls since we no longer useAppendFormatThis ensures user strings are never reinterpreted as format strings.
Original prompt
This section details on the original issue you should resolve
<issue_title>Be() throws System.FormatException when expected value contains "{"</issue_title>
<issue_description>### Description
Hi,
I was writing tests for my code formatter and came across this weird behavior - FluentAssertions use
string.Formatwithout sanitizing the values (but that is not optimal solution IMHO).It is kind of annoying:
This works just fine:
This throws throws System.FormatException.
Thanks
Reproduction Steps
P.S.: The fact that it fails around 79-80 is funny.
Expected behavior
Be should throw only XunitException for string comparisons - strings are either equal or not equal.
IMHO, building final assertion message incrementally using multiple string.Format calls feels too hacky.
Probably, a better approach would be to create some tree-ish type and walking over it to build the final string. But I'm not regularly programming in C# so don't listen to me. :)
Actual behavior
In reproduction tests:
NotOktest fails - the actual string is "{" and then 80+ "x"s and it is compared to an empty string.Oktest succeeds but it has string.Format error in the assertion message - the actual string is "{" and 79 "x"s.Full dotnet test result: