Preventing truncation of long strings in pytest
Asked Answered
S

3

16

I have written a test harness for system tests of our code using pytest. These tests are used in our continuous integration system so I am using the junit xml output option. The truncation of long strings by pytest is causing me problems. I know I can prevent it using the -vv option but then that gives verbose output for the results of each test which is difficult to read. Essentially I want a different way to prevent the truncation of the long string at least in the junit xml file. If it also worked in the console output, that would be better but not essential.

Our code produces reports with a large number of values and I compare the output to a set of output known to be correct. I am reporting all fields that are in error not just the first error. So I am generating a list of strings with one error per string. I then join the strings with newlines to create one long string and long string that contains all the errors. If the assertion fails I need to see the entire contents of the string which could be several hundred lines.

errors = []
error.extend(get_report_errors())
s = '\n'.join(errors)
assert (s == '')

Any suggestions

I am using python 2.6 and 2.7 and pytest 2.3.5. I can upgrade the version of pytest of needed.

Scotfree answered 4/10, 2013 at 1:7 Comment(1)
Also see this related question and relevant answer, which resolves this by passing the --showlocals option to pytest and then manually inspecting output for the value of the s local variable assigned above.Kozloski
D
12

A simple hack that works with higher versions of pytest (e.g. 5) is to modify the values that control how much of the diff is truncated.

# conftest.py
from _pytest.assertion import truncate
truncate.DEFAULT_MAX_LINES = 9999
truncate.DEFAULT_MAX_CHARS = 9999  

This allows you to leave verbosity at 0 but still see what failed for long comparisons. Just make sure to check whenever you update pytest to make sure the internals didn't change since this is mucking around inside there.

Edit As Cecil Curry points out, this hack is not intended as a complete solution. Hopefully this feature gets added to Pytest so we can get what we want without breaking encapsulation. :)

Domesticate answered 20/2, 2020 at 14:9 Comment(3)
Yikes. On the one hand, this is temporarily awesome. On the other hand, this violates privacy encapsulation and is thus guaranteed to fail under a future pytest version. That's not quite so awesome.Kozloski
You could also do truncate.DEFAULT_MAX_CHARS = truncate.DEFAULT_MAX_LINES * (os.environ.get("COLUMNS", 80) + 1) to fit DEFAULT_MAX_LINES of content (including trailing newline) in the output.Fernand
Is "columns" being an env var a linux thing or something? It's not on windowsSusi
P
1

Another trick I just used for this (but for manual inspection, nothing automated beyond pytest itself) was to use the output as the second 'argument' to assert (i.e., as the 'assert message'). Pytest shows the full assert message without truncation. So I had:

assert shortString in veryLongString

and I wanted to see veryLongString without truncation so I changed that to:

assert shortString in veryLongString, veryLongString

The output is ugly and poorly formatted, but I can see it which was enough to let me solve my problem.

Piccalilli answered 19/2, 2022 at 1:19 Comment(0)
W
-4

You can use the tb flag this is the traceback output for pytest. There is a few options for that: --tb=style traceback print mode (auto/long/short/line/native/no)

You need to chooise what is the best for you.

Winton answered 31/1, 2018 at 16:13 Comment(2)
--tb= option has no effect on assert length.Sev
Yes! as I said, tb flag, this is the traceback output for pytest. for output only not for assert ¯_(ツ)_/¯Winton

© 2022 - 2024 — McMap. All rights reserved.