【pytest單元測試框架】(2)pytest 的基本使用方法
阿新 • • 發佈:2021-11-18
pytest 的基本使用方法
1、斷言
在 unittest 單元測試框架中提供了豐富的斷言方法,如 assertEqual()、assertIn()、assertTrue()、assertIs()等。pytest 單元測試框架並沒有提供專門的斷言方法,而是直接使用Python 的 assert 進行斷言。 建立 test_assert.py 檔案# -*- coding:utf-8 -*- # filename: test_assert.py # author: hello.yin # date: 2021/11/18 import pytest # 建立用於測試的功能函式 #加法測試 def add(a, b): return a + b # 判斷素數 def is_prime(n): if n < 2: return False else: for i in range(2, n): if n % i == 0: return False else: return True # 判斷相等 def test_add1(): assert add(3, 5) == 8 # 判斷大於def test_add2(): assert add(5, 5) > 10 # 判斷為True def test_isprime1(): assert is_prime(1) is False # 判斷為False def test_isprime2(): assert is_prime(7) is True # 判斷包含 def test_in(): a = "he" b = "hello" assert a in b # 判斷不包含 def test_not_in(): a = "yin" b = "hello" assert a not in b if __name__ == "__main__": pytest.main()
執行結果:
(base_practice) D:\00test\base_practice\pyTest>pytest test_assert.py =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 6 items test_assert.py .F.... [100%] ==================================================================== FAILURES ===================================================================== ____________________________________________________________________ test_add2 ____________________________________________________________________ def test_add2(): > assert add(5, 5) > 10 E assert 10 > 10 E + where 10 = add(5, 5) test_assert.py:34: AssertionError ============================================================= short test summary info ============================================================= FAILED test_assert.py::test_add2 - assert 10 > 10 =========================================================== 1 failed, 5 passed in 0.06s ===========================================================上面的例子展示了 pytest 斷言的用法,藉助 Python 的運算子號和關鍵字即可輕鬆實現不同資料型別的斷言。
2、Fixture
Fixture 通常用來對測試方法、測試函式、測試類和整個測試檔案進行初始化或還原測試環境。建立 test_fixtures_01.py 檔案。# -*- coding:utf -8 -*- # filename: /pyTest/test_fixtrue.py # author: hello.yin # date: 2021/11/18 # 功能函式 def mul(a, b): return a*b # 模組級別 def setup_module(module): print("===========setup_module=========") def teardown_module(module): print("============teardown_module========") # 函式級別 def setup_function(function): print("==========setup_founction=========") def teardown_function(function): print("==========setup_founction==========") # 用例級別 def setup(): print("==========setup=========") def teardown(): print("=========teardowm==========") # 測試用例 def test_35(): assert mul(3, 5) == 14 def test_45(): assert mul(4, 5) == 20這裡主要用到模組級別和函式級別的 Fixture。
- setup_module/teardown_module:在當前檔案中,在所有測試用例執行之前與之後執行。
- setup_function/teardown_function:在每個測試函式之前與之後執行。
- setup/teardown:在每個測試函式之前與之後執行。這兩個方法同樣可以作用於類方法。
執行結果:
(base_practice) D:\00test\base_practice\pyTest>pytest test_fixtrue01.py =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 2 items test_fixtrue01.py F. [100%] ==================================================================== FAILURES ===================================================================== _____________________________________________________________________ test_35 _____________________________________________________________________ def test_35(): > assert mul(3, 5) == 14 E assert 15 == 14 E + where 15 = mul(3, 5) test_fixtrue01.py:41: AssertionError -------------------------------------------------------------- Captured stdout setup -------------------------------------------------------------- ===========setup_module========= ==========setup_founction========= ==========setup========= ------------------------------------------------------------ Captured stdout teardown ------------------------------------------------------------- =========teardowm========== ==========setup_founction========== ============================================================= short test summary info ============================================================= FAILED test_fixtrue01.py::test_35 - assert 15 == 14 =========================================================== 1 failed, 1 passed in 0.05s ===========================================================
pytest 是支援使用測試類的,同樣必須以“Test”開頭,注意首字母大寫。在引入測試類的情況下,Fixture 的用法如下。建立 test_fixtures_02.py 檔案。
# -*- coding:utf-8 -*- # filename: test_fixtrue02.py # author: hello.yin # date: 2021/11/18 # 功能函式 def mul(a, b): return a*b # 判斷函式類 class TestMul: @classmethod def setup_class(cls): print("===============setup_class===============") @classmethod def teardown_class(cls): print("===============teardown_class==============") @staticmethod def setup_method(self): print("==============setup_method=================") @staticmethod def teardown_method(self): print("==============teardown_method==============") @staticmethod def setup(): print("==========setup=============") @staticmethod def teardown(): print("===========teardown============") # 測試用例 def test_mul35(self): assert mul(3, 5) == 16 def test_mul45(self): assert mul(4, 5) == 20這裡主要用到類級別和方法級別的 Fixture。
- setup_class/teardown_class :在當前測試類的開始與結束時執行。
- setup_method/teardown_method :在每個測試方法開始與結束時執行。
- setup/teardown :在每個測試方法開始與結束時執行,同樣可以作用於測試函式。
(base_practice) D:\00test\base_practice\pyTest>pytest test_fixtrue02.py =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 2 items test_fixtrue02.py F. [100%] ==================================================================== FAILURES ===================================================================== _______________________________________________________________ TestMul.test_mul35 ________________________________________________________________ self = <pyTest.test_fixtrue02.TestMul object at 0x0000026A7E40D108> def test_mul35(self): > assert mul(3, 5) == 16 E assert 15 == 16 E + where 15 = mul(3, 5) test_fixtrue02.py:41: AssertionError -------------------------------------------------------------- Captured stdout setup -------------------------------------------------------------- ===============setup_class=============== ==============setup_method================= ==========setup============= ------------------------------------------------------------ Captured stdout teardown ------------------------------------------------------------- ===========teardown============ ==============teardown_method============== ============================================================= short test summary info ============================================================= FAILED test_fixtrue02.py::TestMul::test_mul35 - assert 15 == 16 =========================================================== 1 failed, 1 passed in 0.05s ===========================================================
3、 引數化
當一組測試用例有固定的測試資料時,就可以通過引數化的方式簡化測試用例的編寫。pytest 本身是支援引數化的,不需要額外安裝外掛。建立 test_parameterize.py 檔案。# -*- coding:utf-8 -*- # filename: test_parameterized.py # author: hello.yin # date: 20221/11/18 import pytest import math @pytest.mark.parametrize( "base, exponent, expected", ((2, 2, 4), (3, 3, 9), (2, 3, 8), (0, 9, 0)), ids=["case1", "case2", "case3", "case4"]) def test_row(base, exponent, expected): assert math.pow(base, exponent) == expected
用法與 unittest 的引數化外掛類似,通過 pytest.mark.parametrize()方法設定引數。“base,exponent,expected”用來定義引數的名稱。通過陣列定義引數時,每一個元組都是一條測試用例使用的測試資料。ids 引數預設為 None,用於定義測試用例的名稱。math 模組的 pow()方法用於計算 xy(x 的 y 次方)的值。
執行結果如下:(base_practice) D:\00test\base_practice\pyTest>pytest -v test_parameterized.py =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- C:\Users\yzp\PycharmProjects\base_practice\Scripts\python.exe cachedir: .pytest_cache rootdir: D:\00test\base_practice\pyTest collected 4 items test_parameterized.py::test_row[case1] PASSED [ 25%] test_parameterized.py::test_row[case2] FAILED [ 50%] test_parameterized.py::test_row[case3] PASSED [ 75%] test_parameterized.py::test_row[case4] PASSED [100%] ==================================================================== FAILURES ===================================================================== _________________________________________________________________ test_row[case2] _________________________________________________________________ base = 3, exponent = 3, expected = 9 @pytest.mark.parametrize( "base, exponent, expected", ((2, 2, 4), (3, 3, 9), (2, 3, 8), (0, 9, 0)), ids=["case1", "case2", "case3", "case4"]) def test_row(base, exponent, expected): > assert math.pow(base, exponent) == expected E assert 27.0 == 9 E +27.0 E -9 test_parameterized.py:18: AssertionError ============================================================= short test summary info ============================================================= FAILED test_parameterized.py::test_row[case2] - assert 27.0 == 9 =========================================================== 1 failed, 3 passed in 0.04s ===========================================================
4、 執行測試
pytest 提供了豐富的引數執行測試用例,在前面的例子中已經使用到一些引數,例如,“-s”引數用於關閉捕捉,從而輸出列印資訊;“-v”引數用於增加測試用例冗長。 通過“pytest --help”可以檢視幫助:pytest––helppytest 提供的引數比較多,下面只介紹常用的引數:
4.1.執行名稱中包含某字串的測試用例
在前面內容test_assert.py 檔案,其中有 42條是關於 add()功能的,並且在測試用例的名稱上包含了“add”字串,因此這裡可以通過“-k”來指定在名稱中包含“add”的測試用例。(base_practice) D:\00test\base_practice\pyTest>pytest -k add test_assert.py =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 6 items / 4 deselected / 2 selected test_assert.py .F [100%] ==================================================================== FAILURES ===================================================================== ____________________________________________________________________ test_add2 ____________________________________________________________________ def test_add2(): > assert add(5, 5) > 10 E assert 10 > 10 E + where 10 = add(5, 5) test_assert.py:34: AssertionError ============================================================= short test summary info ============================================================= FAILED test_assert.py::test_add2 - assert 10 > 10 ==================================================== 1 failed, 1 passed, 4 deselected in 0.04s ====================================================
4.2.減少測試的執行冗長
這一次執行日誌少了很多資訊,“-q”用來減少測試執行的冗長;也可以使用“--quiet”代替(base_practice) D:\00test\base_practice\pyTest>pytest -q test_assert.py .F.... [100%] ==================================================================== FAILURES ===================================================================== ____________________________________________________________________ test_add2 ____________________________________________________________________ def test_add2(): > assert add(5, 5) > 10 E assert 10 > 10 E + where 10 = add(5, 5) test_assert.py:34: AssertionError ============================================================= short test summary info ============================================================= FAILED test_assert.py::test_add2 - assert 10 > 10 1 failed, 5 passed in 0.03s
4.3. 如果出現一條測試用例失敗,則退出測試
這在測試用例的除錯階段是有用的,當出現一條失敗的測試用例時,應該先通過除錯讓這條測試用例執行通過,而不是繼續執行後面的測試用例。(base_practice) D:\00test\base_practice\pyTest>pytest -x test_assert.py =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 6 items test_assert.py .F ==================================================================== FAILURES ===================================================================== ____________________________________________________________________ test_add2 ____________________________________________________________________ def test_add2(): > assert add(5, 5) > 10 E assert 10 > 10 E + where 10 = add(5, 5) test_assert.py:34: AssertionError ============================================================= short test summary info ============================================================= FAILED test_assert.py::test_add2 - assert 10 > 10 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! =========================================================== 1 failed, 1 passed in 0.04s ===========================================================
4.4.執行測試目錄
測試目錄既可以指定相對路徑(如 ./test_dir ) , 也 可以指定絕對路徑(如D:\00test\base_practice\pyTest)(base_practice) D:\00test\base_practice\pyTest>pytest D:\00test\base_practice\pyTest =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 15 items test_assert.py .F.... [ 40%] test_fixtrue01.py F. [ 53%] test_fixtrue02.py F. [ 66%] test_parameterized.py .F.. [ 93%] test_sample.py F [100%] ==================================================================== FAILURES ===================================================================== ____________________________________________________________________ test_add2 ____________________________________________________________________ def test_add2(): > assert add(5, 5) > 10 E assert 10 > 10 E + where 10 = add(5, 5) test_assert.py:34: AssertionError _____________________________________________________________________ test_35 _____________________________________________________________________ def test_35(): > assert mul(3, 5) == 14 E assert 15 == 14 E + where 15 = mul(3, 5) test_fixtrue01.py:41: AssertionError -------------------------------------------------------------- Captured stdout setup -------------------------------------------------------------- ===========setup_module========= ==========setup_founction========= ==========setup========= ------------------------------------------------------------ Captured stdout teardown ------------------------------------------------------------- =========teardowm========== ==========setup_founction========== _______________________________________________________________ TestMul.test_mul35 ________________________________________________________________ self = <pyTest.test_fixtrue02.TestMul object at 0x00000276153A5F88> def test_mul35(self): > assert mul(3, 5) == 16 E assert 15 == 16 E + where 15 = mul(3, 5) test_fixtrue02.py:41: AssertionError -------------------------------------------------------------- Captured stdout setup -------------------------------------------------------------- ===============setup_class=============== ==============setup_method================= ==========setup============= ------------------------------------------------------------ Captured stdout teardown ------------------------------------------------------------- ===========teardown============ ==============teardown_method============== _________________________________________________________________ test_row[case2] _________________________________________________________________ base = 3, exponent = 3, expected = 9 @pytest.mark.parametrize( "base, exponent, expected", ((2, 2, 4), (3, 3, 9), (2, 3, 8), (0, 9, 0)), ids=["case1", "case2", "case3", "case4"]) def test_row(base, exponent, expected): > assert math.pow(base, exponent) == expected E assert 27.0 == 9 E + where 27.0 = <built-in function pow>(3, 3) E + where <built-in function pow> = math.pow test_parameterized.py:18: AssertionError ___________________________________________________________________ test_answer ___________________________________________________________________ def test_answer(): > assert inc(3) == 5 E assert 4 == 5 E + where 4 = inc(3) test_sample.py:13: AssertionError ============================================================= short test summary info ============================================================= FAILED test_assert.py::test_add2 - assert 10 > 10 FAILED test_fixtrue01.py::test_35 - assert 15 == 14 FAILED test_fixtrue02.py::TestMul::test_mul35 - assert 15 == 16 FAILED test_parameterized.py::test_row[case2] - assert 27.0 == 9 FAILED test_sample.py::test_answer - assert 4 == 5 ========================================================== 5 failed, 10 passed in 0.13s ===========================================================
4.5.指定特定類或方法執行
這裡指定執行 test_fixtures_02.py 檔案中 TestMul 類下的test_mul35()方法,檔名、類名和方法名之間用“::”符號分隔(base_practice) D:\00test\base_practice\pyTest>pytest test_fixtrue02.py::TestMul::test_mul35 =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 1 item test_fixtrue02.py F [100%] ==================================================================== FAILURES ===================================================================== _______________________________________________________________ TestMul.test_mul35 ________________________________________________________________ self = <pyTest.test_fixtrue02.TestMul object at 0x0000027E785C9808> def test_mul35(self): > assert mul(3, 5) == 16 E assert 15 == 16 E + where 15 = mul(3, 5) test_fixtrue02.py:41: AssertionError -------------------------------------------------------------- Captured stdout setup -------------------------------------------------------------- ===============setup_class=============== ==============setup_method================= ==========setup============= ------------------------------------------------------------ Captured stdout teardown ------------------------------------------------------------- ===========teardown============ ==============teardown_method============== ===============teardown_class============== ============================================================= short test summary info ============================================================= FAILED test_fixtrue02.py::TestMul::test_mul35 - assert 15 == 16 ================================================================ 1 failed in 0.04s ================================================================
4.6.通過 main()方法執行測試
import pytest if __name__ == '__main__': pytest.main(['-s', './test_dir'])建立 run_tests.py 檔案,在檔案中通過陣列指定引數,每個引數為陣列中的一個元素。
5、生成測試報告
pytest 支援生成多種格式的測試報告。5.1生成 JUnit XML 檔案
> pytest ./test_dir --junit-xml=./report/log.xml
XML 型別的日誌主要用於存放測試結果,方便我們利用裡面的資料定製自己的測試報告。XML 格式的測試報告如圖所示。
執行結果:
(base_practice) D:\00test\base_practice\pyTest>pytest test_assert.py --junit-xml=./report/log.xml =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: D:\00test\base_practice\pyTest collected 6 items test_assert.py .F.... [100%] ==================================================================== FAILURES ===================================================================== ____________________________________________________________________ test_add2 ____________________________________________________________________ def test_add2(): > assert add(5, 5) > 10 E assert 10 > 10 E + where 10 = add(5, 5) test_assert.py:34: AssertionError ---------------------------------------- generated xml file: D:\00test\base_practice\pyTest\report\log.xml ---------------------------------------- ============================================================= short test summary info ============================================================= FAILED test_assert.py::test_add2 - assert 10 > 10 =========================================================== 1 failed, 5 passed in 0.06s ===========================================================
6、conftest.py
conftest.py 是 pytest 特有的本地測試配置檔案,既可以用來設定專案級別的 Fixture,也可以用來匯入外部外掛,還可以用來指定鉤子函式。 建立 test_project/conftest.py 測試配置檔案。 需要說明的是,conftest.py 只作用於它所在的目錄及子目錄。建立 test_project/conftest.py 測試配置檔案
import pytest @pytest.fixture() def test_url(): return "https://www.baidu.com"
建立 test_project/test_sub.py 測試用例檔案
def test_baidu(test_url): print(test_url)這裡建立的函式可以直接呼叫 conftest.py 檔案中的 test_url()鉤子函式,測試結果如下
(base_practice) D:\00test\base_practice\pyTest>pytest -v -s test_project\ =============================================================== test session starts =============================================================== platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- C:\Users\yzp\PycharmProjects\base_practice\Scripts\python.exe cachedir: .pytest_cache rootdir: D:\00test\base_practice\pyTest collected 1 item test_project/test_sub.py::test_baidu https://www.baidu.com PASSED ================================================================ 1 passed in 0.01s ================================================================
本部落格所有文章僅用於學習、研究和交流目的,歡迎非商業性質轉載。
本文來自部落格園,作者:hello_殷,轉載請註明原文連結:https://www.cnblogs.com/yinzuopu/p/15572779.html
本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,並保留此段宣告,否則保留追究法律責任的權利。