pytest是一個功能非常全面的Python自動化測試框架
特點:
1、簡單靈活,支持參數化,可以細粒度的控制測試用例;
2、不僅支持簡單的單元測試,還支持復雜的功能測試,不僅可以用來做selenium/appium的UI自動化測試,還可以用作做基於Python+requests的接口自動化測試;
3、第三方插件非常豐富,如pytest-selenium(集成了selenium)、pytest-html(完美的html測試報告)、pytest-reunfailures(失敗case重復測試)等;
4、測試用例跳躍式(skip)執行以及標記后選擇性處理(mark);
5、很好的與CI工具(jenkins)結合;
編寫規則:
1、測試文件以test_開頭,以_test結尾也可以;
2、測試類以Test開頭,並且不能帶有__init__方法;
3、測試函數(方法)以test_開頭;
4、斷言使用assert;
一、安裝pytest
$ pip install pytest
二、執行一個測試
測試通過
# test_demo8.py def test_pass(): assert 1 == 1
通過pytest來運行上面測試函數
在pycharm的Terminal中直接輸入命令pytest test_demo8.py執行
MacBook-Pro:test_demo fyuanyuan$ pytest test_demo8.py
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 1 item
test_demo8.py . [100%]
========================================================================================== 1 passed in 0.01s ===========================================================================================
執行結果為test_demo8.py測試通過(pytest使用 . 標識測試通過PASSED)
下面使用-v選項來展示測試的詳細信息
MacBook-Pro:test_demo fujinjie$ pytest -v test_demo8.py ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 1 item test_demo8.py::test_passing PASSED [100%] ========================================================================================== 1 passed in 0.01s ===========================================================================================
測試失敗
# test_demo8.py def test_fail(): assert 1 ==2
同樣在命令行執行pytest test_demo8.py命令
MacBook-Pro:test_demo fujinjie$ pytest test_demo8.py ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 1 item test_demo8.py F [100%] =============================================================================================== FAILURES =============================================================================================== _____________________________________________________________________________________________ test_failing _____________________________________________________________________________________________ def test_fail(): > assert 1 == 2 E assert 1 == 2 test_demo8.py:8: AssertionError ========================================================================================== 1 failed in 0.05s ===========================================================================================
測試結果為失敗,pytest使用 F 來標識測試失敗FAILED
pytest中使用assert來進行斷言。
三、標記函數
pytest默認查找當前目錄下所有以test開始或者結尾的Python文件,並執行其中所有以test開始或結束的函數(方法)
run.py
#--coding:utf-8 --
#run.py
import pytest if __name__ == '__main__': pytest.main(['-v'])
test_demo9.py
#--coding:utf-8 -- #test_demo9.py def test_demo9_func1(): assert 1 == 1 def test_demo9_func2(): assert 2 == 2
test_demo10.py
#--coding:utf-8 -- #test_demo10.py def test_demo10_func3(): assert 3 == 3 def test_demo10_func4(): assert 4 == 4
因為run.py/test_demo9.py/test_demo10.py在同一個demo目錄下,所以執行run.py時pytest會查找該目錄下所有以test開頭或結尾的Python文件,並執行文件中所有以test開頭或結尾的函數和方法
============================= test session starts ============================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo/templates/demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collecting ... collected 4 items test_demo10.py::test_demo10_func3 PASSED [ 25%] test_demo10.py::test_demo10_func4 PASSED [ 50%] test_demo9.py::test_demo9_func1 PASSED [ 75%] test_demo9.py::test_demo9_func2 PASSED [100%] ============================== 4 passed in 0.02s ===============================
由於某些原因,我只想執行test_demo9_func2()測試用例看是否通過,通過pytest有以下幾種方法:
方法一,執行時指定函數名,通過 :: 標記
#--coding:utf-8 -- #run.py import pytest if __name__ == '__main__': pytest.main(['test_demo9.py::test_demo9_func2','-v'])
或者在命令行中輸入
$pytest -v demo/test_demo9.py::test_demo9_func2
運行結果
MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo9.py::test_demo9_func2 ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 1 item demo/test_demo9.py::test_demo9_func2 PASSED [100%] ========================================================================================== 1 passed in 0.01s ===================================================
方法二,使用 -k 選項標識來模糊匹配
匹配執行demo目錄下名稱中含有func2的測試用例
$ pytest -v -k func2 demo/
執行結果
MacBook-Pro:test_demo fujinjie$ pytest -v -k func2 demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 4 items / 3 deselected / 1 selected demo/test_demo9.py::test_demo9_func2 PASSED [100%] =================================================================================== 1 passed, 3 deselected in 0.01s =========================================
以上兩種方法,第一種只能指定一個測試用例,無法批量執行;第二種需要所有測試名稱包含相同的部分名稱是才能批量執行。
方法三,直接使用 pytest.mark 在函數(測試用例)上進行標記
#--coding:utf-8 -- #test_demo9.py import pytest @pytest.mark.run def test_demo9_func1(): assert 1 == 1 @pytest.mark.unrun def test_demo9_func2(): assert 2 == 2
#--coding:utf-8 -- #test_demo10.py import pytest @pytest.mark.unrun def test_demo10_func3(): assert 3 == 3 @pytest.mark.unrun def test_demo10_func4(): assert 4 == 4
在命令行輸入 pytest -v -m run demo/ 命令執行
MacBook-Pro:test_demo fujinjie$ pytest -v -m run demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 4 items / 3 deselected / 1 selected demo/test_demo9.py::test_demo9_func1 PASSED [100%] =========================================================================================== warnings summary ==========================
上述4個測試函數,只有被標記為run的 test_demo9_func1( ) 被執行
注:一個函數可以被添加多個標記,多個函數可以添加相同的標記來實現批量執行
運行時 -m 后面可加邏輯
#--coding:utf-8 -- #test_demo9.py import pytest @pytest.mark.run def test_demo9_func1(): assert 1 == 1 @pytest.mark.commit @pytest.mark.unrun def test_demo9_func2(): assert 2 == 2
執行 pytest -v -m "unrun and commit" demo/
MacBook-Pro:test_demo fujinjie$ pytest -v -m "unrun and commit" demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 4 items / 3 deselected / 1 selected demo/test_demo9.py::test_demo9_func2 PASSED [100%]
被標記為 unrun 和 commit 的測試函數才執行
四、跳過測試
在測試工作中面對大批量的測試用例,想對其中某一條跳過不執行,Pytest中使用 pytest.mark.skip 可直接跳過該測試用例
#--coding:utf-8 -- #test_demo10.py import pytest @pytest.mark.skip def test_demo10_func3(): assert 3 == 3 def test_demo10_func4(): assert 4 == 4
在命令行執行 pytest -v demo/test_demo10.py
MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo10.py ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 2 items demo/test_demo10.py::test_demo10_func3 SKIPPED [ 50%] demo/test_demo10.py::test_demo10_func4 PASSED [100%] ===================================================================================== 1 passed, 1 skipped in 0.01s =============================================
執行結果中只有 test_demo10_func4 被執行,test_demo10_func3 直接跳過沒執行
五、參數化
當對一個函數進行測試時,通常會給這個函數傳遞多組參數,模擬各種不同情況,在pytest中就是參數化測試,即每組參數都獨立執行一次測試,使用 pytest.mark.parametrize(argnames, argvalues)
#--coding:utf-8 -- #test_demo11.py import pytest @pytest.mark.parametrize('password',['12345','123456a','abcdefgh']) def test_demo_func5(password): assert len(password) >= 6
在命令行執行 pytest -v demo/test_demo11.py
MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo11.py ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 3 items demo/test_demo11.py::test_demo_func5[12345] FAILED [ 33%] demo/test_demo11.py::test_demo_func5[123456a] PASSED [ 66%] demo/test_demo11.py::test_demo_func5[abcdefgh] PASSED [100%] =============================================================================================== FAILURES =============================================================================================== ________________________________________________________________________________________ test_demo_func5[12345] ________________________________________________________________________________________ password = '12345' @pytest.mark.parametrize('password',['12345','123456a','abcdefgh']) def test_demo_func5(password): > assert len(password) >= 6 E AssertionError: assert 5 >= 6 E + where 5 = len('12345') demo/test_demo11.py:8: AssertionError
通過上述結果可以看出該測試函數被執行了3次,每次都以不同的password參數傳入,FAILLED一次,PASSED兩次。
傳入多個參數
#--coding:utf-8 -- #test_demo11.py import pytest @pytest.mark.parametrize('user,password',[('Jack','123456'),('Pluo','123456a'),('Flak','abcdefg')]) def test_demo11_func6(user,password): db = {'Jack':'123456', 'Pluo':'123456a', 'Flak':'abcdefg'} assert db[user] == password
在命令行執行 pytest -v demo/test_demo11.py::test_demo11_func6
MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo11.py::test_demo11_func6 ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 3 items demo/test_demo11.py::test_demo11_func6[Jack-123456] PASSED [ 33%] demo/test_demo11.py::test_demo11_func6[Pluo-123456a] PASSED [ 66%] demo/test_demo11.py::test_demo11_func6[Flak-abcdefg] PASSED [100%] ========================================================================================== 3 passed in 0.02s ===========================================================================================
六、固件Fixture
Fixture是一些函數,pytest會在執行測試函數(用例)之前或之后加載執行它們,比如執行測試函數前數據庫的連接和執行完畢后數據庫的關閉操作。
Pytest通過 @pytest.fixture() 來定義固件,在pytest中使用conftest.py集中管理固件,更大程度上復用(conftest.py的作用域為其所在的目錄和子目錄)
conftest.py在demo目錄下,因此它的作用域為demo目錄下的所有文件以及子文件
conftest.py
#--coding:utf-8 -- #conftest.py import pytest @pytest.fixture() def fixture_func1(): return '3721'
test_demo11.py
#--coding:utf-8 -- #test_demo11.py import pytest def test_demo11_func7(fixture_func1): num = '3721' assert num == fixture_func1
在 test_demo11.py 中測試函數 test_demo11_func7 直接調用 conftest.py 中的 fixture_func1 固件完成測試
注意:不要顯示調用 conftest.py (pytest會根據conftest.py的作用域自動調用),可以把 conftest.py 當作插件來理解。
在命令行執行 pytest -v -k func7 demo/test_demo11.py
MacBook-Pro:test_demo fujinjie$ pytest -v -k func7 demo/test_demo11.py ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7 cachedir: .pytest_cache metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}} rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 7 items / 6 deselected / 1 selected demo/test_demo11.py::test_demo11_func7 PASSED [100%] =================================================================================== 1 passed, 6 deselected in 0.02s ====================================================================================
七、預處理和后處理
在測試過程中,我們需要在測試開始之前做准備工作,以及在測試結束后做收尾工作,在pytest中通過固件來自動化所有預處理和后處理,使用 yield 關鍵字將固件分為兩部分,yield 之前的代碼屬於預處理,在測試之前執行,yield 之后的代碼屬於后處理,將在測試完成后執行。
在 conftest.py 中加入 fixture_func2 固件
#--coding:utf-8 -- #conftest.py import pytest @pytest.fixture() def fixture_func1(): return '3721' @pytest.fixture() def fixture_func2(): print('測試開始之前') yield print('測試結束之后')
在 test_demo11.py 的測試函數 test_demo11_func7 中調用固件 fixture_func1 和 fixture_func2
def test_demo11_func7(fixture_func1,fixture_func2): num = '3721' assert num == fixture_func1
在命令行中執行 pytest --setup-show -s -k func7 demo/
MacBook-Pro:test_demo fujinjie$ pytest --setup-show -s -k func7 demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 11 items / 10 deselected / 1 selected demo/test_demo11.py SETUP F fixture_func1測試開始之前 SETUP F fixture_func2 demo/test_demo11.py::test_demo11_func7 (fixtures used: fixture_func1, fixture_func2).測試結束之后 TEARDOWN F fixture_func2 TEARDOWN F fixture_func1 =================================================================================== 1 passed, 10 deselected in 0.02s ===================================================================================
八、作用域
pytest使用作用域來進行指定固件的使用范圍
定義固件時通過 scope 參數聲明作用域,可選項有:
1、function: 函數級,每個測試函數都會執行一次固件;
2、class:類級別,每個測試類執行一次,所有方法都可以使用;
3、module:模塊級,每個模塊執行一次,模塊內函數和方法都可以使用;
4、session:會話級,一次測試只執行一次,所有被找到的函數和方法都可用。
注:固件默認的作用域為 function
conftest.py
@pytest.fixture(scope='function') def fixture_function(): pass @pytest.fixture(scope='module') def fixture_module(): pass @pytest.fixture(scope='session') def fixture_session(): pass @pytest.fixture(scope='class') def fixture_class(): pass
test_demo11.py
def test_demo11_func8(fixture_function,fixture_session,fixture_module):
pass
在命令行執行 pytest --setup-show -k func8 demo/ 可以看到各固件的作用域與執行順序
MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k func8 demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 12 items / 11 deselected / 1 selected demo/test_demo11.py SETUP S fixture_session SETUP M fixture_module SETUP F fixture_function demo/test_demo11.py::test_demo11_func8 (fixtures used: fixture_function, fixture_module, fixture_session). TEARDOWN F fixture_function TEARDOWN M fixture_module TEARDOWN S fixture_session =================================================================================== 1 passed, 11 deselected in 0.02s ============================================================
對於類使用作用域,需要使用 @pytest.mark.usefixtures
test_demo11.py
@pytest.mark.usefixtures('fixture_class') class TestDemo11Class1: def test_demo11_func9(self): pass def test_demo11_func10(self): pass
在命令行執行 pytest --setup-show -k TestDemo11Class1 demo/ 結果如下
MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k TestDemo11Class1 demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 14 items / 12 deselected / 2 selected demo/test_demo11.py SETUP C fixture_class demo/test_demo11.py::TestDemo11Class1::test_demo11_func9 (fixtures used: fixture_class). demo/test_demo11.py::TestDemo11Class1::test_demo11_func10 (fixtures used: fixture_class). TEARDOWN C fixture_class =================================================================================== 2 passed, 12 deselected in 0.04s ===================================================================================
上述結果可見,該類下的所有測試函數都在這個類級別固件作用范圍內
九、自動執行
上述固件,都是通過我們手動指定后才執行的,在pytest中可以在定義固件時指定 autouse 參數讓固件自動執行
conftest.py
@pytest.fixture(scope='function',autouse=True) def fixture_function(): pass @pytest.fixture(scope='module',autouse=True) def fixture_module(): pass @pytest.fixture(scope='session',autouse=True) def fixture_session(): pass
test_demo11.py
def test_demo11_func11():
pass
命令行執行 pytest --setup-show -k func11 demo/
MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k func11 demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 15 items / 14 deselected / 1 selected demo/test_demo11.py SETUP S fixture_session SETUP M fixture_module SETUP F fixture_function demo/test_demo11.py::test_demo11_func11 (fixtures used: fixture_function, fixture_module, fixture_session). TEARDOWN F fixture_function TEARDOWN M fixture_module TEARDOWN S fixture_session =================================================================================== 1 passed, 14 deselected in 0.02s ===================================================================================
結果可見,所有參數 autouse = True 的 fixture 都自動執行了
十、對固件重命名
fixture默認的名稱為定義是的函數名稱,可以通過 name 選項指定名稱
conftest.py
@pytest.fixture(name='year') def fixture_year(): return 2020
test_demo11.py
def test_demo11_func12(year): now_year = 2020 assert now_year == year
執行結果可見,固件名稱被命名為 year,可供測試函數直接調用
MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k func12 demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 16 items / 15 deselected / 1 selected demo/test_demo11.py SETUP F year demo/test_demo11.py::test_demo11_func12 (fixtures used: year). TEARDOWN F year =================================================================================== 1 passed, 15 deselected in 0.02s ===================================================================================
十一、固件參數化
通過固件調用不同的參數,使測試函數應用與不同的測試場景,提高測試函數的復用性
固件參數化需要使用 pytest 內置的固件 request,並通過 request.param 獲取參數
# conftest.py @pytest.fixture(params=[('參數k1','參數v1'),('參數k2','參數v2'),('參數k3','參數v3')]) def param(request): return request.param @pytest.fixture(autouse=True) def fixture_param(param): print('正在傳入參數%s:%s'% param) yield print('參數%s:%s處理完畢'% param)
在test_demo11.py中加入test_demo11_func13 測試函數
def test_demo11_func13():
pass
執行結果
MacBook-Pro:test_demo fujinjie$ pytest --setup-show -s -k func13 demo/ ========================================================================================= test session starts ========================================================================================== platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /Users/fujinjie/PycharmProjects/test_demo plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0 collected 51 items / 48 deselected / 3 selected demo/test_demo11.py SETUP F param[('參數k1', '參數v1')]正在傳入參數參數k1:參數v1 SETUP F fixture_param (fixtures used: param) demo/test_demo11.py::test_demo11_func13[param0] (fixtures used: fixture_param, param, request).參數參數k1:參數v1處理完畢 TEARDOWN F fixture_param TEARDOWN F param[('參數k1', '參數v1')] SETUP F param[('參數k2', '參數v2')]正在傳入參數參數k2:參數v2 SETUP F fixture_param (fixtures used: param) demo/test_demo11.py::test_demo11_func13[param1] (fixtures used: fixture_param, param, request).參數參數k2:參數v2處理完畢 TEARDOWN F fixture_param TEARDOWN F param[('參數k2', '參數v2')] SETUP F param[('參數k3', '參數v3')]正在傳入參數參數k3:參數v3 SETUP F fixture_param (fixtures used: param) demo/test_demo11.py::test_demo11_func13[param2] (fixtures used: fixture_param, param, request).參數參數k3:參數v3處理完畢 TEARDOWN F fixture_param TEARDOWN F param[('參數k3', '參數v3')] =================================================================================== 3 passed, 48 deselected in 0.04s ============================================
注意:與函數參數化 @pyest.mark.parametrize 不同,固件是在定義時使用 params 進行參數化,固件參數化依賴內置的 request 以及屬性 param