Merge pull request #1414 from rygwdn/indexerror

catch IndexError exceptions when getting exception source location
This commit is contained in:
Florian Bruhin 2016-02-26 18:53:10 +01:00
commit c9927bb66f
4 changed files with 31 additions and 2 deletions

View File

@ -69,6 +69,7 @@ Ralf Schmitt
Raphael Pierzina Raphael Pierzina
Ronny Pfannschmidt Ronny Pfannschmidt
Ross Lawley Ross Lawley
Ryan Wooden
Samuele Pedroni Samuele Pedroni
Tom Viner Tom Viner
Trevor Bekolay Trevor Bekolay

View File

@ -30,7 +30,9 @@
* *
* * catch IndexError exceptions when getting exception source location. This fixes
pytest internal error for dynamically generated code (fixtures and tests)
where source lines are fake by intention
* *

View File

@ -1774,7 +1774,7 @@ class FixtureLookupError(LookupError):
fspath, lineno = getfslineno(function) fspath, lineno = getfslineno(function)
try: try:
lines, _ = inspect.getsourcelines(get_real_func(function)) lines, _ = inspect.getsourcelines(get_real_func(function))
except IOError: except (IOError, IndexError):
error_msg = "file %s, line %s: source code not available" error_msg = "file %s, line %s: source code not available"
addline(error_msg % (fspath, lineno+1)) addline(error_msg % (fspath, lineno+1))
else: else:

View File

@ -568,6 +568,32 @@ def test_makereport_getsource(testdir):
result.stdout.fnmatch_lines(['*else: assert False*']) result.stdout.fnmatch_lines(['*else: assert False*'])
def test_makereport_getsource_dynamic_code(testdir, monkeypatch):
"""Test that exception in dynamically generated code doesn't break getting the source line."""
import inspect
original_findsource = inspect.findsource
def findsource(obj, *args, **kwargs):
# Can be triggered by dynamically created functions
if obj.__name__ == 'foo':
raise IndexError()
return original_findsource(obj, *args, **kwargs)
monkeypatch.setattr(inspect, 'findsource', findsource)
testdir.makepyfile("""
import pytest
@pytest.fixture
def foo(missing):
pass
def test_fix(foo):
assert False
""")
result = testdir.runpytest('-vv')
assert 'INTERNALERROR' not in result.stdout.str()
result.stdout.fnmatch_lines(["*test_fix*", "*fixture*'missing'*not found*"])
def test_store_except_info_on_eror(): def test_store_except_info_on_eror():
""" Test that upon test failure, the exception info is stored on """ Test that upon test failure, the exception info is stored on
sys.last_traceback and friends. sys.last_traceback and friends.