1. 程式人生 > 實用技巧 >pytest文件42-fixture引數化params

pytest文件42-fixture引數化params

前言

引數化是自動化測試裡面必須掌握的一個知識點,用過 unittest 框架的小夥伴都知道使用 ddt 來實現測試用例的引數化。
pytest 測試用例裡面對應的引數可以用 parametrize 實現,隨著用例的增多,我們的需求也會越來越多,那麼如何在 fixture 中使用引數呢?

fixture 原始碼

先看下 fixture 原始碼,有這幾個引數:scope,params,autouse,ids,name。

def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
    """Decorator to mark a fixture factory function.

    This decorator can be used, with or without parameters, to define a
    fixture function.

    The name of the fixture function can later be referenced to cause its
    invocation ahead of running tests: test
    modules or classes can use the ``pytest.mark.usefixtures(fixturename)``
    marker.

    Test functions can directly use fixture names as input
    arguments in which case the fixture instance returned from the fixture
    function will be injected.

    Fixtures can provide their values to test functions using ``return`` or ``yield``
    statements. When using ``yield`` the code block after the ``yield`` statement is executed
    as teardown code regardless of the test outcome, and must yield exactly once.

    :arg scope: the scope for which this fixture is shared, one of
                ``"function"`` (default), ``"class"``, ``"module"``,
                ``"package"`` or ``"session"``.

                ``"package"`` is considered **experimental** at this time.

    :arg params: an optional list of parameters which will cause multiple
                invocations of the fixture function and all of the tests
                using it.
                The current parameter is available in ``request.param``.

    :arg autouse: if True, the fixture func is activated for all tests that
                can see it.  If False (the default) then an explicit
                reference is needed to activate the fixture.

    :arg ids: list of string ids each corresponding to the params
                so that they are part of the test id. If no ids are provided
                they will be generated automatically from the params.

    :arg name: the name of the fixture. This defaults to the name of the
                decorated function. If a fixture is used in the same module in
                which it is defined, the function name of the fixture will be
                shadowed by the function arg that requests the fixture; one way
                to resolve this is to name the decorated function
                ``fixture_<fixturename>`` and then use
                ``@pytest.fixture(name='<fixturename>')``.
    """
    if callable(scope) and params is None and autouse is False:
        # direct decoration
        return FixtureFunctionMarker("function", params, autouse, name=name)(scope)
    if params is not None and not isinstance(params, (list, tuple)):
        params = list(params)
    return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)

重點看 params 引數:一個可選的引數列表,它將導致多次呼叫fixture函式和使用它的所有測試
獲取當前引數可以使用 request.param

    :arg params: an optional list of parameters which will cause multiple
                invocations of the fixture function and all of the tests
                using it.
                The current parameter is available in ``request.param``.

fixture 之 params 使用示例

request 是pytest的內建 fixture ,主要用於傳遞引數

# test_fixture_params.py
import pytest
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/


# 測試資料,存放在list
user_data = ["user1", "user2"]

@pytest.fixture(scope="function", params=user_data)
def users(request):
    '''註冊使用者引數化'''
    return request.param


def test_register(users):
    print("註冊使用者:%s"%users)

if __name__ == '__main__':
    pytest.main(["-s", "test_fixture_params"])

執行結果

>pytest test_fixture_params.py -s
============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-4.5.0, py-1.5.4, pluggy-0.13.1
rootdir: D:\soft\demo
plugins: allure-pytest-2.8.6
collected 2 items

test_fixture_params.py 註冊使用者:user1
.註冊使用者:user2
.

========================== 2 passed in 0.02 seconds ===========================

後置清理資料

如果每次註冊使用者之前,需先在前置操作裡面清理使用者登錄檔的資料,可以執行SQL,傳不同使用者的引數

# test_fixture_params.py
import pytest
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

def delete_sql(user):
    '''這裡執行SQL'''
    sql = "delete from auth_user WHERE username = '%s';"%user
    print("執行的sql:%s"%sql)
    # 呼叫執行SQL的封裝函式


# 測試資料,存放在list
user_data = ["user1", "user2"]

@pytest.fixture(scope="function", params=user_data)
def users(request):
    '''註冊使用者引數化'''

    # 前置操作
    delete_sql(request.param)

    yield request.param

    # # 後置操作
    # delete_sql(request.param)


def test_register(users):
    print("註冊使用者:%s"%users)

if __name__ == '__main__':
    pytest.main(["-s", "test_fixture_params.py"])

執行結果

collected 2 items

test_fixture_params.py 執行的sql:delete from auth_user WHERE username = 'user1';
註冊使用者:user1
.執行的sql:delete from auth_user WHERE username = 'user2';
註冊使用者:user2
.

========================== 2 passed in 0.06 seconds ===========================

後置操作可以寫到 yield 後面,參考上面的格式。