-
Notifications
You must be signed in to change notification settings - Fork 731
Description
Background and motivation
Initial discussion in #2339 and #2064
I would like to add some overloads to most string equivalency assertions to tackle various use cases (e.g. ignore white space, ignore casing, ignore newline, etc.) with the goal to tackle most existing use cases and to allow for extensibility of the provided mechanism. In order to achieve this, I would add an overload with a Func<EquivalencyAssertionOptions<string>, EquivalencyAssertionOptions<string>> to specify additional options on the string comparison like ignoring leading or trailing white space or newlines to the following string assertions:
- BeEquivalentTo
- ContainEquivalentOf
- EndWithEquivalentOf
- MatchEquivalentOf
- NotBeEquivalentTo
- NotContainEquivalentOf
- NotEndWithEquivalentOf
- NotMatchEquivalentOf
- NotStartWithEquivalentOf
- StartWithEquivalentOf
This also allows specifying an IEqualityComparer<string> as requested in #2339 via the .Using method on the assertion options.
API Proposal
Example for BeEquivalentTo:
public AndConstraint<TAssertions> BeEquivalentTo(string expected,
Func<EquivalencyAssertionOptions<string>, EquivalencyAssertionOptions<string>> config,
string because = "", params object[] becauseArgs)
{
// ...
}
public AndConstraint<TAssertions> NotBeEquivalentTo(string unexpected,
Func<EquivalencyAssertionOptions<string>, EquivalencyAssertionOptions<string>> config,
string because = "", params object[] becauseArgs)
{
// ...
}and add the following methods to the EquivalencyAssertionOptions<T> class:
public EquivalencyAssertionOptions<T> IgnoringLeadingWhitespace()
{
// ...
return this;
}
public EquivalencyAssertionOptions<T> IgnoringTrailingWhitespace()
{
// ...
return this;
}
public EquivalencyAssertionOptions<T> IgnoringCase()
{
// ...
return this;
}API Usage
subject.Should().BeEquivalentTo(expected, o => o
.IgnoringLeadingWhitespace()
.IgnoringTrailingWhitespace()
.IgnoringCase());subject.Should().BeEquivalentTo(expected, o => o
.Using(StringComparer.InvariantCultureIgnoreCase));Alternative Designs
No response
Risks
As I would support arbitrary IEqualityComparer<string>, I can no longer use the IndexOfFirstMismatch extension method, but would have to rewrite it, e.g. as follows:
public static int IndexOfFirstMismatch(this string value, string expected, IEqualityComparer<string> comparer)
{
for (int index = 0; index < value.Length; index++)
{
if (index >= expected.Length || !comparer.Equals(value[index..(index + 1)], expected[index..(index + 1)]))
{
return index;
}
}
return -1;
}The difference is, that I have to slice the strings and get substrings, instead of comparing char by char. This could have a performance impact...
Are you willing to help with a proof-of-concept (as PR in that or a separate repo) first and as pull-request later on?
Yes, please assign this issue to me.