[svn r58308] * de-generalize conditional skips and only care
nicely for common tedious causes of skipping: import a module and checking it has a certain version. usage example: docutils = py.test.importorskip(docutils, minversion="0.4") * used new helper and cleanup skipping logic in py lib --HG-- branch : trunk
This commit is contained in:
parent
fa5c975c00
commit
cc10d84088
|
@ -1,11 +1,10 @@
|
||||||
$Id: CHANGELOG 58297 2008-09-21 12:50:56Z hpk $
|
$Id: CHANGELOG 58308 2008-09-21 15:15:28Z 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
|
* new method: py.test.importorskip(mod,minversion)
|
||||||
conditionally skip, e.g. ifraises="import docutils"
|
will either import or call py.test.skip()
|
||||||
will skip if there is no docutils installed.
|
|
||||||
|
|
||||||
* revised internal py.test architecture
|
* revised internal py.test architecture
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@ version = "1.0.0a1"
|
||||||
|
|
||||||
initpkg(__name__,
|
initpkg(__name__,
|
||||||
description = "pylib and py.test: agile development and test support library",
|
description = "pylib and py.test: agile development and test support library",
|
||||||
revision = int('$LastChangedRevision: 58190 $'.split(':')[1][:-1]),
|
revision = int('$LastChangedRevision: 58308 $'.split(':')[1][:-1]),
|
||||||
lastchangedate = '$LastChangedDate: 2008-09-17 10:50:04 +0200 (Wed, 17 Sep 2008) $',
|
lastchangedate = '$LastChangedDate: 2008-09-21 17:15:28 +0200 (Sun, 21 Sep 2008) $',
|
||||||
version = version,
|
version = version,
|
||||||
url = "http://pylib.org",
|
url = "http://pylib.org",
|
||||||
download_url = "http://codespeak.net/py/0.9.2/download.html",
|
download_url = "http://codespeak.net/py/0.9.2/download.html",
|
||||||
|
@ -67,6 +67,7 @@ initpkg(__name__,
|
||||||
'test.raises' : ('./test/outcome.py', 'raises'),
|
'test.raises' : ('./test/outcome.py', 'raises'),
|
||||||
'test.deprecated_call' : ('./test/outcome.py', 'deprecated_call'),
|
'test.deprecated_call' : ('./test/outcome.py', 'deprecated_call'),
|
||||||
'test.skip' : ('./test/outcome.py', 'skip'),
|
'test.skip' : ('./test/outcome.py', 'skip'),
|
||||||
|
'test.importorskip' : ('./test/outcome.py', 'importorskip'),
|
||||||
'test.fail' : ('./test/outcome.py', 'fail'),
|
'test.fail' : ('./test/outcome.py', 'fail'),
|
||||||
'test.exit' : ('./test/outcome.py', 'exit'),
|
'test.exit' : ('./test/outcome.py', 'exit'),
|
||||||
'test.pdb' : ('./test/custompdb.py', 'set_trace'),
|
'test.pdb' : ('./test/custompdb.py', 'set_trace'),
|
||||||
|
|
|
@ -61,10 +61,7 @@ def deindent(s, sep='\n'):
|
||||||
_initialized = False
|
_initialized = False
|
||||||
def checkdocutils():
|
def checkdocutils():
|
||||||
global _initialized
|
global _initialized
|
||||||
try:
|
py.test.importorskip("docutils")
|
||||||
import docutils
|
|
||||||
except ImportError:
|
|
||||||
py.test.skip("docutils not importable")
|
|
||||||
if not _initialized:
|
if not _initialized:
|
||||||
from py.__.rest import directive
|
from py.__.rest import directive
|
||||||
directive.register_linkrole('api', resolve_linkrole)
|
directive.register_linkrole('api', resolve_linkrole)
|
||||||
|
|
|
@ -90,20 +90,17 @@ Skipping tests
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
If you want to skip tests you can use ``py.test.skip`` within
|
If you want to skip tests you can use ``py.test.skip`` within
|
||||||
test or setup functions. Examples::
|
test or setup functions. Example::
|
||||||
|
|
||||||
py.test.skip("message")
|
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
|
You can also use a helper to skip on a failing import::
|
||||||
The second skip will only cause skipping if
|
|
||||||
``docutils`` is not importable.
|
docutils = py.test.importorskip("docutils")
|
||||||
The third form will cause skipping if ``somepkg``
|
|
||||||
is not importable or is not at least version "2".
|
or to skip if the library does not have the right version::
|
||||||
|
|
||||||
|
docutils = py.test.importorskip("docutils", minversion="0.3")
|
||||||
|
|
||||||
automatic collection of tests on all levels
|
automatic collection of tests on all levels
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
|
@ -181,7 +181,7 @@ class LocalPath(common.FSPathBase, PlatformMixin):
|
||||||
break
|
break
|
||||||
for arg in strargs:
|
for arg in strargs:
|
||||||
arg = arg.strip(sep)
|
arg = arg.strip(sep)
|
||||||
if py.std.sys.platform == 'win32':
|
if iswin32:
|
||||||
# allow unix style paths even on windows.
|
# allow unix style paths even on windows.
|
||||||
arg = arg.strip('/')
|
arg = arg.strip('/')
|
||||||
arg = arg.replace('/', sep)
|
arg = arg.replace('/', sep)
|
||||||
|
@ -512,7 +512,7 @@ class LocalPath(common.FSPathBase, PlatformMixin):
|
||||||
if p.check(file=1):
|
if p.check(file=1):
|
||||||
return p
|
return p
|
||||||
else:
|
else:
|
||||||
if py.std.sys.platform == 'win32':
|
if iswin32:
|
||||||
paths = py.std.os.environ['Path'].split(';')
|
paths = py.std.os.environ['Path'].split(';')
|
||||||
try:
|
try:
|
||||||
systemroot = os.environ['SYSTEMROOT']
|
systemroot = os.environ['SYSTEMROOT']
|
||||||
|
|
|
@ -7,6 +7,13 @@ from py.__.path.svn import cache, svncommon
|
||||||
mypath = py.magic.autopath()
|
mypath = py.magic.autopath()
|
||||||
repodump = mypath.dirpath('repotest.dump')
|
repodump = mypath.dirpath('repotest.dump')
|
||||||
|
|
||||||
|
def getsvnbin():
|
||||||
|
svnbin = py.path.local.sysfind('svn')
|
||||||
|
if svnbin is None:
|
||||||
|
py.test.skip("svn binary not found")
|
||||||
|
return svnbin
|
||||||
|
|
||||||
|
|
||||||
# make a wc directory out of a given root url
|
# make a wc directory out of a given root url
|
||||||
# cache previously obtained wcs!
|
# cache previously obtained wcs!
|
||||||
#
|
#
|
||||||
|
|
|
@ -95,6 +95,7 @@ class svnwc_no_svn(py.path.svnwc):
|
||||||
class TestSvnWCAuth(object):
|
class TestSvnWCAuth(object):
|
||||||
def setup_method(self, meth):
|
def setup_method(self, meth):
|
||||||
self.auth = SvnAuth('user', 'pass', cache_auth=False)
|
self.auth = SvnAuth('user', 'pass', cache_auth=False)
|
||||||
|
svntestbase.getsvnbin()
|
||||||
|
|
||||||
def test_checkout(self):
|
def test_checkout(self):
|
||||||
wc = svnwc_no_svn('foo', auth=self.auth)
|
wc = svnwc_no_svn('foo', auth=self.auth)
|
||||||
|
@ -250,6 +251,7 @@ class TestSvnURLAuth(object):
|
||||||
|
|
||||||
class SvnAuthFunctionalTestBase(object):
|
class SvnAuthFunctionalTestBase(object):
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
|
svntestbase.getsvnbin()
|
||||||
if not option.runslowtests:
|
if not option.runslowtests:
|
||||||
py.test.skip('skipping slow functional tests - use --runslowtests '
|
py.test.skip('skipping slow functional tests - use --runslowtests '
|
||||||
'to override')
|
'to override')
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import py
|
import py
|
||||||
from py.__.path.svn.testing.svntestbase import make_test_repo
|
from py.__.path.svn.testing.svntestbase import make_test_repo, getsvnbin
|
||||||
|
|
||||||
|
|
||||||
if py.path.local.sysfind('svn') is None:
|
|
||||||
py.test.skip("cannot test py.path.svn, 'svn' binary not found")
|
|
||||||
|
|
||||||
class TestMakeRepo(object):
|
class TestMakeRepo(object):
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
|
getsvnbin()
|
||||||
cls.repo = make_test_repo()
|
cls.repo = make_test_repo()
|
||||||
cls.wc = py.path.svnwc(py.test.ensuretemp("test-wc").join("wc"))
|
cls.wc = py.path.svnwc(py.test.ensuretemp("test-wc").join("wc"))
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import py
|
import py
|
||||||
from py.__.path.svn.urlcommand import InfoSvnCommand
|
from py.__.path.svn.urlcommand import InfoSvnCommand
|
||||||
from py.__.path.svn.testing.svntestbase import CommonCommandAndBindingTests, \
|
from py.__.path.svn.testing.svntestbase import CommonCommandAndBindingTests, \
|
||||||
getrepowc
|
getrepowc, getsvnbin
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
|
|
||||||
def setup_module(mod):
|
def setup_module(mod):
|
||||||
if py.path.local.sysfind('svn') is None:
|
getsvnbin()
|
||||||
py.test.skip("cannot test py.path.svn, 'svn' binary not found")
|
|
||||||
|
|
||||||
class TestSvnURLCommandPath(CommonCommandAndBindingTests):
|
class TestSvnURLCommandPath(CommonCommandAndBindingTests):
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import py
|
import py
|
||||||
import sys
|
import sys
|
||||||
from py.__.path.svn.testing.svntestbase import CommonSvnTests, getrepowc
|
from py.__.path.svn.testing.svntestbase import CommonSvnTests, getrepowc, getsvnbin
|
||||||
from py.__.path.svn.wccommand import InfoSvnWCCommand, XMLWCStatus
|
from py.__.path.svn.wccommand import InfoSvnWCCommand, XMLWCStatus
|
||||||
from py.__.path.svn.wccommand import parse_wcinfotime
|
from py.__.path.svn.wccommand import parse_wcinfotime
|
||||||
from py.__.path.svn import svncommon
|
from py.__.path.svn import svncommon
|
||||||
|
@ -22,8 +22,7 @@ else:
|
||||||
return os.path.normpath(os.path.normcase(p))
|
return os.path.normpath(os.path.normcase(p))
|
||||||
|
|
||||||
def setup_module(mod):
|
def setup_module(mod):
|
||||||
if py.path.local.sysfind('svn') is None:
|
getsvnbin()
|
||||||
py.test.skip("cannot test py.path.svn, 'svn' binary not found")
|
|
||||||
|
|
||||||
class TestWCSvnCommandPath(CommonSvnTests):
|
class TestWCSvnCommandPath(CommonSvnTests):
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
|
|
|
@ -8,3 +8,4 @@ def getdata():
|
||||||
tmpdir = py.test.ensuretemp(rel.replace(pydir.sep, '_'))
|
tmpdir = py.test.ensuretemp(rel.replace(pydir.sep, '_'))
|
||||||
mydatadir.copy(tmpdir)
|
mydatadir.copy(tmpdir)
|
||||||
return tmpdir
|
return tmpdir
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import py
|
import py
|
||||||
try:
|
|
||||||
import docutils
|
|
||||||
except ImportError:
|
|
||||||
py.test.skip("docutils not present")
|
|
||||||
|
|
||||||
|
from py.__.rest.testing.setup import getdata
|
||||||
|
docutils = py.test.importorskip("docutils")
|
||||||
from py.__.rest import directive
|
from py.__.rest import directive
|
||||||
from py.__.misc import rest
|
from py.__.misc import rest
|
||||||
from py.__.rest.latex import process_rest_file
|
from py.__.rest.latex import process_rest_file
|
||||||
from py.__.rest.testing.setup import getdata
|
|
||||||
|
|
||||||
def setup_module(mod):
|
def setup_module(mod):
|
||||||
mod.datadir = getdata()
|
mod.datadir = getdata()
|
||||||
|
|
|
@ -4,16 +4,13 @@ import py
|
||||||
from py.__.misc import rest
|
from py.__.misc import rest
|
||||||
from py.__.rest.testing.setup import getdata
|
from py.__.rest.testing.setup import getdata
|
||||||
|
|
||||||
|
|
||||||
def setup_module(mod):
|
def setup_module(mod):
|
||||||
|
py.test.importorskip("docutils")
|
||||||
if not py.path.local.sysfind("gs") or \
|
if not py.path.local.sysfind("gs") or \
|
||||||
not py.path.local.sysfind("dot") or \
|
not py.path.local.sysfind("dot") or \
|
||||||
not py.path.local.sysfind("latex"):
|
not py.path.local.sysfind("latex"):
|
||||||
py.test.skip("ghostscript, graphviz and latex needed")
|
py.test.skip("ghostscript, graphviz and latex needed")
|
||||||
try:
|
|
||||||
import docutils
|
|
||||||
except ImportError:
|
|
||||||
py.test.skip("docutils not present")
|
|
||||||
|
|
||||||
mod.datadir = getdata()
|
mod.datadir = getdata()
|
||||||
|
|
||||||
def test_process_simple():
|
def test_process_simple():
|
||||||
|
|
|
@ -4,11 +4,7 @@ import py
|
||||||
from py.__.rest.latex import process_configfile, process_rest_file
|
from py.__.rest.latex import process_configfile, process_rest_file
|
||||||
from py.__.rest.testing.setup import getdata
|
from py.__.rest.testing.setup import getdata
|
||||||
|
|
||||||
try:
|
docutils = py.test.importorskip("docutils")
|
||||||
import docutils
|
|
||||||
except ImportError:
|
|
||||||
py.test.skip("docutils not present")
|
|
||||||
|
|
||||||
|
|
||||||
def setup_module(mod):
|
def setup_module(mod):
|
||||||
if not py.path.local.sysfind("gs") or \
|
if not py.path.local.sysfind("gs") or \
|
||||||
|
|
|
@ -49,31 +49,30 @@ def exit(msg):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Exit(msg)
|
raise Exit(msg)
|
||||||
|
|
||||||
def skip(msg="", ifraises=None, ns=None):
|
def skip(msg=""):
|
||||||
""" (conditionally) skip this test/module/conftest.
|
""" skip with the given message. """
|
||||||
|
|
||||||
msg: use this message when skipping.
|
|
||||||
ifraises:
|
|
||||||
if "exec ifraises in {'py': py}" raises an exception
|
|
||||||
skip this test.
|
|
||||||
ns: use this namespace when executing ifraises
|
|
||||||
"""
|
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
if ifraises is not None:
|
|
||||||
ifraises = py.code.Source(ifraises).compile()
|
|
||||||
if ns is None:
|
|
||||||
ns = {}
|
|
||||||
try:
|
|
||||||
exec ifraises in ns
|
|
||||||
except (KeyboardInterrupt, SystemExit):
|
|
||||||
raise
|
|
||||||
except Exception, e:
|
|
||||||
if not msg:
|
|
||||||
msg = repr(e)
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
raise Skipped(msg=msg)
|
raise Skipped(msg=msg)
|
||||||
|
|
||||||
|
def importorskip(modname, minversion=None):
|
||||||
|
""" return imported module or skip() """
|
||||||
|
compile(modname, '', 'eval') # to catch syntaxerrors
|
||||||
|
try:
|
||||||
|
mod = __import__(modname)
|
||||||
|
except ImportError:
|
||||||
|
py.test.skip("could not import %r" %(modname,))
|
||||||
|
if minversion is None:
|
||||||
|
return mod
|
||||||
|
verattr = getattr(mod, '__version__', None)
|
||||||
|
if isinstance(minversion, str):
|
||||||
|
minver = minversion.split(".")
|
||||||
|
else:
|
||||||
|
minver = list(minversion)
|
||||||
|
if verattr is None or verattr.split(".") < minver:
|
||||||
|
py.test.skip("module %r has __version__ %r, required is: %r" %(
|
||||||
|
modname, verattr, minversion))
|
||||||
|
return mod
|
||||||
|
|
||||||
def fail(msg="unknown failure"):
|
def fail(msg="unknown failure"):
|
||||||
""" fail with the given Message. """
|
""" fail with the given Message. """
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
|
|
@ -387,7 +387,7 @@ class TestPyTest(AcceptBase):
|
||||||
|
|
||||||
class TestInteractive(AcceptBase):
|
class TestInteractive(AcceptBase):
|
||||||
def getspawn(self):
|
def getspawn(self):
|
||||||
py.test.skip(ifraises="import pexpect", ns=globals())
|
pexpect = py.test.importorskip("pexpect")
|
||||||
def spawn(cmd):
|
def spawn(cmd):
|
||||||
return pexpect.spawn(cmd, logfile=self.tmpdir.join("spawn.out").open("w"))
|
return pexpect.spawn(cmd, logfile=self.tmpdir.join("spawn.out").open("w"))
|
||||||
return spawn
|
return spawn
|
||||||
|
|
|
@ -59,33 +59,25 @@ 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():
|
def test_skip_simple():
|
||||||
excinfo = py.test.raises(Skipped, 'py.test.skip("xxx")')
|
excinfo = py.test.raises(Skipped, '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()
|
||||||
|
|
||||||
def test_skip_ifraises():
|
def test_importorskip():
|
||||||
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_ns():
|
|
||||||
d = {}
|
|
||||||
py.test.skip(ns=d, ifraises="import py")
|
|
||||||
assert d['py'] == py
|
|
||||||
|
|
||||||
def test_skip_ifraises_syntaxerror():
|
|
||||||
try:
|
try:
|
||||||
excinfo = py.test.raises(SyntaxError, '''
|
sys = py.test.importorskip("sys")
|
||||||
py.test.skip(ifraises="x y z")''')
|
assert sys == py.std.sys
|
||||||
|
#path = py.test.importorskip("os.path")
|
||||||
|
#assert path == py.std.os.path
|
||||||
|
py.test.raises(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 = py.test.importorskip("py", minversion=".".join(py.__version__))
|
||||||
|
py.test.raises(Skipped, """
|
||||||
|
py.test.importorskip("py", minversion="5.0")
|
||||||
|
""")
|
||||||
except Skipped:
|
except Skipped:
|
||||||
py.test.fail("should not skip")
|
print py.code.ExceptionInfo()
|
||||||
assert not excinfo.traceback[-1].ishidden()
|
py.test.fail("spurious skip")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue