New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ISSUE 2629] Improve readability of containsExactly #2638
[ISSUE 2629] Improve readability of containsExactly #2638
Conversation
throw shouldContainExactlyWithDiffAssertionError(diff, actual, values, info); | ||
} | ||
throw failures.failure(info, elementsDifferAtIndex(actualAsList.get(i), values[i], i, comparisonStrategy)); | ||
throw shouldContainExactlyWithDiffAssertionError(diff, actual, values, info); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to include the first index of the diff elements into the message as well?
+ "Expecting actual:%n" | ||
+ " [\"Yoda\", \"Han\", \"Luke\", \"Anakin\"]%n" | ||
+ "to contain exactly (and in same order):%n" | ||
+ " [\"Yoda\", \"Luke\", \"Han\", \"Anakin\"]%n")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what would be more helpful here in addition to this description is to have the list of mismatches, each mismatch showing the index, the actual element value and the expected element value.
On the example above we could add
but there were differences at these indexes:
- index 1: actual element "Han" but expected was "Luke"
- index 2: actual element "Luke" but expected was "Han"
or
but there were differences at these indexes:
- element at index 1: expected "Han" but was "Luke"
- element at index 2: expected "Luke" but was "Han"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer option 2, WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid the list of mismatches could be huge (e.g. both lists like 1000 elements and they are in the reverse order), so there should be a hard limit on the number of printed mismatches
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Option 3:
@@ -1,4 +1,4 @@
Yoda
-Han
Luke
+Han
Anakin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do like the idea of showing (some) indexes, since it may not be as easy to see the differences at a first glance, but I didn't want to differ to much from the original suggestion in the issue.
A couple of questions arise:
In the case actual and expected are equal but not in order, you would show 2 indexes per mismatch which might be too verbose? Does it only count for equal but unorder comparisons, or do we and how would we want to handle other cases like indexes of unexpected and/or missing elements? Should we consider indexes on almost equal cases like [1, 2, 3] vs [1, 2, 4, 3]
or could it be too complex?
Wouldn't almost all options be big and perhaps unreadable if the lists contain lots of elements? Option 3 would still add 2 lines per mismatch, resulting in a long list where you would have to scroll a while and without color differences to support the -
and +
signs it might be difficult to spot the differences if they are 10 elements apart? I'd think the creator of the unit test should consider smaller data sets to prove the functionality is working. Ordering a set of 10 elements would be as good of a test as ordering 1000 elements, unless you are testing performance in which case you wouldn't look at the sets itself, but the time it took?
Do note
The current implementation of Iterables#assertContainsExactly()
throws a failure at the first difference it has found, after which it will only remember the missing and unexpected elements without any other information. You might currently not even know anything if the actual and expected are of not the same length. So I'm not sure what the impact of such a change will be, I'd have to look into that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was playing around with the amount of indexes to display yesterday and the MAX_ELEMENTS_FOR_PRINTING
is a lot indeed. The first 10 to 50 seems reasonable to me. It could be useful feedback to display something along the lines:
but there were differences at these indexes:
element at index 0: expected "Luke" but was "Han"
...
element at index 9: expected "Anakin" but was "Leia"
Only showing the first 10 mismatches
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What output would you suggest for the following call assertThat(Arrays.asList(10, 1, 2, 3, 4, 5, 6, 7, 8, 9)).containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
?
I guess displaying all the indices as mismatching won't be that helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Giovds LGTM, maybe we should move Only showing the first 10 mismatches
before showing the indexes to be sure users will see it (I'm fine with it at the end too, it's just a suggestion)
but there were differences at these indexes (only showing the first 10 mismatches):
element at index 0: expected "Luke" but was "Han"
...
element at index 9: expected "Anakin" but was "Leia"
If we have less than 10 mismatches, no need to mention only showing the first 10 mismatches
this is a bit of a contrived example @vlsi, I feel the proposed error message is still helpful enough in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also happy to increase to 50 mismatches by default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you mean the example is contrieved? If the use-case is to assert elements in a strict order, then failure cases would likely be "almost matching" like I show here. There was almost an exact match, except the last element is misplaced.
If all the elements are completely shuffled, then there's no way to briefly describe the mismatch. However, if the elements almost match, then AssertJ could help the user to understand the mismatch
I'm not sure about this approach, but I'd like to hear your thoughts on it! |
src/test/java/org/assertj/core/error/ShouldContainExactly_create_Test.java
Outdated
Show resolved
Hide resolved
1005feb
to
d6f1d90
Compare
@Giovds is your PR ready for a review? |
@joel-costigliola Yes, that would be great! |
Removes elementsDifferAtIndex() from assertContainsExactly() and re-use shouldContainExactlyWithDiffAssertionError() in order to show the actual and expected sets entirely. Making the differencesFound() check unnecessary. It also introduces a new shouldContainExactly() and checks for both the missing and unexpected diffs to be empty. Otherwise cases where the actual and expected only differ in order, result into logging of missing elements - which there are none.
Introduces an IndexedDiff to keep track of the diff at an index. If the lists are of the same length and contain the same elements, but are in not in the same order, print the indices - limited to 50 - where a mismatch occurred.
d6f1d90
to
4ba9631
Compare
Removes
elementsDifferAtIndex()
fromassertContainsExactly()
and re-useshouldContainExactlyWithDiffAssertionError()
in order to show the actualand expected sets entirely. Making the
differencesFound()
check unnecessary.It also introduces a new s
houldContainExactly()
and checks for boththe missing and unexpected diffs to be empty. Otherwise cases where the
actual and expected only differ in order, result into logging of missing
elements - which there are none.
Check List:
Following the contributing guidelines will make it easier for us to review and accept your PR.