[svn r58297] add a new way of conditionally skipping a test:
py.test.skip(ifraises="...") see more info in the added doc. also remove a redundant raises test and cleanup raises code a bit. --HG-- branch : trunk
This commit is contained in:
parent
cdb8fa1abe
commit
e77fab82ee
|
@ -1,9 +1,14 @@
|
||||||
$Id: CHANGELOG 57548 2008-08-21 12:12:20Z hpk $
|
$Id: CHANGELOG 58297 2008-09-21 12:50:56Z hpk $
|
||||||
|
|
||||||
Changes between 0.9.2 and 1.0 (UNRELEASED)
|
Changes between 0.9.2 and 1.0 (UNRELEASED)
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
|
* py.test.skip(ifraises=execstring) allows to
|
||||||
|
conditionally skip, e.g. ifraises="import docutils"
|
||||||
|
will skip if there is no docutils installed.
|
||||||
|
|
||||||
* revised internal py.test architecture
|
* revised internal py.test architecture
|
||||||
|
|
||||||
* new py.process.ForkedFunc object allowing to
|
* new py.process.ForkedFunc object allowing to
|
||||||
fork execution of a function to a sub process
|
fork execution of a function to a sub process
|
||||||
and getting a result back.
|
and getting a result back.
|
||||||
|
|
|
@ -86,6 +86,24 @@ asserts that the given ``Exception`` is raised. The reporter will
|
||||||
provide you with helpful output in case of failures such as *no
|
provide you with helpful output in case of failures such as *no
|
||||||
exception* or *wrong exception*.
|
exception* or *wrong exception*.
|
||||||
|
|
||||||
|
Skipping tests
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
If you want to skip tests you can use ``py.test.skip`` within
|
||||||
|
test or setup functions. Examples::
|
||||||
|
|
||||||
|
py.test.skip("message")
|
||||||
|
py.test.skip(ifraises="import docutils")
|
||||||
|
py.test.skip(ifraises="""
|
||||||
|
import somepkg
|
||||||
|
assert somepkg.__version__.startswith("2")
|
||||||
|
""")
|
||||||
|
|
||||||
|
The first skip will cause unconditional skipping
|
||||||
|
The second skip will only cause skipping if
|
||||||
|
``docutils`` is not importable.
|
||||||
|
The third form will cause skipping if ``somepkg``
|
||||||
|
is not importable or is not at least version "2".
|
||||||
|
|
||||||
automatic collection of tests on all levels
|
automatic collection of tests on all levels
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
|
@ -49,9 +49,26 @@ def exit(msg):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Exit(msg)
|
raise Exit(msg)
|
||||||
|
|
||||||
def skip(msg=""):
|
def skip(msg="", ifraises=None):
|
||||||
""" skip with the given Message. """
|
""" (conditionally) skip this test/module/conftest.
|
||||||
|
|
||||||
|
ifraises:
|
||||||
|
if "exec ifraises in {'py': py}" raises an exception
|
||||||
|
skip this test.
|
||||||
|
msg: use this message when skipping.
|
||||||
|
"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
if ifraises is not None:
|
||||||
|
ifraises = py.code.Source(ifraises).compile()
|
||||||
|
try:
|
||||||
|
exec ifraises in {'py': py}
|
||||||
|
except (KeyboardInterrupt, SystemExit):
|
||||||
|
raise
|
||||||
|
except Exception, e:
|
||||||
|
if not msg:
|
||||||
|
msg = repr(e)
|
||||||
|
else:
|
||||||
|
return
|
||||||
raise Skipped(msg=msg)
|
raise Skipped(msg=msg)
|
||||||
|
|
||||||
def fail(msg="unknown failure"):
|
def fail(msg="unknown failure"):
|
||||||
|
@ -66,16 +83,15 @@ def raises(ExpectedException, *args, **kwargs):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
assert args
|
assert args
|
||||||
if isinstance(args[0], str):
|
if isinstance(args[0], str):
|
||||||
expr, = args
|
code, = args
|
||||||
assert isinstance(expr, str)
|
assert isinstance(code, str)
|
||||||
frame = sys._getframe(1)
|
frame = sys._getframe(1)
|
||||||
loc = frame.f_locals.copy()
|
loc = frame.f_locals.copy()
|
||||||
loc.update(kwargs)
|
loc.update(kwargs)
|
||||||
#print "raises frame scope: %r" % frame.f_locals
|
#print "raises frame scope: %r" % frame.f_locals
|
||||||
source = py.code.Source(expr)
|
|
||||||
try:
|
try:
|
||||||
exec source.compile() in frame.f_globals, loc
|
code = py.code.Source(code).compile()
|
||||||
#del __traceback__
|
exec code in frame.f_globals, loc
|
||||||
# XXX didn'T mean f_globals == f_locals something special?
|
# XXX didn'T mean f_globals == f_locals something special?
|
||||||
# this is destroyed here ...
|
# this is destroyed here ...
|
||||||
except ExpectedException:
|
except ExpectedException:
|
||||||
|
@ -85,7 +101,6 @@ def raises(ExpectedException, *args, **kwargs):
|
||||||
assert callable
|
assert callable
|
||||||
try:
|
try:
|
||||||
func(*args[1:], **kwargs)
|
func(*args[1:], **kwargs)
|
||||||
#del __traceback__
|
|
||||||
except ExpectedException:
|
except ExpectedException:
|
||||||
return py.code.ExceptionInfo()
|
return py.code.ExceptionInfo()
|
||||||
k = ", ".join(["%s=%r" % x for x in kwargs.items()])
|
k = ", ".join(["%s=%r" % x for x in kwargs.items()])
|
||||||
|
|
|
@ -427,29 +427,13 @@ class Testgenitems:
|
||||||
ev = failures[0]
|
ev = failures[0]
|
||||||
assert ev.outcome.longrepr.reprcrash.message.startswith("SyntaxError")
|
assert ev.outcome.longrepr.reprcrash.message.startswith("SyntaxError")
|
||||||
|
|
||||||
def test_skip_at_module_level(self):
|
|
||||||
self.tmp.ensure("test_module.py").write(py.code.Source("""
|
|
||||||
import py
|
|
||||||
py.test.skip('xxx')
|
|
||||||
"""))
|
|
||||||
items, events = self._genitems()
|
|
||||||
funcs = [x for x in items if isinstance(x, event.ItemStart)]
|
|
||||||
assert not funcs
|
|
||||||
assert not items
|
|
||||||
l = [x for x in events
|
|
||||||
if isinstance(x, event.CollectionReport)
|
|
||||||
and x.colitem.name == 'test_module.py']
|
|
||||||
assert len(l) == 1
|
|
||||||
ev = l[0]
|
|
||||||
assert ev.skipped
|
|
||||||
|
|
||||||
def test_example_items1(self):
|
def test_example_items1(self):
|
||||||
self.tmp.ensure("test_example.py").write(py.code.Source('''
|
self.tmp.ensure("test_example.py").write(py.code.Source('''
|
||||||
def test_one():
|
def testone():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestX:
|
class TestX:
|
||||||
def test_method_one(self):
|
def testmethod_one(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestY(TestX):
|
class TestY(TestX):
|
||||||
|
@ -457,17 +441,17 @@ class Testgenitems:
|
||||||
'''))
|
'''))
|
||||||
items, events = self._genitems()
|
items, events = self._genitems()
|
||||||
assert len(items) == 3
|
assert len(items) == 3
|
||||||
assert items[0].name == 'test_one'
|
assert items[0].name == 'testone'
|
||||||
assert items[1].name == 'test_method_one'
|
assert items[1].name == 'testmethod_one'
|
||||||
assert items[2].name == 'test_method_one'
|
assert items[2].name == 'testmethod_one'
|
||||||
|
|
||||||
# let's also test getmodpath here
|
# let's also test getmodpath here
|
||||||
assert items[0].getmodpath() == "test_one"
|
assert items[0].getmodpath() == "testone"
|
||||||
assert items[1].getmodpath() == "TestX.test_method_one"
|
assert items[1].getmodpath() == "TestX.testmethod_one"
|
||||||
assert items[2].getmodpath() == "TestY.test_method_one"
|
assert items[2].getmodpath() == "TestY.testmethod_one"
|
||||||
|
|
||||||
s = items[0].getmodpath(stopatmodule=False)
|
s = items[0].getmodpath(stopatmodule=False)
|
||||||
assert s == "test_example_items1.test_example.test_one"
|
assert s == "test_example_items1.test_example.testone"
|
||||||
print s
|
print s
|
||||||
|
|
||||||
def test_collect_doctest_files_with_test_prefix(self):
|
def test_collect_doctest_files_with_test_prefix(self):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
import py
|
import py
|
||||||
import marshal
|
import marshal
|
||||||
|
from py.__.test.outcome import Skipped
|
||||||
|
|
||||||
class TestRaises:
|
class TestRaises:
|
||||||
def test_raises(self):
|
def test_raises(self):
|
||||||
|
@ -58,3 +59,28 @@ def test_deprecated_explicit_call():
|
||||||
py.test.deprecated_call(dep_explicit, 0)
|
py.test.deprecated_call(dep_explicit, 0)
|
||||||
py.test.deprecated_call(dep_explicit, 0)
|
py.test.deprecated_call(dep_explicit, 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_simple():
|
||||||
|
excinfo = py.test.raises(Skipped, 'py.test.skip("xxx")')
|
||||||
|
assert excinfo.traceback[-1].frame.code.name == "skip"
|
||||||
|
assert excinfo.traceback[-1].ishidden()
|
||||||
|
|
||||||
|
def test_skip_ifraises():
|
||||||
|
excinfo = py.test.raises(Skipped, '''
|
||||||
|
py.test.skip(ifraises="""
|
||||||
|
import lky
|
||||||
|
""")
|
||||||
|
''')
|
||||||
|
assert excinfo.traceback[-1].frame.code.name == "skip"
|
||||||
|
assert excinfo.traceback[-1].ishidden()
|
||||||
|
assert excinfo.value.msg.startswith("ImportError")
|
||||||
|
|
||||||
|
def test_skip_ifraises_syntaxerror():
|
||||||
|
try:
|
||||||
|
excinfo = py.test.raises(SyntaxError, '''
|
||||||
|
py.test.skip(ifraises="x y z")''')
|
||||||
|
except Skipped:
|
||||||
|
py.test.fail("should not skip")
|
||||||
|
assert not excinfo.traceback[-1].ishidden()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue