* 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:
holger krekel 2010-04-28 08:42:56 +02:00
parent d5e463605e
commit 78d33a2f28
10 changed files with 112 additions and 106 deletions

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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:

View File

@ -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

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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

View File

@ -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()