-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
assertion diffs for multiline-string can become unreadable soup #6757
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
Comments
I like this presentation, but I would like to avoid another option if possible. How about if we have a threshold for differences based on the total number of characters (say 20%+), in which case we fallback to not displaying a diff but show texts horizontally as you suggest? |
That sounds ok. Or perhaps there can just be presentation included, in addition, after the rich diff for high enough verbosity levels. Something that just occurred to me, does pytest have any opinion, introspection, or convention about which is the "actual" and which is the "expected"? I suppose it might have to be just be presented "left" and then "right". |
One good heuristic here would also be to try with indentation removed ( Ratio is also good, of course. FWIW I have this in my conftest to print more with verbosity 3 - very helpful to adjust existing tests: @pytest.hookimpl(hookwrapper=True)
def pytest_assertrepr_compare(config: Config, op: str, left: Any, right: Any) -> Optional[List[str]]:
verbose = config.option.verbose
outcome = yield
result = outcome.get_result() # type: Optional[List[str]]
if not result:
return
lines = result[0]
…
if verbose > 2:
import pprint
full = pprint.saferepr(right).splitlines()
output = [
"Expected:",
] + full
lines.extend(output)
full = pprint.saferepr(left).splitlines()
output = [
"Actual:",
] + full
lines.extend(output)
print(left)
outcome.force_result(result)
|
I played a bit with different outputs for large strings. Here are my thoughts:
Increase usability only for string with reasonable size. If we want to keep this convention we should batch output - it would be more readable.
Version with "?" part: Definitely more complicated to implement but represents the best readability. I am interested in solving this issue. Which version is more suitable? |
My preference would be for a vertical presentation, not side-by-side. It has a few wins in basic practicality
I also don't want to see any extra diff characters inline like "E" on the start of the line or stuff like "?", "-", "++++" within the presentation. |
It is a shame that the PR stalled. I have this workaround in
|
I searched for possible diff algorithms to replace the default difflib algo for the final result. Any of There's specialized diff plugins for git (https://github.com/so-fancy/diff-so-fancy), but I did not check them in detail. Adding a fancy diff for each case might not be sufficiently better than simply displaying both strings alongside each other (what a |
The diff on multiline strings when a string from capysys is differing from expected just by indentation level and/or some leading/trailing whitespace is not great, I think we can do better.
Here's a reproducer, I just dumped some output of
fortune | cowsay
into a raw string for example purposes. Intentionally wrong "expected" to demonstrate the issue: it adds 4 space indentation, i.e. hardcoded in a multiline string within a function body but forgetting to usetextwrap.dedent
on it.When running with increased verbosity
-vv
, it's often complicated to figure out what the issue is without stepping into a debugger. The initial assertion is on one line which may get wrapped in the terminal over multiple lines:However the output appears like the actual was a tuple
('\n'\n ' ____ ...
If you look closer you see it is not even valid Python syntax, just a confusing repr corruption, and the multi-line diff that follows isn't too readable either because of the way the changes are interspersed line by line.
How about an option for the user to suppress pytest's attempts to make a rich diff, and to just to print one, and then print the other, between some horizontal "margins" such as this?
The text was updated successfully, but these errors were encountered: