gsa*_*kis 5 python fixtures 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)
Run Code Online (Sandbox Code Playgroud)
输出:
$ 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%] =================================================== ============ 0.02 秒内10 个通过,4 个跳过 ================================ ==================================
虽然这有效,但并不理想:
odd_square它需要使用过滤后的装置的测试函数为参数提供不同的名称 ( )。我想要的是一个filter_fixture(predicate, fixture)过滤原始灯具对象并可以传递给 的函数pytest.mark.parametrize,如下所示:
$ pytest pytests.py -v =================================================================== test session starts =================================================================== ... collected 14 items pytests.py::test_all_squares[0] PASSED [ 7%] pytests.py::test_all_squares[1] PASSED [ 14%] pytests.py::test_all_squares[2] PASSED [ 21%] pytests.py::test_all_squares[3] PASSED [ 28%] pytests.py::test_all_squares[4] PASSED [ 35%] pytests.py::test_all_squares[5] PASSED [ 42%] pytests.py::test_all_squares[6] PASSED [ 50%] pytests.py::test_all_odd_squares[0] SKIPPED [ 57%] pytests.py::test_all_odd_squares[1] PASSED [ 64%] pytests.py::test_all_odd_squares[2] SKIPPED [ 71%] pytests.py::test_all_odd_squares[3] PASSED [ 78%] pytests.py::test_all_odd_squares[4] SKIPPED [ 85%] pytests.py::test_all_odd_squares[5] PASSED [ 92%] pytests.py::test_all_odd_squares[6] SKIPPED [100%] ============================================================== 10 passed, 4 skipped in 0.02s ==============================================================
这在某种程度上可行吗?
如果您需要一定程度的逻辑来确定将哪些参数应用于每个测试,您可能需要考虑使用钩子pytest_generate_tests 。
pytest_generate_tests每个收集的测试都会调用钩子函数。该metafunc参数允许您动态参数化每个单独的测试用例。重写您的示例以使用pytest_generate_tests可能如下所示:
def pytest_generate_tests(metafunc):\n square_parameters = (x**2 for x in range(7))\n if \'square\' in metafunc.fixturenames:\n metafunc.parametrize("square", square_parameters)\n if \'odd_square\' in metafunc.fixturenames:\n odd_square_parameters = (x for x in square_parameters if x % 2 == 1)\n metafunc.parametrize("odd_square", odd_square_parameters)\n\ndef test_all_squares(square):\n sqrt = square ** 0.5\n assert sqrt == int(sqrt)\n\ndef test_all_odd_squares(odd_square):\n assert odd_square % 2 == 1\n sqrt = odd_square ** 0.5\n assert sqrt == int(sqrt)\nRun Code Online (Sandbox Code Playgroud)\n这会导致运行以下测试用例:
\n$ pytest -v pytests.py \n=========== test session starts ===========\n\xe2\x80\xa6\ncollected 10 items\n\npytests.py::test_all_squares[0] PASSED [ 10%]\npytests.py::test_all_squares[1] PASSED [ 20%]\npytests.py::test_all_squares[4] PASSED [ 30%]\npytests.py::test_all_squares[9] PASSED [ 40%]\npytests.py::test_all_squares[16] PASSED [ 50%]\npytests.py::test_all_squares[25] PASSED [ 60%]\npytests.py::test_all_squares[36] PASSED [ 70%]\npytests.py::test_all_odd_squares[1] PASSED [ 80%]\npytests.py::test_all_odd_squares[9] PASSED [ 90%]\npytests.py::test_all_odd_squares[25] PASSED [100%]\n\n=========== 10 passed in 0.03s ===========\nRun Code Online (Sandbox Code Playgroud)\n请注意,我的示例中的测试 ID 与您的略有不同。但是,您可以使用\xc3\xacds参数提供显式测试标识符metafunc.parametrize提供显式测试标识符。