Pytest測試框架(三):pytest fixture 用法

測試開發小記發表於2021-01-03

xUnit style 結構的 fixture用於初始化測試函式, pytest fixture是對傳統的 xUnit 架構的setup/teardown功能的改進。pytest fixture為測試準備一個良好的測試環境,測試函式使用的每個 fixture通常有一個引數(以 fixture 命名),測試函式通過引數訪問它們。本文將介紹pytest fixture的一些基本用法。

@pytest.fixture

import pytest

@pytest.fixture()
def login():
    print("登入")
    return 8

class Test_Demo():
    def test_case1(self):
        print("\n開始執行測試用例1")
        assert 1 + 1 == 2

    def test_case2(self, login):
        print("\n開始執行測試用例2")
        print(login)
        assert 2 + login == 10

    def test_case3(self):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100

if __name__ == '__main__':
    pytest.main()

test_case2需要呼叫login方法(或者獲取login的返回值),pytest 將會尋找並呼叫@pytest.fixture標記的login() 方法。

結果:

PASSED                           [ 33%]
開始執行測試用例1
登入
PASSED                           [ 66%]
開始執行測試用例2
8
PASSED                           [100%]
開始執行測試用例3

共享 fixture 函式:conftest.py

在測試過程中,多個測試檔案可能都要呼叫 fixture 函式,可以將其移動到 conftest.py 檔案中。conftest.py 檔案中的 fixture 函式不需要在測試函式中匯入,可以被 pytest 自動識別,查詢順序從測試類開始,然後是測試模組,然後是 conftest.py 檔案,最後是內建外掛和第三方外掛。

conftest.py :

import pytest
@pytest.fixture()
def login():
    print("登入")
    return 8

測試用例:

import pytest

class Test_Demo():
    def test_case1(self):
        print("\n開始執行測試用例1")
        assert 1 + 1 == 2

    def test_case2(self, login):
        print("\n開始執行測試用例2")
        print(login)
        assert 2 + login == 10

    def test_case3(self):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100


if __name__ == '__main__':
    pytest.main()

結果:

PASSED                           [ 33%]
開始執行測試用例1
登入
PASSED                           [ 66%]
開始執行測試用例2
8
PASSED                           [100%]
開始執行測試用例3

yield方法

使用yield關鍵字可以實現setup/teardown的功能,在yield關鍵字之前的程式碼在case之前執行,yield之後的程式碼在case執行結束後執行

import pytest

@pytest.fixture()
def login():
    print("登入")
    yield
    print("退出登入")

class Test_Demo():
    def test_case1(self):
        print("\n開始執行測試用例1")
        assert 1 + 1 == 2

    def test_case2(self, login):
        print("\n開始執行測試用例2")
        assert 2 + 8 == 10

    def test_case3(self):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100


if __name__ == '__main__':
    pytest.main()

結果:

PASSED                      [ 33%]
開始執行測試用例1
登入
PASSED                      [ 66%]
開始執行測試用例2
退出登入
PASSED                      [100%]
開始執行測試用例3

addfinalizer方法

addfinalizer也可以實現環境的清理,實現與yield方法相同的效果,跟yield不同的是需要註冊作為終結器使用的函式。

import pytest

@pytest.fixture()
def login(request):
    print("登入")
    def demo_finalizer():
        print("退出登入")
    # 註冊demo_finalizer為終結函式
    request.addfinalizer(demo_finalizer)

class Test_Demo():
    def test_case1(self):
        print("\n開始執行測試用例1")
        assert 1 + 1 == 2

    def test_case2(self, login):
        print("\n開始執行測試用例2")
        assert 2 + 8 == 10

    def test_case3(self):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100


if __name__ == '__main__':
    pytest.main()

結果:

PASSED               [ 33%]
開始執行測試用例1
登入
PASSED               [ 66%]
開始執行測試用例2
退出登入
PASSED               [100%]
開始執行測試用例3

fixture 作用範圍:Scope

