pytest - Pytest - 是否可以创建一个过滤另一个夹具的夹具?
问题描述
我有这个代码(谢谢,MT):
url_list = [
['example1.com/x', 'example2.com/x'],
['example1.com/y', 'example2.com/y'],
['example1.com/z', 'example2.com/z'],
['example1.com/v', 'example2.com/v'],
['example1.com/w', 'example2.com/w'],
]
@pytest.fixture(scope="session", params=url_pairs)
def response_pairs(request):
url_a, url_b = request.param
yield requests.get(url_a), requests.get(url_b)
def test_1(response_pairs):
response_a, response_b = response_pairs
assert response_a.status_code == response_b.status_code
except Exception as e:
yield e, None
@pytest.mark.parametrize("field", ["one", "two", "three", "four", "five"])
def test_2(field, response_pairs):
body_a = response_pairs[0].json()
body_b = response_pairs[1].json()
assert body_a[field] == body_b[field]
到目前为止,这工作正常。
现在,我想test_2
根据status_code
.
所以我创建了多个副本并为每个副本test_2
添加了语句:if
@pytest.mark.parametrize("field", ["one", "two", "three", "four", "five"])
def test_200(field, response_pairs):
response_a, response_b = response_pairs
if response_a.status_code == response_b.status_code == 200:
body_a = response_a.json()
body_b = response_b.json()
assert body_a[field] == body_b[field]
@pytest.mark.parametrize("field", ["reason", "text"])
def test_404(field, response_pairs):
response_a, response_b = response_pairs
if response_a.status_code == response_b.status_code == 404:
assert getattr(response_a, field, None).lower() == getattr(response_b, field, None).lower()
@pytest.mark.parametrize("field", ["reason", "text"])
def test_error(field, response_pairs):
response_a, response_b = response_pairs
if response_a.status_code == response_b.status_code and response_a.status_code not in [200, 404]:
assert getattr(response_a, field, None).lower() == getattr(response_b, field, None).lower()
这工作正常,但我得到了所有那些“成功”的测试False
案例if
有没有办法过滤掉它们?
我尝试创建一个过滤掉成功的夹具:
@pytest.fixture
def responses_200(response_pairs):
for response_a, response_b in response_pairs:
if response_a.status_code == response_b.status_code == 200:
yield response_a, response_b
(对于 404s 等也是如此)
但这不起作用。它并没有摆脱无意义的测试,而是一切都失败了:
所以我尝试response_pairs
从参数列表中删除:
@pytest.fixture
def responses_200(request):
for response_a, response_b in response_pairs:
if response_a.status_code == response_b.status_code == 200:
yield response_a, response_b
现在安装失败TypeError: 'function' object is not iterable
:
我还在学习如何使用固定装置...
是否可以创建一个过滤另一个夹具的夹具?
解决方案
在没有重现您的错误的情况下,关于观察到的错误有两个评论:
- 您需要将要使用的夹具名称添加到参数列表中(在本例中
response_pairs
)。如果您删除它,则在函数中引用其名称返回的值不是您期望的固定值,而是函数本身(因此您尝试遍历函数的错误消息) - 在任何给定的测试中,我都希望
response_pairs
只包含一对。因此,我会尝试删除 for 循环,然后像这样解压缩那一对:
@pytest.fixture
def responses_200(response_pairs):
response_a, response_b = response_pairs
if response_a.status_code == response_b.status_code == 200:
yield response_a, response_b
我希望这可以避免观察到的错误,但我不确定它是否会产生仅针对状态 200 响应执行测试的预期结果。
至少可以避免执行测试的一种稍微笨拙的方法是从夹具内部跳过它们:
简化示例:
import pytest
rl_list = [
['example1.com/x', 200],
['example1.com/y', 404],
['example1.com/z', 200],
]
@pytest.fixture(scope="session", params=rl_list)
def url_response_pair(request):
url, response = request.param
yield url, response
@pytest.fixture(scope="session")
def response_200(url_response_pair):
url, response = url_response_pair
if response != 200:
pytest.skip('Skipping 200 test for response code {response} from url {url}')
def test_something_for_response_200(response_200):
print("testing something")
推荐阅读
- multithreading - 多线程会增加 CPU 时间吗?
- c - 宏上的空括号有什么作用?
- bigcommerce - 为什么选项端点返回我没有创建的选项值?
- php - 从两个表中的任何一个中获取单行
- elasticsearch - 由于据称磁盘可用空间不足,ElasticSearch 错误地停止了索引
- neo4j - NEO4J Cypher - 过滤路径变量
- python - 如何在python中以对齐的方式打印动态二维列表?
- php - 具有 2 个提供数据的 API 的 laravel 应用程序的正确结构
- sql-server - 将子表链接到多个父表的最佳方法是什么?
- python - 代码优化 | 比 dataframe.iterrows() 更快的方法?