use new marking idioms, simplify generalized skipping implementation

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-10-22 18:37:24 +02:00
parent 4a76c096da
commit 861f34fe90
7 changed files with 40 additions and 62 deletions

View File

@ -33,6 +33,8 @@ In addition to keyword arguments you can also use positional arguments::
after which ``test_receive.webtest._args[0] == 'triangular`` holds true. after which ``test_receive.webtest._args[0] == 'triangular`` holds true.
.. _`scoped-marking`:
Marking classes or modules Marking classes or modules
---------------------------------------------------- ----------------------------------------------------

View File

@ -13,15 +13,15 @@ reported at the end of test run through the terminal reporter.
skip a test function conditionally skip a test function conditionally
------------------------------------------- -------------------------------------------
Here is an example for skipping a test function on Python3:: Here is an example for skipping a test function when
running on Python3::
@py.test.mark.skipif("sys.version_info >= (3,0)") @py.test.mark.skipif("sys.version_info >= (3,0)")
def test_function(): def test_function():
... ...
The 'skipif' marker accepts an **arbitrary python expression** During test function setup the skipif condition is
as a condition. When setting up the test function the condition evaluated by calling ``eval(expr, namespace)``. The namespace
is evaluated by calling ``eval(expr, namespace)``. The namespace
contains the ``sys`` and ``os`` modules as well as the contains the ``sys`` and ``os`` modules as well as the
test ``config`` object. The latter allows you to skip based test ``config`` object. The latter allows you to skip based
on a test configuration value e.g. like this:: on a test configuration value e.g. like this::
@ -30,6 +30,10 @@ on a test configuration value e.g. like this::
def test_function(...): def test_function(...):
... ...
Note that `test marking can be declared at whole class- or module level`_.
.. _`test marking can also be declared at whole class- or module level`: keyword.html#scoped-marking
conditionally mark a function as "expected to fail" conditionally mark a function as "expected to fail"
------------------------------------------------------- -------------------------------------------------------
@ -123,6 +127,7 @@ def pytest_runtest_makereport(__multicall__, item, call):
rep.keywords['xfail'] = True # expr rep.keywords['xfail'] = True # expr
return rep return rep
# called by terminalreporter progress reporting
def pytest_report_teststatus(report): def pytest_report_teststatus(report):
if 'xfail' in report.keywords: if 'xfail' in report.keywords:
if report.skipped: if report.skipped:
@ -165,29 +170,22 @@ def show_xfailed(terminalreporter):
tr._tw.line(pos) tr._tw.line(pos)
def getexpression(item, keyword):
if isinstance(item, py.test.collect.Function):
val = getattr(item.obj, keyword, None)
val = getattr(val, '_0', val)
if val is not None:
return val
cls = item.getparent(py.test.collect.Class)
if cls and hasattr(cls.obj, keyword):
return getattr(cls.obj, keyword)
mod = item.getparent(py.test.collect.Module)
if mod:
return getattr(mod.obj, keyword, None)
def evalexpression(item, keyword): def evalexpression(item, keyword):
expr = getexpression(item, keyword) if isinstance(item, py.test.collect.Function):
result = None markholder = getattr(item.obj, keyword, None)
if expr: result = False
if isinstance(expr, str): if markholder:
d = {'os': py.std.os, 'sys': py.std.sys, 'config': item.config} d = {'os': py.std.os, 'sys': py.std.sys, 'config': item.config}
result = eval(expr, d) expr, result = None, True
else: for expr in markholder._args:
result = expr if isinstance(expr, str):
return expr, result result = eval(expr, d)
else:
result = expr
if not result:
break
return expr, result
return None, False
def folded_skips(skipped): def folded_skips(skipped):
d = {} d = {}

View File

@ -52,7 +52,7 @@ def pytest_generate_tests(metafunc):
multi = getattr(metafunc.function, 'multi', None) multi = getattr(metafunc.function, 'multi', None)
if multi is None: if multi is None:
return return
assert len(multi.__dict__) == 1 assert len(multi._kwargs) == 1
for name, l in multi.__dict__.items(): for name, l in multi._kwargs.items():
for val in l: for val in l:
metafunc.addcall(funcargs={name: val}) metafunc.addcall(funcargs={name: val})

View File