fixture 作用範圍可以為module、class、session和function,預設作用域為function。

  • function:每一個函式或方法都會呼叫
  • class:每一個類呼叫一次
  • module:每一個.py檔案呼叫一次
  • session:是多個檔案呼叫一次

scope="function"

import pytest

@pytest.fixture(scope="function")
def login():
    print("登入...")

class Test_Demo():
    def test_case1(self, login):
        print("\n開始執行測試用例1")
        assert 1 + 1 == 2

    def test_case2(self, login):
        print("\n開始執行測試用例2")
        assert 2 + 8 == 10

    def test_case3(self, login):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100

if __name__ == '__main__':
    pytest.main()

結果:

登入...
PASSED                      [ 33%]
開始執行測試用例1
登入...
PASSED                      [ 66%]
開始執行測試用例2
登入...
PASSED                      [100%]
開始執行測試用例3

scope="class"

一個class裡面多個用例都呼叫了此fixture,那麼只在class裡所有用例開始前執行一次

import pytest

@pytest.fixture(scope="class")
def login():
    print("登入...")

結果:

登入...
PASSED                      [ 33%]
開始執行測試用例1
PASSED                      [ 66%]
開始執行測試用例2
PASSED                      [100%]
開始執行測試用例3

fixture自動應用

autouse引數

autouse設定為True時,自動呼叫fixture功能。由於預設作用域為function,不指定scope則每個方法都會呼叫fixture方法。

import pytest

@pytest.fixture(autouse=True)
def login():
    print("登入...")

class Test_Demo():
    def test_case1(self):
        print("\n開始執行測試用例1")
        assert 1 + 1 == 2

    def test_case2(self):
        print("\n開始執行測試用例2")
        assert 2 + 8 == 10

    def test_case3(self):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100


if __name__ == '__main__':
    pytest.main()

結果:

登入...
PASSED                    [ 33%]
開始執行測試用例1
登入...
PASSED                    [ 66%]
開始執行測試用例2
登入...
PASSED                    [100%]
開始執行測試用例3

@pytest.mark.usefixtures()

在測試方法上加@pytest.mark.usefixtures()

import pytest

@pytest.fixture()
def login():
    print("登入...")

@pytest.mark.usefixtures("login")
class Test_Demo():
    def test_case1(self):
        print("\n開始執行測試用例1")
        assert 1 + 1 == 2

    def test_case2(self):
        print("\n開始執行測試用例2")
        assert 2 + 8 == 10

    def test_case3(self):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100


if __name__ == '__main__':
    pytest.main()

結果:

登入...
PASSED                [ 33%]
開始執行測試用例1
登入...
PASSED                [ 66%]
開始執行測試用例2
登入...
PASSED                [100%]
開始執行測試用例3

fixture函式引數化

如果多條用例都需要呼叫相同引數,可以將fixture函式引數化。fixture 函式將執行每個引數值,fixture通過固定引數request傳遞。

import pytest

@pytest.fixture(scope="module", params=[
    [1, 1, 2],
    [2, 8, 10],
    [99, 1, 100]
])
def data(request):
    yield request.param

class Test_Demo():
    def test_case1(self):
        print("\n開始執行測試用例1")
        assert 2 + 8 == 10

    def test_case2(self, data):
        print("\n開始執行測試用例2")
        assert data[0] + data[1] == data[2]

    def test_case3(self):
        print("\n開始執行測試用例3")
        assert 99 + 1 == 100


if __name__ == '__main__':
    pytest.main()

結果:

PASSED                     [ 20%]
開始執行測試用例1
PASSED              [ 40%]
開始執行測試用例2
PASSED              [ 60%]
開始執行測試用例2
PASSED              [ 80%]
開始執行測試用例2
PASSED                     [100%]
開始執行測試用例3
--THE END--

文章標題:Pytest測試框架(三):pytest fixture 用法
本文作者:hiyo
本文連結:https://www.cnblogs.com/hiyong/p/14163280.html
歡迎關注公眾號:「測試開發小記」及時接收最新技術文章!

相關文章