pytest:如何在同一函数中从夹具和 pytest.mark.parametrize 获取 return 值

pytest: how to get return value from a fixture and pytest.mark.parametrize in the same function

我正在努力完成以下任务:

我浏览了 pytest 文档和多个论坛。我没有得到任何答复。有人可以建议解决问题的方法吗?或者另一种方法?

编辑 1: 我希望数据库连接在设置函数中只发生一次。此数据库连接用于所有测试功能。测试函数将 运行 针对参数化值中的参数。我如何 return 来自 fixture 的 db_conn 值?

import pytest

@pytest.fixture(scope="module")
def conn():
    db_conn = get_db_conn()
    yield db_conn
    db_conn.close()


@pytest.mark.parametrize("arg",[1,2,3])
def test_1(arg):
    db_conn.insert(arg)
    process(arg)

@pytest.mark.parametrize("arg",["a","b","c"])
def test_2(arg):
    db_conn.insert(arg)
    process(arg)

是否尝试过将 conn 夹具作为测试参数传递?

import pytest

@pytest.fixture(scope="module")
def conn():
    db_conn = get_db_conn()
    yield db_conn
    db_conn.close()


@pytest.mark.parametrize("arg",[1,2,3])
def test_1(arg, conn):
    conn.insert(arg)
    process(arg)

@pytest.mark.parametrize("arg",["a","b","c"])
def test_2(arg, conn):
    conn.insert(arg)
    process(arg)

这个简单的模拟 (test_fixture_params.py) 应该演示用法:

import pytest


@pytest.fixture(scope="module")
def conn():
    print('Opening db connection')
    yield 'MY DB CONNECTION'
    print('Closing db connection')


@pytest.mark.parametrize("arg",[1,2,3])
def test_1(arg, conn):
    print(conn, arg)


@pytest.mark.parametrize("arg",["a","b","c"])
def test_2(arg, conn):
    print(conn, arg)

对于pytest -s test_fixture_params.py,输出应该是:

$ pytest -s test_fixture_params.py 
===================================================== test session starts =====================================================
platform linux -- Python 3.8.1, pytest-5.4.3, py-1.8.1, pluggy-0.13.1
collected 6 items                                                                                                             

test_fixture_params.py Opening db connection
MY DB CONNECTION 1
.MY DB CONNECTION 2
.MY DB CONNECTION 3
.MY DB CONNECTION a
.MY DB CONNECTION b
.MY DB CONNECTION c
.Closing db connection


====================================================== 6 passed in 0.03s ======================================================

希望对您有所帮助!

看起来 yield-fixtures 已弃用。我用这个解决了我的案子。 (try/except 块是为了防止测试方法不那么幼稚 true/false 并且可能引发坏事 :)

长话短说:是的,按名称传递夹具并使用额外的“请求”参数及其 .getfixturevalue 方法

import pytest

class TestFoo:
    @pytest.fixture
    def odd_numbers(self):
        return [1, 3, 5, 7]

    @pytest.fixture
    def even_numbers(self):
        return [2, 4, 6, 8]

    @pytest.fixture
    def mixed_numbers(self):
        return [1, 2, 3, 4]

    @pytest.mark.parametrize(
        ("fixture_name", "expected"),
        [
            pytest.param("mixed_numbers", True, marks=pytest.mark.xfail),
            pytest.param("odd_numbers", False),
            pytest.param("even_numbers", True),
        ],
    )
    def test_is_even_number(self, fixture_name, expected, request):
        numbers = request.getfixturevalue(fixture_name)
        result = expected
        for number in numbers:
            try:
                result = number % 2 == 0
            except:
                result = False
            assert result == expected