@ -208,7 +208,7 @@ class TestLocalPath(common.CommonFSTests):
assert l[2] == p3 assert l[2] == p3
class TestExecutionOnWindows: class TestExecutionOnWindows:
skipif = "sys.platform != 'win32'" pytestmark = py.test.mark.skipif("sys.platform != 'win32'")
def test_sysfind(self): def test_sysfind(self):
x = py.path.local.sysfind('cmd') x = py.path.local.sysfind('cmd')
@ -216,7 +216,7 @@ class TestExecutionOnWindows:
assert py.path.local.sysfind('jaksdkasldqwe') is None assert py.path.local.sysfind('jaksdkasldqwe') is None
class TestExecution: class TestExecution:
skipif = "sys.platform == 'win32'" pytestmark = py.test.mark.skipif("sys.platform == 'win32'")
def test_sysfind(self): def test_sysfind(self):
x = py.path.local.sysfind('test') x = py.path.local.sysfind('test')
@ -346,7 +346,7 @@ def test_homedir():
assert homedir.check(dir=1) assert homedir.check(dir=1)
class TestWINLocalPath: class TestWINLocalPath:
skipif = "sys.platform != 'win32'" pytestmark = py.test.mark.skipif("sys.platform != 'win32'")
def test_owner_group_not_implemented(self): def test_owner_group_not_implemented(self):
py.test.raises(NotImplementedError, "path1.stat().owner") py.test.raises(NotImplementedError, "path1.stat().owner")
@ -395,7 +395,7 @@ class TestWINLocalPath:
old.chdir() old.chdir()
class TestPOSIXLocalPath: class TestPOSIXLocalPath:
skipif = "sys.platform == 'win32'" pytestmark = py.test.mark.skipif("sys.platform == 'win32'")
def test_samefile(self, tmpdir): def test_samefile(self, tmpdir):
assert tmpdir.samefile(tmpdir) assert tmpdir.samefile(tmpdir)

View File

@ -1,6 +1,6 @@
import py, sys, os import py, sys, os
skipif = "not hasattr(os, 'fork')" pytestmark = py.test.mark.skipif("not hasattr(os, 'fork')")
def test_waitfinish_removes_tempdir(): def test_waitfinish_removes_tempdir():
ff = py.process.ForkedFunc(boxf1) ff = py.process.ForkedFunc(boxf1)

View File

@ -218,7 +218,8 @@ class TestExecutionNonForked(BaseFunctionalTests):
py.test.fail("did not raise") py.test.fail("did not raise")
class TestExecutionForked(BaseFunctionalTests): class TestExecutionForked(BaseFunctionalTests):
skipif = "not hasattr(os, 'fork')" pytestmark = py.test.mark.skipif("not hasattr(os, 'fork')")
def getrunner(self): def getrunner(self):
return runner.forked_run_report return runner.forked_run_report

View File

@ -46,8 +46,8 @@ def test_xfail_decorator(testdir):
def test_xfail_at_module(testdir): def test_xfail_at_module(testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""
xfail = 'True' import py
pytestmark = py.test.mark.xfail('True')
def test_intentional_xfail(): def test_intentional_xfail():
assert 0 assert 0
""") """)
@ -76,8 +76,9 @@ def test_skipif_decorator(testdir):
def test_skipif_class(testdir): def test_skipif_class(testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""
import py import py
class TestClass: class TestClass:
skipif = "True" pytestmark = py.test.mark.skipif("True")
def test_that(self): def test_that(self):
assert 0 assert 0
def test_though(self): def test_though(self):
@ -88,36 +89,12 @@ def test_skipif_class(testdir):
"*2 skipped*" "*2 skipped*"
]) ])
def test_getexpression(testdir):
from _py.test.plugin.pytest_skipping import getexpression
l = testdir.getitems("""
import py
mod = 5
class TestClass:
cls = 4
@py.test.mark.func(3)
def test_func(self):
pass
@py.test.mark.just
def test_other(self):
pass
""")
item, item2 = l
assert getexpression(item, 'xyz') is None
assert getexpression(item, 'func') == 3
assert getexpression(item, 'cls') == 4
assert getexpression(item, 'mod') == 5
assert getexpression(item2, 'just')
item2.parent = None
assert not getexpression(item2, 'nada')
def test_evalexpression_cls_config_example(testdir): def test_evalexpression_cls_config_example(testdir):
from _py.test.plugin.pytest_skipping import evalexpression from _py.test.plugin.pytest_skipping import evalexpression
item, = testdir.getitems(""" item, = testdir.getitems("""
import py
class TestClass: class TestClass:
skipif = "config._hackxyz" pytestmark = py.test.mark.skipif("config._hackxyz")
def test_func(self): def test_func(self):
pass pass
""") """)