python - 过滤 pytest 固定装置
问题描述
这与旧问题基本相同,但希望现在有更好的解决方案。
问题:给定一个参数化的夹具,如何使用夹具对象的子集参数化测试功能?
示例:
import pytest
@pytest.fixture(params=range(7))
def square(request):
return request.param ** 2
def test_all_squares(square):
sqrt = square ** 0.5
assert sqrt == int(sqrt)
@pytest.fixture()
def odd_square(square):
if square % 2 == 1:
return square
pytest.skip()
def test_all_odd_squares(odd_square):
assert odd_square % 2 == 1
sqrt = odd_square ** 0.5
assert sqrt == int(sqrt)
输出:
$ pytest pytests.py -v =========================================== ========================= 测试会话开始 ======================= ============================================ ... 收集了 14 个项目 pytests.py::test_all_squares[0] 通过 [7%] pytests.py::test_all_squares[1] 通过 [14%] pytests.py::test_all_squares[2] 通过 [21%] pytests.py::test_all_squares[3] 通过 [28%] pytests.py::test_all_squares[4] 通过 [35%] pytests.py::test_all_squares[5] 通过 [42%] pytests.py::test_all_squares[6] 通过 [50%] pytests.py::test_all_odd_squares[0] 跳过 [57%] pytests.py::test_all_odd_squares[1] 通过 [64%] pytests.py::test_all_odd_squares[2] 跳过 [71%] pytests.py::test_all_odd_squares[3] 通过 [78%] pytests.py::test_all_odd_squares[4] 跳过 [85%] pytests.py::test_all_odd_squares[5] 通过 [92%] pytests.py::test_all_odd_squares[6] 跳过 [100%] ==================================================== ============ 10 次通过,4 次在 0.02 秒内跳过 ============================== =================================
虽然这可行,但并不理想:
- 它创建了总是被跳过的虚拟测试用例
- 它需要使用过滤的夹具的测试函数
odd_square
为参数提供不同的名称()。
我想要的是例如filter_fixture(predicate, fixture)
过滤原始夹具对象并可以传递给的函数,pytest.mark.parametrize
如下所示:
@pytest.mark.parametrize("square", filter_fixture(lambda x: x % 2 == 1, square))
def test_all_odd_squares(square):
assert square % 2 == 1
sqrt = square ** 0.5
assert sqrt == int(sqrt)
这在某种程度上可行吗?
解决方案
如果您需要一定程度的逻辑来确定将哪些参数应用于每个测试,您可能需要考虑使用pytest_generate_tests
钩子。
pytest_generate_tests
为每个收集的测试调用钩子函数。该metafunc
参数允许您动态参数化每个单独的测试用例。重写要使用的示例pytest_generate_tests
可能如下所示:
def pytest_generate_tests(metafunc):
square_parameters = (x**2 for x in range(7))
if 'square' in metafunc.fixturenames:
metafunc.parametrize("square", square_parameters)
if 'odd_square' in metafunc.fixturenames:
odd_square_parameters = (x for x in square_parameters if x % 2 == 1)
metafunc.parametrize("odd_square", odd_square_parameters)
def test_all_squares(square):
sqrt = square ** 0.5
assert sqrt == int(sqrt)
def test_all_odd_squares(odd_square):
assert odd_square % 2 == 1
sqrt = odd_square ** 0.5
assert sqrt == int(sqrt)
这将导致运行以下测试用例:
$ pytest -v pytests.py
=========== test session starts ===========
…
collected 10 items
pytests.py::test_all_squares[0] PASSED [ 10%]
pytests.py::test_all_squares[1] PASSED [ 20%]
pytests.py::test_all_squares[4] PASSED [ 30%]
pytests.py::test_all_squares[9] PASSED [ 40%]
pytests.py::test_all_squares[16] PASSED [ 50%]
pytests.py::test_all_squares[25] PASSED [ 60%]
pytests.py::test_all_squares[36] PASSED [ 70%]
pytests.py::test_all_odd_squares[1] PASSED [ 80%]
pytests.py::test_all_odd_squares[9] PASSED [ 90%]
pytests.py::test_all_odd_squares[25] PASSED [100%]
=========== 10 passed in 0.03s ===========
请注意,我的示例中的测试 ID 与您的略有不同。ìds
但是,您可以使用 的参数提供显式测试标识符metafunc.parametrize
。
推荐阅读
- c# - 用引号内的双引号替换单引号
- python - python烧瓶:如果request.method =='POST'附加到表单
- c# - 无法将 Apple Id 添加到 Visual Studio 2019
- python - Python,在一行中没有for循环的情况下搜索不在dict中的子字符串
- ios - 如何使用 UITextChecker 查找拼写错误的单词
- react-native - 平面列表不呈现数据
- mysql - 使用 JPA 在复合主键上创建多个外键时出现问题
- python-3.x - 编写程序以删除重复元素时列表索引超出范围
- sql - 具有非自动生成 ID 的 JPA 批量插入
- node.js - 如何使用 PM2 仅将一个特定的 nodeJS 应用程序部署到一个特定的环境?