Pytest: Provide a way to show stacktraces with the Python default format

Created on 15 Jun 2016  路  10Comments  路  Source: pytest-dev/pytest

I'm currently working in fixing the pytest integration inside of PyDev (http://pydev.org), and to make items hyperlinked, I resort to hacking around pytest to make the hyperlinks printed in the Python format:

'File "%s", line %s\n%s' (filename, lineno, msg)

To do that, I mock code.ReprFileLocation.toterminal (as can be seen at https://github.com/fabioz/Pydev/blob/master/plugins/org.python.pydev/pysrc/_pydev_runfiles/pydev_runfiles_pytest2.py), but ideally, this would be supported by pytest itself with a proper API (so that it doesn't break when pytest itself is updated).

Most helpful comment

There's the --tb=native option:

import pytest

def foo():
    bar()

def bar():
    raise RuntimeError

def test_foo():
    foo()

if __name__ == '__main__':
    test_foo()
$ python test_bar.py
Traceback (most recent call last):
  File "test_bar.py", line 13, in <module>
    test_foo()
  File "test_bar.py", line 10, in test_foo
    foo()
  File "test_bar.py", line 4, in foo
    bar()
  File "test_bar.py", line 7, in bar
    raise RuntimeError
RuntimeError
$ py.test  test_bar.py --tb=native
============================= test session starts =============================
platform win32 -- Python 3.5.0, pytest-2.10.0.dev1, py-1.4.31, pluggy-0.3.1
rootdir: X:\pytest\tmp\foo\tests, inifile: pytest.ini
plugins: hypothesis-3.1.0, xdist-1.14
collected 1 items

test_bar.py F

================================== FAILURES ===================================
__________________________________ test_foo ___________________________________
Traceback (most recent call last):
  File "X:\pytest\tmp\foo\tests\test_bar.py", line 10, in test_foo
    foo()
  File "X:\pytest\tmp\foo\tests\test_bar.py", line 4, in foo
    bar()
  File "X:\pytest\tmp\foo\tests\test_bar.py", line 7, in bar
    raise RuntimeError
RuntimeError
========================== 1 failed in 0.02 seconds ===========================

Or do you mean something else?

All 10 comments

There's the --tb=native option:

import pytest

def foo():
    bar()

def bar():
    raise RuntimeError

def test_foo():
    foo()

if __name__ == '__main__':
    test_foo()
$ python test_bar.py
Traceback (most recent call last):
  File "test_bar.py", line 13, in <module>
    test_foo()
  File "test_bar.py", line 10, in test_foo
    foo()
  File "test_bar.py", line 4, in foo
    bar()
  File "test_bar.py", line 7, in bar
    raise RuntimeError
RuntimeError
$ py.test  test_bar.py --tb=native
============================= test session starts =============================
platform win32 -- Python 3.5.0, pytest-2.10.0.dev1, py-1.4.31, pluggy-0.3.1
rootdir: X:\pytest\tmp\foo\tests, inifile: pytest.ini
plugins: hypothesis-3.1.0, xdist-1.14
collected 1 items

test_bar.py F

================================== FAILURES ===================================
__________________________________ test_foo ___________________________________
Traceback (most recent call last):
  File "X:\pytest\tmp\foo\tests\test_bar.py", line 10, in test_foo
    foo()
  File "X:\pytest\tmp\foo\tests\test_bar.py", line 4, in foo
    bar()
  File "X:\pytest\tmp\foo\tests\test_bar.py", line 7, in bar
    raise RuntimeError
RuntimeError
========================== 1 failed in 0.02 seconds ===========================

Or do you mean something else?

I mean something else. Users want to run with:

--tb=line

And still get the output as

================================== FAILURES ===================================
File "X:\workspace2\rocky30\source\python\rocky30\check.py", line 3
AssertionError: 20
========================== 1 failed in 0.46 seconds ===========================

Instead of

================================== FAILURES ===================================
X:\workspace2\rocky30\source\python\rocky30\check.py:3: AssertionError: 20
========================== 1 failed in 0.45 seconds ===========================

Or --tb=long and get:

================================== FAILURES ===================================
___________________________________ test_it ___________________________________

    def test_it():
        a = 10
>       raise AssertionError(20)
E       AssertionError: 20

File "X:\workspace2\rocky30\source\python\rocky30\check.py", line 3
AssertionError
========================== 1 failed in 0.45 seconds ===========================

Instead of:

================================== FAILURES ===================================
___________________________________ test_it ___________________________________

    def test_it():
        a = 10
>       raise AssertionError(20)
E       AssertionError: 20

rocky30\check.py:3: AssertionError
========================== 1 failed in 0.45 seconds ===========================

Note that the change is only on the file/line reporting, not on the remainder of the traceback.

Oh I see thanks.

How do you suggest this to be changed? A command-line option?

As another note for PyDev specifically, wouldn't be easier to implement the pytest_runtest_logreport(report) hook? report.location gives the full filename and line number, no need to parse any output.

Humm, not really, report.location seems to be dependent on the cwd. I think item.fspath.strpath has the full path for the item, but in both cases, it may not be related to the generated stacktrace in any way... (so, I don't see how to really implement it given your suggestion).

As a note, I currently do implement the pytest_runtest_logreport, but I don't want to redo how the user sees the whole stacktrace, only the part related to the file (the only way I found to customize that was by mocking code.ReprFileLocation.toterminal -- not ideal).

In my particular case, it doesn't need to be a command-line option, just some supported API would do it.

Hmm I see, you want to make filenames hyperlinked on the console.

In my particular case, it doesn't need to be a command-line option, just some supported API would do it.

Could you give a suggestion? It's not clear to me how an API would help you here.

Sure...

I can give you 2 suggestions :)

  1. Provide a factory which creates ReprFileLocation which I can customize (and guarantee the API keeps stable).
  2. Provide some api such as set_file_location_format(format, is_absolute), where format = "File %s, %s\n %s and is_absolute = False or True (or a configuration for that) which then goes on to customize ReprFileLocation (as it is now, ReprFileLocation seems to be an internal API on _pytest, so, I don't think I can really rely on it not being changed over time).

Oh I see, thanks (I didn't think an API would help because I thought you didn't want to change the output perceived by users).

I think 2) is doable and relatively simple to implement.

do we have anyone wanting to implement this?

Superseded by #1613

Solution: --tb=native

Was this page helpful?
0 / 5 - 0 ratings