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

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
本文鏈接://www.cnblogs.com/hiyong/p/14163280.html
歡迎關注公眾號:「測試開發小記」及時接收最新技術文章!