1. 程式人生 > 其它 >pytest之fixture使用

pytest之fixture使用

前言 

setup和teardown能實現在測試用例執行之前或之後做一些操作,但是這種是整個測試指令碼全域性生效的;

如果我們想實現在某些用例執行之前進行登入,某些用例執行之前不需要進行登入,這種場景我們再使用setup和teardown就無法實現了,這時候我們就需要用到fixture功能。

fixture方法

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

引數:

scope:被fixture標記的方法的作用域,可選值:function(預設)、class、module、session

  • function:作用於每個方法或函式,每個方法或函式都執行一次
  • class:作用於整個class類,每個class中的所有test只執行一次
  • module:作用於整個模組,每個module中的所有test只執行一次
  • session:作用於整個session,整個session只執行一次(慎用)

params:list型別,一個可選的引數列表,它將會多次呼叫被fixture標記的方法和所有用到這個fixture的test測試用例,當前呼叫引數可以用 request.param 來獲取。

autouse:如果為True,則為所有test測試用例啟用fixture,執行測試用例的時候會自動執行被fixture標記的方法;如果為False,則需要顯示指定來啟用fixture,不會自動執行。

ids:id字串列表,與params相對應,因此它們也是測試的一部分。如果沒有提供ids,那麼將會從params來自動生成。

name:fixture的名稱。預設為被fixture裝飾器標記的函式名。

fixture的使用

通過引數引用fixture

舉例:

# file_name:test_fixture.py


import pytest


class Test_A:

    @pytest.fixture()
    def before(self):
        print("\n--------before fixture has ran--------")

    
def test_a(self, before): # test_a方法以引數的形式傳入了被fixture標記的函式,fixture的名稱預設為被fixture標記的函式名 print('-------test_a has ran-------') assert 1 if __name__ == '__main__': pytest.main(['-s', 'test_fixture.py'])

執行結果:

從結果中可以看到被fixture標記的函式before會優先於測試用例test_a執行。

通過使用name引數來引用fixture

# file_name:test_fixture.py


import pytest


class Test_A:

    @pytest.fixture(name="before_fixture_name")
    def before(self):
        print("\n--------before fixture has ran--------")

    def test_a(self, before_fixture_name):    # test_a方法以引數的形式傳入了被fixture標記的函式,這裡的fixture名稱為:before_fixture_name,如果不設定name引數,則fixture的名稱預設為被fixture標記的函式名
        print('-------test_a has ran-------')
        assert 1


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

通過函式的形式引用fixture

舉例:

# file_name: test_fixture.py


import pytest


@pytest.fixture()  # 被fixture標記的函式也可以應用在測試類的外部
def before():
    print("\n--------before fixture has ran--------")


@pytest.mark.usefixtures("before")  # 通過使用usefixtures()來引用fixture
class Test_A:

    def test_a(self):
        print('-------test_a has ran-------')
        assert 1


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

執行結果:

從結果中可以看到被fixture標記的函式before會優先於測試用例test_a執行。

通過autouse=True設定預設執行fixture

舉例:

# file_name: test_fixture.py


import pytest


@pytest.fixture(autouse=True)  # 通過引數autouse=True來設定fixture預設執行
def before():
    print("\n--------before fixture has ran--------")


class Test_A:

    def test_a(self):
        print('-------test_a has ran-------')
        assert 1

    def test_b(self):
        print('-------test_b has ran-------')
        assert 1


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

執行結果:

從結果中可以看到我們並沒有顯示指定test_a和test_b使用fixture,但是在執行測試用例之前卻執行了fixture,這就是因為我們將fixture設定成了autouse=True。

fixture作用域設定成function

舉例:

# file_name: test_fixture.py


import pytest


@pytest.fixture(scope="function", autouse=True)  # 作用域設定成function,通過引數autouse=True來設定fixture預設執行
def before():
    print("\n--------before fixture has ran--------")


class Test_A:

    def test_a(self):
        print('-------test_a has ran-------')
        assert 1

    def test_b(self):
        print('-------test_b has ran-------')
        assert 1


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

執行結果:

從結果中可以看到將fixture的作用域設定成scope=function後,每個test測試用例執行前都會執行一次被fixture標記的函式。並且通過跟上一個例子對比我們可以看到設定scope=function和不設定scope引數的執行結果是一致的,這說明scope引數的預設值是function

fixture作用域設定成class

舉例:

# file_name: test_fixture.py


import pytest


@pytest.fixture(scope="class", autouse=True)  # 作用域設定成class,通過引數autouse=True來設定fixture預設執行
def before():
    print("\n--------before fixture has ran--------")


class Test_A:

    def test_a(self):
        print('-------test_a has ran-------')
        assert 1

    def test_b(self):
        print('-------test_b has ran-------')
        assert 1


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

執行結果:

從執行結果中可以看到測試類中有兩個測試用例,但是fixture卻只執行了一次。

fixture的返回值使用

舉例:

# file_name: test_fixture.py


import pytest


@pytest.fixture()
def return_data():
    print("\n--------before fixture has ran--------")
    return 2    # 返回值


class Test_A:

    def test_a(self, return_data):
        print('-------test_a has ran-------')
        assert 1 == return_data # 拿到返回值做斷言


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

執行結果:

從結果中看到我們拿到了fixture的返回值為2,在測試用例中拿到返回值做斷言,斷言失敗。

fixture的params引數使用

舉例:

# file_name: test_fixture.py


import pytest


@pytest.fixture(params=[1, 2, 3])
def return_data(request):   # 傳入引數request,request系統內建的fixture
    print("\n--------before fixture has ran--------")
    return request.param  # 通過request.param 獲取當前傳入的引數


class Test_A:

    def test_a(self, return_data):
        print('-------test_a has ran,return_data的值為:{}-------'.format(return_data))
        assert 1 == return_data  # 拿到返回值做斷言


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

執行結果:

從結果中我們可以看到測試用例執行了3次。通過設定params引數會導致多次呼叫被fixture標記的函式,並且使用該fixture函式的測試用例也會執行多次。

去期待陌生,去擁抱驚喜。