use new marking idioms, simplify generalized skipping implementation
--HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									4a76c096da
								
							
						
					
					
						commit
						861f34fe90
					
				| 
						 | 
					@ -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 
 | 
				
			||||||
----------------------------------------------------
 | 
					----------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 = {}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
    """)
 | 
					    """)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue