1. 程式人生 > 其它 >Pytest學習-如何在用例程式碼中呼叫fixtrue時傳入引數

Pytest學習-如何在用例程式碼中呼叫fixtrue時傳入引數

前言

在使用Pytest的時候,為了提高程式碼的複用性,我們一般會把一些常用操作,比如把登入方法寫在 conftest.py 中,然後在不同測試用例中,呼叫這個登入方法。

但是在測試用例中,我們可能需要傳入不同的賬號密碼·,然後通過呼叫fixtrue中的登入函式對該賬戶進行登入,這裡就涉及到呼叫 fixture 時引數傳遞的問題了,今天我們就來學習下。

使用 pytest.mark.parametrize() 對函式傳參

在Pytest中,我們一般使用其裝飾器 @pytest.mark.parametrize() 來實現引數化。

下面是一個簡單的示例:

import pytest


data = [
    ["user1", "password1"],
    ["wintest", "wintest"],
    ["user2", "password2"]
]


def login_user(username, password):
    print("登入使用者:{}".format(username))
    print("登入密碼:{}".format(password))
    return True if (username == "wintest" and password == "wintest") else False


@pytest.mark.parametrize("username, password", data)
def test_login_user(username, password):
    res = login_user(username, password)
    assert res

我們在 conftest.py 中把用例開始和結束給打印出來,以便看起來更直觀。

@pytest.fixture(autouse=True)
def start_end():
    print("------------------------Start---------------------------")
    yield
    print("------------------------End---------------------------")

把以上用例執行後,得到結果如下:

------------------------Start---------------------------
登入使用者:user1
登入密碼:password1
F------------------------End---------------------------
------------------------Start---------------------------
登入使用者:wintest
登入密碼:wintest
.------------------------End---------------------------
------------------------Start---------------------------
登入使用者:user2
登入密碼:password2
F------------------------End---------------------------

============================ FAILURES =============================
________________ test_login_user[user1-password1] _________________

username = 'user1', password = 'password1'

    @pytest.mark.parametrize("username, password", data)
    def test_login_user(username, password):
        res = login_user(username, password)
>       assert res
E       assert False

test_04.py:20: AssertionError
________________ test_login_user[user2-password2] _________________

username = 'user2', password = 'password2'

    @pytest.mark.parametrize("username, password", data)
    def test_login_user(username, password):
        res = login_user(username, password)
>       assert res
E       assert False

test_04.py:20: AssertionError
2 failed, 1 passed in 0.13 seconds

request接收引數

我們通過檢視fixture的原始碼,可以知道 fixture 下可以有以下5個引數,引數預設值如下:

def fixture(scope="function", params=None, autouse=False, ids=None, name=None):

在這些引數中,有一個引數 params ,它表示當前引數列表,而我們想要拿到當前的引數,可以通過 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``.

我們把上面函式傳參的用例改一下,然後對 request.param 進行簡單的示例:

import pytest


def test_login_user(login_user):
    res = login_user
    assert res

修改 conftest.py 如下:

import pytest


data = [
    ["user1", "password1"],
    ["wintest", "wintest"],
    ["user2", "password2"]
]


@pytest.fixture(scope="function", params=data, autouse=False)
def login_user(request):
    username = request.param[0]
    password = request.param[1]
    print("登入使用者:{}".format(username))
    print("登入密碼:{}".format(password))
    return True if (username == "wintest" and password == "wintest") else False


@pytest.fixture(scope="function", autouse=True)
def start_end():
    print("------------------------Start---------------------------")
    yield
    print("------------------------End---------------------------")

把以上用例執行後,得到結果如下:

------------------------Start---------------------------
登入使用者:user1
登入密碼:password1
F------------------------End---------------------------
------------------------Start---------------------------
登入使用者:wintest
登入密碼:wintest
.------------------------End---------------------------
------------------------Start---------------------------
登入使用者:user2
登入密碼:password2
F------------------------End---------------------------

============================ FAILURES =============================
__________________ test_login_user[login_user0] ___________________

login_user = False

    def test_login_user(login_user):
        res = login_user
>       assert res
E       assert False

test_04.py:6: AssertionError
__________________ test_login_user[login_user2] ___________________

login_user = False

    def test_login_user(login_user):
        res = login_user
>       assert res
E       assert False

test_04.py:6: AssertionError
2 failed, 1 passed in 0.17 seconds

呼叫fixtrue時結合request傳參

在上面的程式碼中,我們是把含有使用者賬號密碼的data資料直接放在 conftest.py 中,如果我需要在測試用例中呼叫 fixtrue 時才傳入賬號密碼,那應該要怎麼做呢?

可以在測試用例中通過 @pytest.mark.parametrize() ,把呼叫的fixtrue當作一個函式來進行引數傳遞,最後再使用request接收引數。

我們繼續對上面的程式碼進行修改,先修改測試用例部分程式碼:

import pytest


data = [
    ["user1", "password1"],
    ["wintest", "wintest"],
    ["user2", "password2"]
]


# indirect=True的作用是為了把 login_user 當作一個fixture函式進行呼叫和傳遞
@pytest.mark.parametrize("login_user", data, indirect=True)
def test_login_user(login_user):
    res = login_user
    assert res

修改 conftest.py 如下:

import pytest


@pytest.fixture(scope="function", autouse=False)
def login_user(request):
    username = request.param[0]
    password = request.param[1]
    print("登入使用者:{}".format(username))
    print("登入密碼:{}".format(password))
    return True if (username == "wintest" and password == "wintest") else False


@pytest.fixture(scope="function", autouse=True)
def start_end():
    print("------------------------Start---------------------------")
    yield
    print("------------------------End---------------------------")

把以上用例執行後,得到結果如下:

------------------------Start---------------------------
登入使用者:user1
登入密碼:password1
F------------------------End---------------------------
------------------------Start---------------------------
登入使用者:wintest
登入密碼:wintest
.------------------------End---------------------------
------------------------Start---------------------------
登入使用者:user2
登入密碼:password2
F------------------------End---------------------------

============================ FAILURES =============================
__________________ test_login_user[login_user0] ___________________

login_user = False

    @pytest.mark.parametrize("login_user", data, indirect=True)
    def test_login_user(login_user):
        res = login_user
>       assert res
E       assert False

test_04.py:15: AssertionError
__________________ test_login_user[login_user2] ___________________

login_user = False

    @pytest.mark.parametrize("login_user", data, indirect=True)
    def test_login_user(login_user):
        res = login_user
>       assert res
E       assert False

test_04.py:15: AssertionError
2 failed, 1 passed in 0.10 seconds