您的位置:

pytestmark详解

一、pytestmark是什么?

pytestmark是pytest框架提供的装饰器,可以用来装饰整个文件或文件中的某些函数,其作用是将标记(mark)与被装饰的函数或文件相关联。

在pytest中,标记是一种在运行测试用例时动态影响测试用例执行的工具。通过pytestmark,可以在pytest命令行中使用不同的标记,例如-s,-m等

二、pytestmark的使用场景

1、使用pytestmark标记来提供一些默认的参数:可通过pytestmark为整个文件设置pytest.fixture()标记。这样,已被标记为fixture的函数,就可以在文件中被其他测试用例函数直接使用。

import pytest 
@pytest.fixture() 
def foo_fixture(): 
    return 'foo module' 
pytestmark = pytest.mark.usefixtures("foo_fixture") 

def test_foo(): 
    assert "foo module" == "foo module" 

在上述代码中,我们为整个文件设置了pytest.fixture()标记,并在pytestmark中使用了usefixtures。当运行test_foo函数时,将先运行foo_fixture()函数,因此test_foo函数中的代码可以有效地使用foo_fixture()。

2、使用pytestmark标记来指定测试用例的实例化方式:可通过pytestmark将测试用例与类或函数进行关联。

import pytest


@pytest.mark.webtest
class TestSomething:
    def test_one(self):
        pass
    def test_two(self):
        pass
@pytest.mark.nighttest    
class TestAnother:
    def test_three(self):
        pass
    def test_four(self):
        pass

在上述代码中,我们通过pytestmark将TestSomething和TestAnother类与不同的mark(webtest和nighttest)关联。在运行测试时,我们可以通过-m选项来执行哪种类型的测试用例。

3、使用pytestmark指定fixture执行范围:我们可以通过@pytest.mark. 用于指定Fixture的使用范围。

import pytest
@pytest.fixture(scope="module")
def foo():
    return 'foo'

def test_foo1(foo):
    assert foo == 'foo'

def test_foo2(foo):
    assert foo == 'foo'
pytestmark = pytest.mark.usefixtures("foo")

在上述代码中,我们将foo fixture设置为‘module’级别的fixture,在pytestmark中使用了usefixtures指定它的使用范围。在test_foo1和test_foo2中我们分别使用了foo fixture,它将在整个module的范围内使用。

三、pytestmark相关参数的使用方法

pytestmark也可以使用多个参数来定义一组标记列表


import pytest

@pytest.mark.parametrize("test_input, expected_output", [("3+5", 8), ("2+4", 6), ("6*9", 54)])
def test_eval(test_input, expected_output):
    assert eval(test_input) == expected_output
pytestmark = [pytest.mark.number, pytest.mark.eval] 

在上述代码中,我们使用pytest.mark.parameterize指定的参数值为test_input, expected_output。在pytestmark中,我们使用了一个长度为2的列表,分别包含了由number和eval标记所组成的标记列表。当我们运行测试用例时,可以通过“-m”参数来只运行标记为其中之一的测试用例。

四、pytestmark的多层嵌套标记

pytestmark也可以实现多层嵌套标记,使得多个标记可以被同时匹配

import pytest
@pytest.mark.parametrize("num", [1, 2, 3])
@pytest.mark.parametrize("letter", ["a", "b", "c"])
def test_multi_tag(num, letter):
    pass
pytestmark = pytest.mark.beta

在上述代码中,我们使用pytest.mark.parameterize指定了两个参数值,num和letter。在pytestmark中,我们使用了beta标记。运行时可以使用“-m”参数指定beta标记,同时也可以使用“-k”参数通过一个测试用例的名称键值对来指定需要运行的测试用例。

五、pytestmark的跨文件标记

pytestmark还可以实现跨文件标记,从而为整个测试套件添加标记。

我们可以在conftest.py文件中定义标记,在整个测试套件中使用。pytest也会自动加载相应的标记,从而使整个测试套件具有相同的属性。


#在conftest.py文件中

import pytest

# 为整个测试套件设置webtest标记
pytestmark = pytest.mark.webtest

在上述代码中,我们在conftest.py文件中定义了webtest标记。pytestmark的值设置为pytest.mark.webmark,从而为整个测试套件添加了webtest标记。在执行整个测试套件时,pytest会自动加载conftest.py文件并实现webtest标记。

六、结论

通过以上内容我们可以看出,pytestmark可以在许多方面提高测试用例的复用性和灵活性。通过使用pytestmark和标记参数,开发人员可以使pytest的整体测试环境更加高效和精准。