fix issue91 introduce new py.test.xfail(reason) helper

to imperatively mark a test as expected to fail. Can
be used from within setup and test functions. This is
useful especially for parametrized tests when certain
configurations are expected-to-fail.  In this case the
declarative approach with the @py.test.mark.xfail cannot
be used as it would mark all configurations as xfail.

--HG--
branch : trunk
This commit is contained in:
holger krekel 2010-05-20 13:29:51 +02:00
parent eac0345689
commit 925f75088d
4 changed files with 69 additions and 3 deletions

View File

@ -9,6 +9,14 @@ Changes between 1.3.0 and 1.3.1
- fix issue95: late-import zlib so that it's not required
for general py.test startup.
- fix issue91: introduce new py.test.xfail(reason) helper
to imperatively mark a test as expected to fail. Can
be used from within setup and test functions. This is
useful especially for parametrized tests when certain
configurations are expected-to-fail. In this case the
declarative approach with the @py.test.mark.xfail cannot
be used as it would mark all configurations as xfail.
- make py.test.cmdline.main() return the exitstatus
instead of raising (which is still done by py.cmdline.pytest())
and make it so that py.test.cmdline.main() can be called

View File

@ -10,6 +10,7 @@ def pytest_namespace():
'skip' : skip,
'importorskip' : importorskip,
'fail' : fail,
'xfail' : xfail,
'exit' : exit,
}
@ -295,6 +296,10 @@ class Failed(OutcomeException):
""" raised from an explicit call to py.test.fail() """
__module__ = 'builtins'
class XFailed(OutcomeException):
""" raised from an explicit call to py.test.xfail() """
__module__ = 'builtins'
class ExceptionFailure(Failed):
""" raised by py.test.raises on an exception-assertion mismatch. """
def __init__(self, expr, expected, msg=None, excinfo=None):
@ -335,6 +340,14 @@ def fail(msg=""):
fail.Exception = Failed
def xfail(reason=""):
""" xfail an executing test or setup functions, taking an optional
reason string.
"""
__tracebackhide__ = True
raise XFailed(reason)
xfail.Exception = XFailed
def raises(ExpectedException, *args, **kwargs):
""" if args[0] is callable: raise AssertionError if calling it with
the remaining arguments does not raise the expected exception.

View File

@ -185,9 +185,17 @@ def pytest_runtest_setup(item):
def pytest_runtest_makereport(__multicall__, item, call):
if not isinstance(item, py.test.collect.Function):
return
evalxfail = getattr(item, '_evalxfail', None)
if not evalxfail:
return
if not (call.excinfo and
call.excinfo.errisinstance(py.test.xfail.Exception)):
evalxfail = getattr(item, '_evalxfail', None)
if not evalxfail:
return
if call.excinfo and call.excinfo.errisinstance(py.test.xfail.Exception):
rep = __multicall__.execute()
rep.keywords['xfail'] = "reason: " + call.excinfo.value.msg
rep.skipped = True
rep.failed = False
return rep
if call.when == "setup":
rep = __multicall__.execute()
if rep.skipped and evalxfail.istrue():

View File

@ -169,6 +169,43 @@ class TestXFail:
])
assert result.ret == 1
def test_xfail_imperative(self, testdir):
p = testdir.makepyfile("""
import py
def test_this():
py.test.xfail("hello")
""")
result = testdir.runpytest(p)
result.stdout.fnmatch_lines([
"*1 xfailed*",
])
result = testdir.runpytest(p, "-rx")
result.stdout.fnmatch_lines([
"*XFAIL*test_this*reason:*hello*",
])
def test_xfail_imperative_in_setup_function(self, testdir):
p = testdir.makepyfile("""
import py
def setup_function(function):
py.test.xfail("hello")
def test_this():
assert 0
""")
result = testdir.runpytest(p)
result.stdout.fnmatch_lines([
"*1 xfailed*",
])
result = testdir.runpytest(p, "-rx")
result.stdout.fnmatch_lines([
"*XFAIL*test_this*reason:*hello*",
])
class TestSkipif:
def test_skipif_conditional(self, testdir):
item = testdir.getitem("""