From 861f34fe90dbe1b8be5d37600443e6b3cfb7e108 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Thu, 22 Oct 2009 18:37:24 +0200 Subject: [PATCH] use new marking idioms, simplify generalized skipping implementation --HG-- branch : trunk --- _py/test/plugin/pytest_keyword.py | 2 + _py/test/plugin/pytest_skipping.py | 48 +++++++++---------- conftest.py | 4 +- testing/path/test_local.py | 8 ++-- testing/process/test_forkedfunc.py | 2 +- testing/pytest/plugin/test_pytest_runner.py | 3 +- testing/pytest/plugin/test_pytest_skipping.py | 35 +++----------- 7 files changed, 40 insertions(+), 62 deletions(-) diff --git a/_py/test/plugin/pytest_keyword.py b/_py/test/plugin/pytest_keyword.py index 626b6fea5..3119d2907 100644 --- a/_py/test/plugin/pytest_keyword.py +++ b/_py/test/plugin/pytest_keyword.py @@ -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. +.. _`scoped-marking`: + Marking classes or modules ---------------------------------------------------- diff --git a/_py/test/plugin/pytest_skipping.py b/_py/test/plugin/pytest_skipping.py index d6a787cec..b1074e0f7 100644 --- a/_py/test/plugin/pytest_skipping.py +++ b/_py/test/plugin/pytest_skipping.py @@ -13,15 +13,15 @@ reported at the end of test run through the terminal reporter. 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)") def test_function(): ... -The 'skipif' marker accepts an **arbitrary python expression** -as a condition. When setting up the test function the condition -is evaluated by calling ``eval(expr, namespace)``. The namespace +During test function setup the skipif condition is +evaluated by calling ``eval(expr, namespace)``. The namespace contains the ``sys`` and ``os`` modules as well as the test ``config`` object. The latter allows you to skip based 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(...): ... +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" ------------------------------------------------------- @@ -123,6 +127,7 @@ def pytest_runtest_makereport(__multicall__, item, call): rep.keywords['xfail'] = True # expr return rep +# called by terminalreporter progress reporting def pytest_report_teststatus(report): if 'xfail' in report.keywords: if report.skipped: @@ -165,29 +170,22 @@ def show_xfailed(terminalreporter): 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): - expr = getexpression(item, keyword) - result = None - if expr: - if isinstance(expr, str): + if isinstance(item, py.test.collect.Function): + markholder = getattr(item.obj, keyword, None) + result = False + if markholder: d = {'os': py.std.os, 'sys': py.std.sys, 'config': item.config} - result = eval(expr, d) - else: - result = expr - return expr, result + expr, result = None, True + for expr in markholder._args: + if isinstance(expr, str): + result = eval(expr, d) + else: + result = expr + if not result: + break + return expr, result + return None, False def folded_skips(skipped): d = {} diff --git a/conftest.py b/conftest.py index cc8a1128f..8f259767c 100644 --- a/conftest.py +++ b/conftest.py @@ -52,7 +52,7 @@ def pytest_generate_tests(metafunc): multi = getattr(metafunc.function, 'multi', None) if multi is None: return - assert len(multi.__dict__) == 1 - for name, l in multi.__dict__.items(): + assert len(multi._kwargs) == 1 + for name, l in multi._kwargs.items(): for val in l: metafunc.addcall(funcargs={name: val}) diff --git a/testing/path/test_local.py b/testing/path/test_local.py index 7af699387..727eae911 100644 --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -208,7 +208,7 @@ class TestLocalPath(common.CommonFSTests): assert l[2] == p3 class TestExecutionOnWindows: - skipif = "sys.platform != 'win32'" + pytestmark = py.test.mark.skipif("sys.platform != 'win32'") def test_sysfind(self): x = py.path.local.sysfind('cmd') @@ -216,7 +216,7 @@ class TestExecutionOnWindows: assert py.path.local.sysfind('jaksdkasldqwe') is None class TestExecution: - skipif = "sys.platform == 'win32'" + pytestmark = py.test.mark.skipif("sys.platform == 'win32'") def test_sysfind(self): x = py.path.local.sysfind('test') @@ -346,7 +346,7 @@ def test_homedir(): assert homedir.check(dir=1) class TestWINLocalPath: - skipif = "sys.platform != 'win32'" + pytestmark = py.test.mark.skipif("sys.platform != 'win32'") def test_owner_group_not_implemented(self): py.test.raises(NotImplementedError, "path1.stat().owner") @@ -395,7 +395,7 @@ class TestWINLocalPath: old.chdir() class TestPOSIXLocalPath: - skipif = "sys.platform == 'win32'" + pytestmark = py.test.mark.skipif("sys.platform == 'win32'") def test_samefile(self, tmpdir): assert tmpdir.samefile(tmpdir) diff --git a/testing/process/test_forkedfunc.py b/testing/process/test_forkedfunc.py index c6071387a..f9105d2bd 100644 --- a/testing/process/test_forkedfunc.py +++ b/testing/process/test_forkedfunc.py @@ -1,6 +1,6 @@ import py, sys, os -skipif = "not hasattr(os, 'fork')" +pytestmark = py.test.mark.skipif("not hasattr(os, 'fork')") def test_waitfinish_removes_tempdir(): ff = py.process.ForkedFunc(boxf1) diff --git a/testing/pytest/plugin/test_pytest_runner.py b/testing/pytest/plugin/test_pytest_runner.py index 08a6e8eec..641ff59f8 100644 --- a/testing/pytest/plugin/test_pytest_runner.py +++ b/testing/pytest/plugin/test_pytest_runner.py @@ -218,7 +218,8 @@ class TestExecutionNonForked(BaseFunctionalTests): py.test.fail("did not raise") class TestExecutionForked(BaseFunctionalTests): - skipif = "not hasattr(os, 'fork')" + pytestmark = py.test.mark.skipif("not hasattr(os, 'fork')") + def getrunner(self): return runner.forked_run_report diff --git a/testing/pytest/plugin/test_pytest_skipping.py b/testing/pytest/plugin/test_pytest_skipping.py index 24cc27d2c..6fc14b9c5 100644 --- a/testing/pytest/plugin/test_pytest_skipping.py +++ b/testing/pytest/plugin/test_pytest_skipping.py @@ -46,8 +46,8 @@ def test_xfail_decorator(testdir): def test_xfail_at_module(testdir): p = testdir.makepyfile(""" - xfail = 'True' - + import py + pytestmark = py.test.mark.xfail('True') def test_intentional_xfail(): assert 0 """) @@ -76,8 +76,9 @@ def test_skipif_decorator(testdir): def test_skipif_class(testdir): p = testdir.makepyfile(""" import py + class TestClass: - skipif = "True" + pytestmark = py.test.mark.skipif("True") def test_that(self): assert 0 def test_though(self): @@ -88,36 +89,12 @@ def test_skipif_class(testdir): "*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): from _py.test.plugin.pytest_skipping import evalexpression item, = testdir.getitems(""" + import py class TestClass: - skipif = "config._hackxyz" + pytestmark = py.test.mark.skipif("config._hackxyz") def test_func(self): pass """)