fix issue30 - better handling and reporting of errors in xfail expressions
This commit is contained in:
parent
6f3b84da9f
commit
682773e0cb
|
@ -1,10 +1,13 @@
|
||||||
Changes between 2.0.1 and 2.0.2
|
Changes between 2.0.1 and 2.0.2
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
- fix issue30 - better handling and error reporting for errors in xfail
|
||||||
|
expressions
|
||||||
|
|
||||||
- fix issue28 - setup_method and pytest_generate_tests work together
|
- fix issue28 - setup_method and pytest_generate_tests work together
|
||||||
|
|
||||||
- fix issue24 - pytest_assertrepr_compare produces an in-line
|
- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
|
||||||
exception on python3
|
(which apparently starts to offer os.symlink now)
|
||||||
|
|
||||||
- fixed some typos in the docs (thanks Victor)
|
- fixed some typos in the docs (thanks Victor)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
""" support for skip/xfail functions and markers. """
|
""" support for skip/xfail functions and markers. """
|
||||||
|
|
||||||
import py, pytest
|
import py, pytest
|
||||||
|
import sys
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
group = parser.getgroup("general")
|
group = parser.getgroup("general")
|
||||||
|
@ -32,7 +33,28 @@ class MarkEvaluator:
|
||||||
return bool(self.holder)
|
return bool(self.holder)
|
||||||
__nonzero__ = __bool__
|
__nonzero__ = __bool__
|
||||||
|
|
||||||
|
def wasvalid(self):
|
||||||
|
return not hasattr(self, 'exc')
|
||||||
|
|
||||||
def istrue(self):
|
def istrue(self):
|
||||||
|
try:
|
||||||
|
return self._istrue()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise
|
||||||
|
except:
|
||||||
|
self.exc = sys.exc_info()
|
||||||
|
if isinstance(self.exc[1], SyntaxError):
|
||||||
|
msg = [" " * (self.exc[1].offset + 4) + "^",]
|
||||||
|
msg.append("SyntaxError: invalid syntax")
|
||||||
|
else:
|
||||||
|
msg = py.std.traceback.format_exception_only(*self.exc[:2])
|
||||||
|
pytest.fail("Error evaluating %r expression\n"
|
||||||
|
" %s\n"
|
||||||
|
"%s"
|
||||||
|
%(self.name, self.expr, "\n".join(msg)),
|
||||||
|
pytrace=False)
|
||||||
|
|
||||||
|
def _istrue(self):
|
||||||
if self.holder:
|
if self.holder:
|
||||||
d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config}
|
d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config}
|
||||||
if self.holder.args:
|
if self.holder.args:
|
||||||
|
@ -99,14 +121,15 @@ def pytest_runtest_makereport(__multicall__, item, call):
|
||||||
return rep
|
return rep
|
||||||
rep = __multicall__.execute()
|
rep = __multicall__.execute()
|
||||||
evalxfail = item._evalxfail
|
evalxfail = item._evalxfail
|
||||||
if not item.config.option.runxfail and evalxfail.istrue():
|
if not item.config.option.runxfail:
|
||||||
|
if evalxfail.wasvalid() and evalxfail.istrue():
|
||||||
if call.excinfo:
|
if call.excinfo:
|
||||||
rep.outcome = "skipped"
|
rep.outcome = "skipped"
|
||||||
rep.keywords['xfail'] = evalxfail.getexplanation()
|
rep.keywords['xfail'] = evalxfail.getexplanation()
|
||||||
elif call.when == "call":
|
elif call.when == "call":
|
||||||
rep.outcome = "failed"
|
rep.outcome = "failed"
|
||||||
rep.keywords['xfail'] = evalxfail.getexplanation()
|
rep.keywords['xfail'] = evalxfail.getexplanation()
|
||||||
else:
|
return rep
|
||||||
if 'xfail' in rep.keywords:
|
if 'xfail' in rep.keywords:
|
||||||
del rep.keywords['xfail']
|
del rep.keywords['xfail']
|
||||||
return rep
|
return rep
|
||||||
|
@ -179,7 +202,8 @@ def cached_eval(config, expr, d):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
#import sys
|
#import sys
|
||||||
#print >>sys.stderr, ("cache-miss: %r" % expr)
|
#print >>sys.stderr, ("cache-miss: %r" % expr)
|
||||||
config._evalcache[expr] = x = eval(expr, d)
|
exprcode = py.code.compile(expr, mode="eval")
|
||||||
|
config._evalcache[expr] = x = eval(exprcode, d)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -29,7 +29,7 @@ def main():
|
||||||
author='holger krekel, Guido Wesdorp, Carl Friedrich Bolz, Armin Rigo, Maciej Fijalkowski & others',
|
author='holger krekel, Guido Wesdorp, Carl Friedrich Bolz, Armin Rigo, Maciej Fijalkowski & others',
|
||||||
author_email='holger at merlinux.eu',
|
author_email='holger at merlinux.eu',
|
||||||
entry_points= make_entry_points(),
|
entry_points= make_entry_points(),
|
||||||
install_requires=['py>1.4.0'],
|
install_requires=['py>1.4.1'],
|
||||||
classifiers=['Development Status :: 5 - Production/Stable',
|
classifiers=['Development Status :: 5 - Production/Stable',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'License :: OSI Approved :: MIT License',
|
'License :: OSI Approved :: MIT License',
|
||||||
|
|
|
@ -470,3 +470,31 @@ def test_reportchars(testdir):
|
||||||
"XPASS*test_3*",
|
"XPASS*test_3*",
|
||||||
"SKIP*four*",
|
"SKIP*four*",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_errors_in_xfail_skip_expressions(testdir):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
@pytest.mark.skipif("asd")
|
||||||
|
def test_nameerror():
|
||||||
|
pass
|
||||||
|
@pytest.mark.xfail("syntax error")
|
||||||
|
def test_syntax():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_func():
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*ERROR*test_nameerror*",
|
||||||
|
"*evaluating*skipif*expression*",
|
||||||
|
"*asd*",
|
||||||
|
"*ERROR*test_syntax*",
|
||||||
|
"*evaluating*xfail*expression*",
|
||||||
|
" syntax error",
|
||||||
|
" ^",
|
||||||
|
"SyntaxError: invalid syntax",
|
||||||
|
"*1 pass*2 error*",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue