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函式的測試用例也會執行多次。
去期待陌生,去擁抱驚喜。