* rather expose internal exceptions under py.test.ACTION.Exception
with ACTION being skip, fail, exit, raises. * move and refine test_outcome.py tests into runner tests --HG-- branch : trunk
This commit is contained in:
parent
d5e463605e
commit
78d33a2f28
|
@ -9,8 +9,9 @@ Changes between 1.2.1 and 1.2.2 (release pending)
|
||||||
- added links to the new capturelog and coverage plugins
|
- added links to the new capturelog and coverage plugins
|
||||||
- (issue87) fix unboundlocal error in assertionold code
|
- (issue87) fix unboundlocal error in assertionold code
|
||||||
- (issue86) improve documentation for looponfailing
|
- (issue86) improve documentation for looponfailing
|
||||||
- expose some internal test running exceptions under py.test.exc.*
|
- expose test outcome related exceptions as py.test.skip.Exception,
|
||||||
and shift raises/importorskip etc. helper definitions to runner plugin .
|
py.test.raises.Exception etc., useful mostly for plugins
|
||||||
|
doing special outcome interpreteration/tweaking
|
||||||
- ship distribute_setup.py version 0.6.10
|
- ship distribute_setup.py version 0.6.10
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ def pytest_configure(config):
|
||||||
class PdbInvoke:
|
class PdbInvoke:
|
||||||
def pytest_runtest_makereport(self, item, call):
|
def pytest_runtest_makereport(self, item, call):
|
||||||
if call.excinfo and not \
|
if call.excinfo and not \
|
||||||
call.excinfo.errisinstance(py.test.exc.Skipped):
|
call.excinfo.errisinstance(py.test.skip.Exception):
|
||||||
# play well with capturing, slightly hackish
|
# play well with capturing, slightly hackish
|
||||||
capman = item.config.pluginmanager.getplugin('capturemanager')
|
capman = item.config.pluginmanager.getplugin('capturemanager')
|
||||||
capman.suspendcapture()
|
capman.suspendcapture()
|
||||||
|
|
|
@ -5,15 +5,7 @@ collect and run test items and create reports.
|
||||||
import py, sys
|
import py, sys
|
||||||
|
|
||||||
def pytest_namespace():
|
def pytest_namespace():
|
||||||
class exc:
|
|
||||||
""" namespace holding py.test runner exceptions. """
|
|
||||||
Skipped = Skipped
|
|
||||||
ExceptionFailure = ExceptionFailure
|
|
||||||
Failed = Failed
|
|
||||||
Exit = Exit
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'exc' : exc,
|
|
||||||
'raises' : raises,
|
'raises' : raises,
|
||||||
'skip' : skip,
|
'skip' : skip,
|
||||||
'importorskip' : importorskip,
|
'importorskip' : importorskip,
|
||||||
|
@ -157,7 +149,7 @@ class ItemTestReport(BaseReport):
|
||||||
self.failed = True
|
self.failed = True
|
||||||
shortrepr = "?"
|
shortrepr = "?"
|
||||||
longrepr = excinfo
|
longrepr = excinfo
|
||||||
elif excinfo.errisinstance(py.test.exc.Skipped):
|
elif excinfo.errisinstance(py.test.skip.Exception):
|
||||||
self.skipped = True
|
self.skipped = True
|
||||||
shortrepr = "s"
|
shortrepr = "s"
|
||||||
longrepr = self.item._repr_failure_py(excinfo)
|
longrepr = self.item._repr_failure_py(excinfo)
|
||||||
|
@ -196,7 +188,7 @@ class CollectReport(BaseReport):
|
||||||
self.result = result
|
self.result = result
|
||||||
else:
|
else:
|
||||||
self.longrepr = self.collector._repr_failure_py(excinfo)
|
self.longrepr = self.collector._repr_failure_py(excinfo)
|
||||||
if excinfo.errisinstance(py.test.exc.Skipped):
|
if excinfo.errisinstance(py.test.skip.Exception):
|
||||||
self.skipped = True
|
self.skipped = True
|
||||||
self.reason = str(excinfo.value)
|
self.reason = str(excinfo.value)
|
||||||
else:
|
else:
|
||||||
|
@ -322,6 +314,8 @@ def exit(msg):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Exit(msg)
|
raise Exit(msg)
|
||||||
|
|
||||||
|
exit.Exception = Exit
|
||||||
|
|
||||||
def skip(msg=""):
|
def skip(msg=""):
|
||||||
""" skip an executing test with the given message. Note: it's usually
|
""" skip an executing test with the given message. Note: it's usually
|
||||||
better use the py.test.mark.skipif marker to declare a test to be
|
better use the py.test.mark.skipif marker to declare a test to be
|
||||||
|
@ -331,11 +325,15 @@ def skip(msg=""):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Skipped(msg=msg)
|
raise Skipped(msg=msg)
|
||||||
|
|
||||||
|
skip.Exception = Skipped
|
||||||
|
|
||||||
def fail(msg=""):
|
def fail(msg=""):
|
||||||
""" explicitely fail an currently-executing test with the given Message. """
|
""" explicitely fail an currently-executing test with the given Message. """
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Failed(msg=msg)
|
raise Failed(msg=msg)
|
||||||
|
|
||||||
|
fail.Exception = Failed
|
||||||
|
|
||||||
def raises(ExpectedException, *args, **kwargs):
|
def raises(ExpectedException, *args, **kwargs):
|
||||||
""" if args[0] is callable: raise AssertionError if calling it with
|
""" if args[0] is callable: raise AssertionError if calling it with
|
||||||
the remaining arguments does not raise the expected exception.
|
the remaining arguments does not raise the expected exception.
|
||||||
|
@ -375,6 +373,8 @@ def raises(ExpectedException, *args, **kwargs):
|
||||||
raise ExceptionFailure(msg="DID NOT RAISE",
|
raise ExceptionFailure(msg="DID NOT RAISE",
|
||||||
expr=args, expected=ExpectedException)
|
expr=args, expected=ExpectedException)
|
||||||
|
|
||||||
|
raises.Exception = ExceptionFailure
|
||||||
|
|
||||||
def importorskip(modname, minversion=None):
|
def importorskip(modname, minversion=None):
|
||||||
""" return imported module if it has a higher __version__ than the
|
""" return imported module if it has a higher __version__ than the
|
||||||
optionally specified 'minversion' - otherwise call py.test.skip()
|
optionally specified 'minversion' - otherwise call py.test.skip()
|
||||||
|
|
|
@ -138,7 +138,7 @@ class PluginManager(object):
|
||||||
mod = importplugin(modname)
|
mod = importplugin(modname)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except py.test.exc.Skipped:
|
except py.test.skip.Exception:
|
||||||
e = py.std.sys.exc_info()[1]
|
e = py.std.sys.exc_info()[1]
|
||||||
self._hints.append("skipped plugin %r: %s" %((modname, e.msg)))
|
self._hints.append("skipped plugin %r: %s" %((modname, e.msg)))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import py
|
import py, sys
|
||||||
from py._plugin import pytest_runner as runner
|
from py._plugin import pytest_runner as runner
|
||||||
from py._code.code import ReprExceptionInfo
|
from py._code.code import ReprExceptionInfo
|
||||||
|
|
||||||
|
@ -201,9 +201,9 @@ class BaseFunctionalTests:
|
||||||
testdir.runitem("""
|
testdir.runitem("""
|
||||||
import py
|
import py
|
||||||
def test_func():
|
def test_func():
|
||||||
raise py.test.exc.Exit()
|
raise py.test.exit.Exception()
|
||||||
""")
|
""")
|
||||||
except py.test.exc.Exit:
|
except py.test.exit.Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
py.test.fail("did not raise")
|
py.test.fail("did not raise")
|
||||||
|
@ -313,3 +313,91 @@ def test_runtest_in_module_ordering(testdir):
|
||||||
assert result.stdout.fnmatch_lines([
|
assert result.stdout.fnmatch_lines([
|
||||||
"*2 passed*"
|
"*2 passed*"
|
||||||
])
|
])
|
||||||
|
|
||||||
|
class TestRaises:
|
||||||
|
def test_raises(self):
|
||||||
|
py.test.raises(ValueError, "int('qwe')")
|
||||||
|
|
||||||
|
def test_raises_exec(self):
|
||||||
|
py.test.raises(ValueError, "a,x = []")
|
||||||
|
|
||||||
|
def test_raises_syntax_error(self):
|
||||||
|
py.test.raises(SyntaxError, "qwe qwe qwe")
|
||||||
|
|
||||||
|
def test_raises_function(self):
|
||||||
|
py.test.raises(ValueError, int, 'hello')
|
||||||
|
|
||||||
|
def test_raises_callable_no_exception(self):
|
||||||
|
class A:
|
||||||
|
def __call__(self):
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
py.test.raises(ValueError, A())
|
||||||
|
except py.test.raises.Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_pytest_exit():
|
||||||
|
try:
|
||||||
|
py.test.exit("hello")
|
||||||
|
except py.test.exit.Exception:
|
||||||
|
excinfo = py.code.ExceptionInfo()
|
||||||
|
assert excinfo.errisinstance(KeyboardInterrupt)
|
||||||
|
|
||||||
|
def test_pytest_fail():
|
||||||
|
try:
|
||||||
|
py.test.fail("hello")
|
||||||
|
except py.test.fail.Exception:
|
||||||
|
excinfo = py.code.ExceptionInfo()
|
||||||
|
s = excinfo.exconly(tryshort=True)
|
||||||
|
assert s.startswith("Failed")
|
||||||
|
|
||||||
|
def test_exception_printing_skip():
|
||||||
|
try:
|
||||||
|
py.test.skip("hello")
|
||||||
|
except py.test.skip.Exception:
|
||||||
|
excinfo = py.code.ExceptionInfo()
|
||||||
|
s = excinfo.exconly(tryshort=True)
|
||||||
|
assert s.startswith("Skipped")
|
||||||
|
|
||||||
|
def test_importorskip():
|
||||||
|
importorskip = py.test.importorskip
|
||||||
|
try:
|
||||||
|
sys = importorskip("sys")
|
||||||
|
assert sys == py.std.sys
|
||||||
|
#path = py.test.importorskip("os.path")
|
||||||
|
#assert path == py.std.os.path
|
||||||
|
py.test.raises(py.test.skip.Exception,
|
||||||
|
"py.test.importorskip('alskdj')")
|
||||||
|
py.test.raises(SyntaxError, "py.test.importorskip('x y z')")
|
||||||
|
py.test.raises(SyntaxError, "py.test.importorskip('x=y')")
|
||||||
|
path = importorskip("py", minversion=".".join(py.__version__))
|
||||||
|
mod = py.std.types.ModuleType("hello123")
|
||||||
|
mod.__version__ = "1.3"
|
||||||
|
py.test.raises(py.test.skip.Exception, """
|
||||||
|
py.test.importorskip("hello123", minversion="5.0")
|
||||||
|
""")
|
||||||
|
except py.test.skip.Exception:
|
||||||
|
print(py.code.ExceptionInfo())
|
||||||
|
py.test.fail("spurious skip")
|
||||||
|
|
||||||
|
def test_importorskip_imports_last_module_part():
|
||||||
|
import os
|
||||||
|
ospath = py.test.importorskip("os.path")
|
||||||
|
assert os.path == ospath
|
||||||
|
|
||||||
|
|
||||||
|
def test_pytest_cmdline_main(testdir):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, %r)
|
||||||
|
import py
|
||||||
|
def test_hello():
|
||||||
|
assert 1
|
||||||
|
if __name__ == '__main__':
|
||||||
|
py.test.cmdline.main([__file__])
|
||||||
|
""" % (str(py._pydir.dirpath())))
|
||||||
|
import subprocess
|
||||||
|
popen = subprocess.Popen([sys.executable, str(p)], stdout=subprocess.PIPE)
|
||||||
|
s = popen.stdout.read()
|
||||||
|
ret = popen.wait()
|
||||||
|
assert ret == 0
|
||||||
|
|
|
@ -51,7 +51,7 @@ def test_importall():
|
||||||
modpath = 'py.%s' % relpath
|
modpath = 'py.%s' % relpath
|
||||||
try:
|
try:
|
||||||
check_import(modpath)
|
check_import(modpath)
|
||||||
except py.test.exc.Skipped:
|
except py.test.skip.Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def check_import(modpath):
|
def check_import(modpath):
|
||||||
|
|
|
@ -76,12 +76,12 @@ class TestConfigAPI:
|
||||||
|
|
||||||
def test_config_getvalueorskip(self, testdir):
|
def test_config_getvalueorskip(self, testdir):
|
||||||
config = testdir.parseconfig()
|
config = testdir.parseconfig()
|
||||||
py.test.raises(py.test.exc.Skipped,
|
py.test.raises(py.test.skip.Exception,
|
||||||
"config.getvalueorskip('hello')")
|
"config.getvalueorskip('hello')")
|
||||||
verbose = config.getvalueorskip("verbose")
|
verbose = config.getvalueorskip("verbose")
|
||||||
assert verbose == config.option.verbose
|
assert verbose == config.option.verbose
|
||||||
config.option.hello = None
|
config.option.hello = None
|
||||||
py.test.raises(py.test.exc.Skipped,
|
py.test.raises(py.test.skip.Exception,
|
||||||
"config.getvalueorskip('hello')")
|
"config.getvalueorskip('hello')")
|
||||||
|
|
||||||
def test_config_overwrite(self, testdir):
|
def test_config_overwrite(self, testdir):
|
||||||
|
|
|
@ -190,7 +190,7 @@ class TestDisabled:
|
||||||
l = modcol.collect()
|
l = modcol.collect()
|
||||||
assert len(l) == 1
|
assert len(l) == 1
|
||||||
recwarn.clear()
|
recwarn.clear()
|
||||||
py.test.raises(py.test.exc.Skipped, "modcol.setup()")
|
py.test.raises(py.test.skip.Exception, "modcol.setup()")
|
||||||
recwarn.pop(DeprecationWarning)
|
recwarn.pop(DeprecationWarning)
|
||||||
|
|
||||||
def test_disabled_class(self, recwarn, testdir):
|
def test_disabled_class(self, recwarn, testdir):
|
||||||
|
@ -207,7 +207,7 @@ class TestDisabled:
|
||||||
l = modcol.collect()
|
l = modcol.collect()
|
||||||
assert len(l) == 1
|
assert len(l) == 1
|
||||||
recwarn.clear()
|
recwarn.clear()
|
||||||
py.test.raises(py.test.exc.Skipped, "modcol.setup()")
|
py.test.raises(py.test.skip.Exception, "modcol.setup()")
|
||||||
recwarn.pop(DeprecationWarning)
|
recwarn.pop(DeprecationWarning)
|
||||||
|
|
||||||
def test_disabled_class_functional(self, testdir):
|
def test_disabled_class_functional(self, testdir):
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
|
|
||||||
import py
|
|
||||||
import sys
|
|
||||||
|
|
||||||
class TestRaises:
|
|
||||||
def test_raises(self):
|
|
||||||
py.test.raises(ValueError, "int('qwe')")
|
|
||||||
|
|
||||||
def test_raises_exec(self):
|
|
||||||
py.test.raises(ValueError, "a,x = []")
|
|
||||||
|
|
||||||
def test_raises_syntax_error(self):
|
|
||||||
py.test.raises(SyntaxError, "qwe qwe qwe")
|
|
||||||
|
|
||||||
def test_raises_function(self):
|
|
||||||
py.test.raises(ValueError, int, 'hello')
|
|
||||||
|
|
||||||
def test_raises_callable_no_exception(self):
|
|
||||||
class A:
|
|
||||||
def __call__(self):
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
py.test.raises(ValueError, A())
|
|
||||||
except py.test.exc.ExceptionFailure:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_pytest_exit():
|
|
||||||
try:
|
|
||||||
py.test.exit("hello")
|
|
||||||
except:
|
|
||||||
excinfo = py.code.ExceptionInfo()
|
|
||||||
assert excinfo.errisinstance(KeyboardInterrupt)
|
|
||||||
|
|
||||||
def test_exception_printing_skip():
|
|
||||||
try:
|
|
||||||
py.test.skip("hello")
|
|
||||||
except Exception:
|
|
||||||
excinfo = py.code.ExceptionInfo()
|
|
||||||
s = excinfo.exconly(tryshort=True)
|
|
||||||
assert s.startswith("Skipped")
|
|
||||||
|
|
||||||
def test_importorskip():
|
|
||||||
importorskip = py.test.importorskip
|
|
||||||
try:
|
|
||||||
sys = importorskip("sys")
|
|
||||||
assert sys == py.std.sys
|
|
||||||
#path = py.test.importorskip("os.path")
|
|
||||||
#assert path == py.std.os.path
|
|
||||||
py.test.raises(py.test.exc.Skipped,
|
|
||||||
"py.test.importorskip('alskdj')")
|
|
||||||
py.test.raises(SyntaxError, "py.test.importorskip('x y z')")
|
|
||||||
py.test.raises(SyntaxError, "py.test.importorskip('x=y')")
|
|
||||||
path = importorskip("py", minversion=".".join(py.__version__))
|
|
||||||
mod = py.std.types.ModuleType("hello123")
|
|
||||||
mod.__version__ = "1.3"
|
|
||||||
py.test.raises(py.test.exc.Skipped, """
|
|
||||||
py.test.importorskip("hello123", minversion="5.0")
|
|
||||||
""")
|
|
||||||
except py.test.exc.Skipped:
|
|
||||||
print(py.code.ExceptionInfo())
|
|
||||||
py.test.fail("spurious skip")
|
|
||||||
|
|
||||||
def test_importorskip_imports_last_module_part():
|
|
||||||
import os
|
|
||||||
ospath = py.test.importorskip("os.path")
|
|
||||||
assert os.path == ospath
|
|
||||||
|
|
||||||
|
|
||||||
def test_pytest_cmdline_main(testdir):
|
|
||||||
p = testdir.makepyfile("""
|
|
||||||
import sys
|
|
||||||
sys.path.insert(0, %r)
|
|
||||||
import py
|
|
||||||
def test_hello():
|
|
||||||
assert 1
|
|
||||||
if __name__ == '__main__':
|
|
||||||
py.test.cmdline.main([__file__])
|
|
||||||
""" % (str(py._pydir.dirpath())))
|
|
||||||
import subprocess
|
|
||||||
popen = subprocess.Popen([sys.executable, str(p)], stdout=subprocess.PIPE)
|
|
||||||
s = popen.stdout.read()
|
|
||||||
ret = popen.wait()
|
|
||||||
assert ret == 0
|
|
|
@ -444,7 +444,7 @@ def test_modulecol_roundtrip(testdir):
|
||||||
|
|
||||||
class TestTracebackCutting:
|
class TestTracebackCutting:
|
||||||
def test_skip_simple(self):
|
def test_skip_simple(self):
|
||||||
excinfo = py.test.raises(py.test.exc.Skipped, 'py.test.skip("xxx")')
|
excinfo = py.test.raises(py.test.skip.Exception, 'py.test.skip("xxx")')
|
||||||
assert excinfo.traceback[-1].frame.code.name == "skip"
|
assert excinfo.traceback[-1].frame.code.name == "skip"
|
||||||
assert excinfo.traceback[-1].ishidden()
|
assert excinfo.traceback[-1].ishidden()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue