我正在使用 allure-pytest。我正在使用故事/标记来表示测试计划要求。我将标记列表添加到 pytest.ini 文件。在 conftest.py 中,我生成了一组尚未使用的标记。我想将每个缺失的标记作为跳过的测试添加到我的魅力报告中。有没有办法做到这一点?
我试过在 conftest.py 中创建测试
import pytest
import allure
import allure_commons
from allure_commons.model2 import TestResult, Status, Label, Parameter
from allure_commons.types import AttachmentType
from allure_commons.reporter import AllureReporter
from allure_commons.utils import uuid4
def pytest_collection_finish(session):
# get all the available markers defined in pytest.ini
marker_dict = session.config.getini('markers')
markers = set(marker_dict)
# get all the markers used in the collected tests
used_markers = set()
for item in session.items:
used_markers.update(set([m.name for m in item.iter_markers()]))
# find the markers defined in pytest.ini but not used in any of the tests
unused_markers = markers - used_markers
item = session.items[0]
# add skipped tests for the unused markers
if unused_markers and item:
print(item.parent)
for marker in unused_markers:
print("adding skipped test: ", marker)
args = marker.split(":")
name = args[0]
add_external_test_result(name, "skipped")
session.items.append(create_skipped_test(name, marker)) # generates an error for missing config
#skipped_test = pytest.Function(name=f"test_missing_{name}", parent=None, config=item.config) # generates an error for deprecated method
#skipped_test = item.from_parent(parent=item.parent, name=f"test_missing_{name}")
#skipped_test.add_marker(pytest.mark.skip(reason=f"No test created for marker({marker})"))
#session.items.append(skipped_test) # generates an error for the method not existing in the parent
def create_skipped_test(name, marker):
# create a dummy test function with a skipped marker
@pytest.mark.skip(reason=f"unmarked marker: {name}")
@pytest.mark.usefixtures() # add any necessary fixtures
def test_dummy():
pass
# add the marker to the test function
test_dummy = pytest.mark.parametrize(name, [marker])(test_dummy)
return test_dummy
好吧,这非常棘手,但我认为我已经使用
pytest_generate_tests
钩子和 pytest_collection_modifyitems
钩子包装器实现了预期的行为。
首先,您需要在您的
test_dummy
目录中的某处添加tests
,如下所示:
test_dummy.py
def test_dummy():
pass
然后在 conftest.py 你应该定义以下钩子函数:
import pytest
from _pytest.mark import Mark
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_collection_modifyitems(items):
# get all test_dummy instances (with each mark parameter)
skip_tests = [item for item in items if item.originalname == "test_dummy"]
# remove all test_dummy from items to prevent it's execution without skip mark
items[:] = [item for item in items if item.originalname != "test_dummy"]
# let all other pytest_collection_modifyitems filter items
yield
# get set of all used markers
used_markers = set()
for item in items:
used_markers.update(set([m.name for m in item.iter_markers()]))
for item in skip_tests:
# get mark name from parameter name of test_dummy instance
mark = item.name.rsplit("[")[-1][:-1]
# if mark name is not in used markers set:
if mark not in used_markers:
# add test_dummy with this mark and skip mark to items list
item.own_markers = [Mark(mark, (), {}), Mark("skip", (), {"reason": f"skip mark: `{mark}`"})]
items.append(item)
def pytest_generate_tests(metafunc):
"""Generate parametrization for test_dummy instance using only custom markers from `pytest.ini`."""
if metafunc.definition.name == "test_dummy":
# get list of CUSTOM markers from pytest.ini (without pytest plugins builtins markers!)
markers = set(mark.split(":", maxsplit=1)[0] for mark in metafunc.config._getini('markers'))
# add mark parameter to function arguments
if "mark" not in metafunc.fixturenames:
metafunc.fixturenames.append("mark")
metafunc.parametrize("mark", [pytest.param(mark) for mark in markers])
我在代码中添加了一些注释,因此您可以跟踪它的逻辑。
基本上,它使用每个自定义标记(在
pytest.ini中定义)为
test_dummy
创建参数化。然后它将所有 test_dummy
实例存储在单独的列表中,并将它们从 items
. 中删除
在其他插件完成所有过滤(包括 pytest 标记过滤)后,它会获得已使用标记的列表。对于每个具有不在使用列表中的参数的
test_dummy
实例,我们添加skip
标记和参数名称标记并将其添加到最终items
列表。
例子:
我在 pytest.ini 中有以下标记:
smoke
、regression
、unit
.
我对每个标记都有一个测试。我跑
pytest -m smoke --alluredir results
.
让我知道你的想法。这是你想要达到的目标吗?