py.test : 可以在测试功能级别应用多个标记吗?
py.test : Can multiple markers be applied at the test function level?
我从 the pytest docs 了解到我们可以在 Class 或模块级别一次应用多个标记。我没有找到在测试功能级别执行此操作的文档。有没有人成功地这样做过?
我想理想地把它作为标记列表来做,就像在上面的文档中为 Classes 所做的那样,例如(从文档中引用):
class TestClass:
pytestmark = [pytest.mark.webtest, pytest.mark.slowtest]
因此,pytest 文档讨论了使用 pytestmark
在 class 和模块级别指定标记。但是,它并没有谈论在测试功能级别上有类似的东西。我将不得不在测试函数之上单独指定标记,以便用它们中的每一个标记它们。随着测试函数顶部标记数量的增加,这使得测试代码看起来有点笨拙。
test_example.py:
pytestmark = [class1, class2]
class TestFeature(TestCase):
@pytest.mark.marker1
@pytest.mark.marker2
@pytest.mark.marker3
def test_function(self):
assert True
我自己还没有尝试过。但是,快速浏览一下 the source,我认为 class MarkDecorator
就是您想要的。尝试:
mark_names=["marker1", "marker2", "marker3"]
my_marks = pytest.MarkDecorator(*mark_names)
marked_test_function = my_marks(test_function)
*mark_names
只是将 mark_names
解包到 MarkDecorator
的构造函数参数中。 MarkDecorator.__call__
然后将存储的标记 (self.args
) 应用于参数,此处为 test_function
,以提供标记测试功能。
您也可以使用 def unmarked_test_function() ...
和 test_function=my_marks(unmarked_test_function)
,这样您就不必更改名称。
补充说明: 我从 pytest.mark
那里得到了这个,turns out to be 一个 MarkGenerator
单身人士。 MarkGenerator
创建 MarkDecorator
classes,然后将其用作装饰器。上面的代码手动模拟了这个过程,填充了多个标记。
对于函数,您只需重复装饰器即可:
@pytest.mark.webtest
@pytest.mark.slowtest
def test_something(...):
...
如果你想在多个测试中重用它,你应该记住装饰器只是返回装饰物的函数,所以几个装饰器只是一个组合:
def compose_decos(decos):
def composition(func):
for deco in reversed(decos):
func = deco(func)
return func
return composition
all_marks = compose_decos(pytest.mark.webtest, pytest.mark.slowtest)
@all_marks
def test_something(...):
...
或者您可以使用通用组合,例如我的 funcy 库有:
from funcy import compose
all_marks = compose(pytest.mark.webtest, pytest.mark.slowtest)
请注意,您可以通过这种方式编写任何装饰器,而不仅仅是 pytest 标记。
我从 the pytest docs 了解到我们可以在 Class 或模块级别一次应用多个标记。我没有找到在测试功能级别执行此操作的文档。有没有人成功地这样做过?
我想理想地把它作为标记列表来做,就像在上面的文档中为 Classes 所做的那样,例如(从文档中引用):
class TestClass:
pytestmark = [pytest.mark.webtest, pytest.mark.slowtest]
因此,pytest 文档讨论了使用 pytestmark
在 class 和模块级别指定标记。但是,它并没有谈论在测试功能级别上有类似的东西。我将不得不在测试函数之上单独指定标记,以便用它们中的每一个标记它们。随着测试函数顶部标记数量的增加,这使得测试代码看起来有点笨拙。
test_example.py:
pytestmark = [class1, class2]
class TestFeature(TestCase):
@pytest.mark.marker1
@pytest.mark.marker2
@pytest.mark.marker3
def test_function(self):
assert True
我自己还没有尝试过。但是,快速浏览一下 the source,我认为 class MarkDecorator
就是您想要的。尝试:
mark_names=["marker1", "marker2", "marker3"]
my_marks = pytest.MarkDecorator(*mark_names)
marked_test_function = my_marks(test_function)
*mark_names
只是将 mark_names
解包到 MarkDecorator
的构造函数参数中。 MarkDecorator.__call__
然后将存储的标记 (self.args
) 应用于参数,此处为 test_function
,以提供标记测试功能。
您也可以使用 def unmarked_test_function() ...
和 test_function=my_marks(unmarked_test_function)
,这样您就不必更改名称。
补充说明: 我从 pytest.mark
那里得到了这个,turns out to be 一个 MarkGenerator
单身人士。 MarkGenerator
创建 MarkDecorator
classes,然后将其用作装饰器。上面的代码手动模拟了这个过程,填充了多个标记。
对于函数,您只需重复装饰器即可:
@pytest.mark.webtest
@pytest.mark.slowtest
def test_something(...):
...
如果你想在多个测试中重用它,你应该记住装饰器只是返回装饰物的函数,所以几个装饰器只是一个组合:
def compose_decos(decos):
def composition(func):
for deco in reversed(decos):
func = deco(func)
return func
return composition
all_marks = compose_decos(pytest.mark.webtest, pytest.mark.slowtest)
@all_marks
def test_something(...):
...
或者您可以使用通用组合,例如我的 funcy 库有:
from funcy import compose
all_marks = compose(pytest.mark.webtest, pytest.mark.slowtest)
请注意,您可以通过这种方式编写任何装饰器,而不仅仅是 pytest 标记。