[英]Pytest: test only one instance of parametrized fixture
假设我有conftest.py
,我在其中定义了测试资源
class ClassifyRequest:
pass
class OCRRequest:
pass
@pytest.fixture(params=[ClassifyRequest, OCRRequest])
def api_request(request):
return request.param() # return one of the request instances
然后,在test_api.py
中,我使用参数化夹具来测试服务:
def test_service(api_request):
response = send_request(api_request)
assert response.ok()
一切都很好,但我想测试专门的夹具api_request[ClassifyRequest]
:
@pytest.mark.usefixture("api_request[ClassifyRequest]")
def test_classification():
# do something with the api_request fixture
为测试功能专门化参数化夹具的方法是什么? 我有两个想法:
@pytest.mark.parametrize("response_class", ["classify", "ocr"]) def test_api(api_request): # do smth
用字符串替换类参数等于创建两个配置源。 如果我想添加另一个参数怎么办? 我是否必须为它设计一个新的字符串,以及在api_request
fixture 中间接实例化一个对象?conftest.py
之外,因为 pytest 无法使用 import 语句从该模块导入名称。pytest==6.0.1
如果您的所有夹具都是实例化,我会选择参数化测试,而不是夹具。 但是,好吧,如果您必须手动对其进行专门化,您可以简单地添加一个包装器以使夹具可调用:
import pytest
import types
class ClassifyRequest:
def __init__(self):
print("ClassifyRequest ctor")
class OCRRequest:
def __init__(self):
print("OCRRequest ctor")
def api_request_wrapper(request):
return request.param() # return one of the request instances
@pytest.fixture(params=[ClassifyRequest, OCRRequest])
def api_request(request):
return api_request_wrapper(request)
def test_classification():
request = types.SimpleNamespace()
request.param = ClassifyRequest
instance = api_request_wrapper(request)
不过,似乎有点hacky。
您要实现的是创建测试用例过滤规则。 最好的方法是通过 Pytest 中的“pytest_collection_modifyitems”挂钩。
一旦从您作为输入提供给 Pytest 的路径收集了所有测试,就会调用此钩子。
你可以把你的逻辑放在这个钩子里。
将 ID 与您的参数相关联始终是最佳实践,如下所示:
@pytest.fixture(params=[ClassifyRequest, OCRRequest],
ids=['ClassifyRequest', 'OCRRequest'])
def api_request(request):
return request.param() # return one of the request instances
一旦你有了这个,你的测试用例将生成为 test_classification[ClassifyRequest] 和 test_classification['OCRRequest']..
如果您正在运行特定的测试集并希望过滤应用于所有测试,那么 -k 选项本身就足够了。
但是因为这里它只在你想要应用规则的测试子集上,所以钩子定义可以在测试所在的模块中。
注意:这是一个初步的结论,我在 pytest Github 上创建了一个issue来看看社区对这个话题的看法。
我认为实现所需专业化的最简洁方法是将请求类移动到单独的模块并使用conftest.py
仅声明夹具功能。 根据 pytest 文档,
如果在实施测试期间您意识到要使用多个测试文件中的夹具 function,您可以将其移动到
conftest.py
文件。
如果您想让文件中的测试数据可用于您的测试,一个好方法是将这些数据加载到夹具中以供您的测试使用。
这样我可以在测试模块中导入类并通过测试函数间接参数化夹具。 在我的情况下,请求类很容易实例化,因此不需要为每个 class 单独的夹具,只需要聚合。 但一般来说,为每个资源定义一个夹具和一个聚合参数化夹具是可以的。
您还可以为ClassifyRequest
分离固定装置,并将其用于分类测试和api_request
固定装置。
假设请求的实例化是廉价的。 如果它们很贵,您可以考虑更改固定装置的范围。
@pytest.fixture
def classify_request():
return ClassifyRequest() # return ClassifyRequest instance
@pytest.fixture
def ocr_request():
return OCRRequest() # return OCRRequest instance
@pytest.fixture(params=["classify", "ocr"])
def api_request(request, classify_request, ocr_request):
# return one of the request instances
if request.param == "classify":
return classify_request
elif request.param == "ocr":
return ocr_request
assert False
否则(这是对您的想法的轻微修改),将您想要的类列入白名单test_classification
@pytest.fixture(params=[ClassifyRequest, OCRRequest])
def clazz(request):
return request.param
@pytest.fixture
def api_request(clazz):
return clazz()
@pytest.mark.parametrize("clazz", [ClassifyRequest], indirect=True)
def test_classification(api_request):
# do smth
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.