Skip to content

Issue3918 white space#4664

Merged
OsirisTerje merged 6 commits intonunit:masterfrom
manfred-brands:Issue3918_WhiteSpace
Mar 27, 2024
Merged

Issue3918 white space#4664
OsirisTerje merged 6 commits intonunit:masterfrom
manfred-brands:Issue3918_WhiteSpace

Conversation

@manfred-brands
Copy link
Copy Markdown
Member

Fixes #3918

Adds preparation work for #4662

There are two new constraints:

One to match String.IsNullOrWhiteSpace . This I modeled on 'Empty':

Assert.That(<s>, Is.WhiteSpace)
Assert.That(<s>, Is.Not.WhiteSpace)

The other is a modifier on existing constrains, which I modeled on IgnoreCase:

Assert.That("Hello World"), Is.EqualTo("HelloWorld").IgnoreWhiteSpace)

Adding the constraint was easy, to get sensible error messages in case of failure where strings have different white space was harder. In case of mis-matched white-space, the message now contains two carrots, one for expected and one for actual:

Expected: "abc def", ignoring white-space
-----------------^
But was:  "a b c d e g"
---------------------^

@OsirisTerje
Copy link
Copy Markdown
Member

Awesome!

Copy link
Copy Markdown
Member

@OsirisTerje OsirisTerje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome work! Really like the changes in ConstraintExpression to the Append method, making it generic fix the typecasting that is all over the other constraints. Very good!

@manfred-brands manfred-brands marked this pull request as draft March 17, 2024 08:50
@manfred-brands
Copy link
Copy Markdown
Member Author

@OsirisTerje The change to Append is an breaking change as it changes the signature of a public method in a public class.
I managed to keep the original and add the new one. Luckily the compiler is smart enough to distinguish.

Whilst updating the documentation, I noticed an issue with the reporting when texts are too long.
Put PR in draft until I sorted this out.

@manfred-brands manfred-brands force-pushed the Issue3918_WhiteSpace branch 2 times, most recently from 7db260e to 21f195b Compare March 18, 2024 02:43
to:
- AnyOfConstraint
- CollectionItemsEqualConstaint
- ContainsConstraint
- EqualConstraint
- UniqueItemsConstraint

Updates to Clip String
Requires individual clipping when white-space is ignored.
We then also need to show two different ^ to indicate the mismatched
location.
@manfred-brands
Copy link
Copy Markdown
Member Author

All issues fixed, PR ready.

Copy link
Copy Markdown
Member

@mikkelbu mikkelbu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. I mostly have minor questions and/or comments

/// <param name="ignoreWhiteSpace">If true, white space is ignored in locating the point where the strings differ</param>
/// <param name="clipping">If true, the strings should be clipped to fit the line</param>
public abstract void DisplayStringDifferences(string expected, string actual, int mismatch, bool ignoreCase, bool clipping);
public abstract void DisplayStringDifferences(string expected, string actual, int mismatchExpected, int mismatchActual, bool ignoreCase, bool ignoreWhiteSpace, bool clipping);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this change breaking? A public (abstract) class containing a public (abstract) method

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it would be. Thanks for noticing!

The problem then is that if I leave the original signature, I cannot do the message improvements.
Even adding a new abstract method would be breaking.
I think adding a a new virtual method it would be fine as it can be resolved without an implementation having to implement it. The default implementation would call into the original method unless:

if (ignoreWhiteSpace && mismatchExpected != mismatchActual)
{
    throw new NotImplementedException("Please override to show difference with 'ignoreWhiteSpace'");
}

Comment on lines +89 to +94
"surname": Doe"
}
]
""";
const string condensedJson = """
"persons":[{"name":"John","surname":"Smith"},{"name": "Jane","surname": Doe"}]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the missing " before Doe on purpose?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it wasn't. I only noticed this myself when I had copied this example into the documentation and the strings were not formatted as expected. Initially I blamed it on the new """ string syntax until I spotted the missing ".

" added in two places.

if (mismatchExpected >= 0 && mismatchExpected != mismatchActual)
WriteCaretLine(mismatchExpected);
WriteActualLine(actual);
//DisplayDifferences(expected, actual);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove this line?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume you mean the one commented out and not the one I just added?

I suspect this line was commented out when the WriteCaretLine was added, but all of this was already there in the first commit to the repo 15 years ago. I agree it should be removed.

Comment on lines +318 to +320
[TestCase(S52, 26, 0, "abcdefghijklmnopqrstuvwxyz...", TestName = "ClipAtEnd")]
[TestCase(S52, 26, 26, "...ABCDEFGHIJKLMNOPQRSTUVWXYZ", TestName = "ClipAtStart")]
[TestCase(S52, 22, 26, "...ABCDEFGHIJKLMNOPQRSTUV...", TestName = "ClipAtStartAndEnd")]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related to you comment on the PR (pasted below)? If not then what is this change about?

Whilst updating the documentation, I noticed an issue with the reporting when texts are too long.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it isn't. The original code had one places determining if the actual visible string should be clipped and in the called method it actually reduced the maxDisplayLength. I moved all determination code into the first method ClipWhenNeeded and reduced the ClipString method to do only the clipping to the length passed in.
This means that the length passed into the ClipString method is 3 or 6 less than previously and hence the updated numbers in the test.

sb.Append($"\\x{(int)c:X4}");
break;
int originalIndex = index;
StringBuilder sb = new(s.Length + 32);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 32 ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Purely to prevent an re-allocation/copy in most cases when there are a few characters to escape.
It could be any number. I can make it the magic '42' (“The Hitchhiker's Guide to the Galaxy”) or 10.

public static string ClipString(string s, int clipLength, int clipStart)
{
int clipLength = maxStringLength;
StringBuilder sb = new StringBuilder();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we set this to be of a certain size - e.g. s.length + 6?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case anyone ever changes the value of ELLIPSIS, I changed it to s.Length + 2 * ELLIPSIS.Length

@manfred-brands manfred-brands requested a review from mikkelbu March 20, 2024 01:21
@OsirisTerje
Copy link
Copy Markdown
Member

OsirisTerje commented Mar 25, 2024

@mikkelbu @manfred-brands Is this ready now to be merged ?

@manfred-brands
Copy link
Copy Markdown
Member Author

@OsirisTerje I think so, but as I made changes after the review from @mikkelbu, I didn't know if he wants to look at it again.

@OsirisTerje
Copy link
Copy Markdown
Member

OsirisTerje commented Mar 27, 2024

I'll merge this now. @mikkelbu did approve earlier. If he finds more to change, we can add a new PR to address that. I can't see anything really.
With this merged, we can then continue with #4662

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

String comparison without whitespace

3 participants