"Should be...but was" messages can be unusable for C# record types and other default ToString representations
jnm2 opened this issue · comments
We should simply never print out the exact same string for both "should be" and "but was" when the failed assertion is that the objects didn't compare as equal. This happens a lot with C# record types that contain collections, where .Equals
returns false because one or more fields fail reference equality but the ToString printout is the same.
Should be: R { A = 42, B = System.Collections.Immutable.ImmutableArray`1[System.Int32] }
But was: R { A = 42, B = System.Collections.Immutable.ImmutableArray`1[System.Int32] }
Just as bad is when the strings are different, but they are so long that it's nearly impossible to spot the difference. This happens frequently due to:
- number of record properties
- long substrings like
System.Collections.Immutable.ImmutableArray`1[System.Int32]
for types with default ToString() - nested records causing
R { A = R2 { B = ...
but where the difference doesn't appear on the first three (or ten) screens of horizontal scrolling
Goals
-
When at all possible, bring the reader's attention directly to the property path that caused .Equals to fail. This requires some assumptions to be made about the implementation of Equals, but we can tell when it's compiler-generated at least.
- When this is not possible, mention that
Xyz.Equals
returned false so that people know how the equality comparison was done. - If the total ToString is short enough on both expected and actual, and it's visually different, no need to add explanations or highlighting of the differing property paths.
- When this is not possible, mention that
-
Use nicer formatting if ToString is compiler-generated, or if when we call it, we get something very long or something which doesn't differ between expected and actual.
- Use multiline indentation?
- Maybe replace long identical subportions with
...
or similar? - Print out collections as
R { SomeItems = [1, 2, 3] }
using syntax similar to the [collection expressions] syntax coming in C# 12 (formerly called "collection literals": dotnet/csharplang#5354). - Find a way to show when equality fails due to references being different even when the string representation looks the same (including in
[1, 2, 3]
syntax for two different collections with the same contents)