引言
前面一篇文章Python單元測試框架介紹已經介紹了python單元測試框架,大家平時經常使用的是unittest,因為它比較基礎,並且可以進行二次開發,如果你的開發水平很高,集成開發自動化測試平台也是可以的。而這篇文章主要講unittest與pytest的區別,pytest相對unittest而言,代碼簡潔,使用便捷靈活,並且插件很豐富。
Unittest vs Pytest
主要從用例編寫規則、用例的前置和后置、參數化、斷言、用例執行、失敗重運行和報告這幾個方面比較unittest和pytest的區別:
用例編寫規則
用例前置與后置條件
斷言
測試報告
失敗重跑機制
參數化
用例分類執行
如果不好看,可以看下面表格:
總體來說,unittest用例格式復雜,兼容性無,插件少,二次開發方便。pytest更加方便快捷,用例格式簡單,可以執行unittest風格的測試用例,無須修改unittest用例的任何代碼,有較好的兼容性。pytest插件豐富,比如flask插件,可用於用例出錯重跑,還有xdist插件,可用於設備並行執行,效率更高。
實例演示
講了七大區別,總要演示一下具體實例,用事實說話。
前后置區別
這里抽用例前置與后置的區別來講,先看unittest的前后置使用:
import unittest class TestFixtures01(unittest.TestCase): # 所有用例執行前執行 def setUp(self) -> None: print("setUp開始") def tearDown(self) -> None: print("tearDown結束") # 每條用例執行前執行 @classmethod def setUpClass(cls) -> None: print("setUpClass開始") @classmethod def tearDownClass(cls) -> None: print("tearDownClass結束") # 測試用例 def test_001(self): print("測試用例001") class TestFixtures02(unittest.TestCase): def test_002(self): print("測試類2") # 每個模塊執行前執行 def setUpModule(): """ 在所有測試類在調用之前會被執行一次,函數名是固定寫法,會被unittest框架自動識別 """ print('集成測試 >>>>>>>>>>>>>>開始') def tearDownModule(): print("集成測試 >>>>>>>>>>>>>>結束") if __name__ == '__main__': unittest.main()
運行結果:
從結果上得知, 三個方法的邏輯優先級: setUp()&tearDown() < setUpClass()&tearDownClass() < setUpModule()&tearDownModule()
接下來看pytest的前后置:
1、我們都知道在自動化測試中都會用到前后置,pytest 相比 unittest 無論是前后置還是插件等都靈活了許多,還能自己用 fixture 來定義。
首先了解一下,用例運行前后置級別如下:
1.模塊級:全局的,整個模塊開只運行一次,優先於測試用例。
2.類級別:定義在類里面,只針對此類生效。類似unittest的cls裝飾器
3.函數級:只對函數生效,類下面的函數不生效。
4.方法級:定義在類里面,每個用例都執行一次
def setup_module(): print('\n整個模塊 前 只運行一次') def teardown_module(): print('\n整個模塊 后 只運行一次') def setup_function(): print('\n不在類中的函數,每個用例 前 只運行一次') def teardown_function(): print('\n不在類中的函數,每個用例 后 只運行一次') def test_ab(): b = 2 assert b < 3 def test_aba(): b = 2 assert b < 3 class Test_api(): def setup_class(self): print('\n此類用例 前 只執行一次') def teardown_class(self): print('\n此類用例 后 只執行一次') def setup_method(self): print('\n此類每個用例 前 只執行一次') def teardown_method(self): print('\n此類每個用例 后 執行一次') def test_aa(self): a = 1 print('\n我是用例:a') # pytest -s 顯示打印內容 assert a > 0 def test_b(self): b = 2 assert b < 3
運行結果:
2、這是原始用法,下面看使用Fixture,Fixture 其實就是自定義 pytest 執行用例前置和后置操作,首先創建 conftest.py 文件 (規定此命名),導入 pytest 模塊,運用 pytest.fixture 裝飾器,默認級別為:函數級:
其它用例文件調用即可,如下定義一個函數,繼承 conftest.py 文件里的 login 函數即可調用:
# conftest.py配置需要注意以下點: # conftest.py配置腳本名稱是固定的,不能改名稱 # conftest.py與運行的用例要在同一個pakage下,並且有__init__.py文件 # 不需要import導入 conftest.py,pytest用例會自動查找 import pytest def test_one(login): print("登陸后,操作111") # def test_two(): # print("操作222") # # def test_three(login): # print("登陸后,操作333")
運行結果:
3、擴展用法,多個自定義函數和全局級別展示:(全局的比如用於登錄獲取到token其他用例模塊就不需要再登錄了)
import pytest def test_one(login): print("登陸后,操作111") def test_two(login,open_page): print("測試用例2") def test_three(open_page): print("測試用例3")
運行結果:
細心的人應該可以知道,測試用例2並沒有調用login函數,因為前置設置的是共享模式,類似全局函數。
參數化區別
參數化應用場景,一個場景的用例會用到多條數據來進行驗證,比如登錄功能會用到正確的用戶名、密碼登錄,錯誤的用戶名、正確的密碼,正確的用戶名、錯誤的密碼等等來進行測試,這時就可以用到框架中的參數化,來便捷的完成測試。
參數化 就是數據驅動思想,即可以在一個測試用例中進行多組的數據測試,而且每一組數據都是分開的、獨立的。
unittest參數化其實是:ddt,叫數據驅動。
pytest數據驅動,就是參數化,使用@pytest.mark.parametrize
1.先看unittest如何進行參數化:
test_data = [1,2,3] @ddt.ddt class Testddt(unittest.TestCase): @ddt.data(*test_data) def test_001(self,get_data): print(get_data) if __name__ == '__main__': unittest.main()
運行結果:
2.pytest中參數化的用法
在測試用例的前面加上:
@pytest.mark.parametrize("參數名",列表數據)
參數名:用來接收每一項數據,並作為測試用例的參數。
列表數據:一組測試數據。
@pytest.mark.parametrize("參數1,參數2",[(數據1,數據2),(數據1,數據2)])
示例:
@pytest.mark.parametrize("a,b,c",[(1,3,4),(10,35,45),(22.22,22.22,44.44)])
def test_add(a,b,c):
res = a + b
assert res == c
實例:
@pytest.mark.parametrize('data',[1,2,3]) class Testddt(object): def test_001(self,data): print(data) if __name__ == '__main__': pytest.main(['-sv'])
運行結果:
總結
以上就是unittest與pytest測試框架的區別,七大主要區別,這里已講了兩個區別的實例,其他五個有時間再補充,如對python自動化測試感興趣的朋友,可以加入左下方學習交流群,討論交流一下心得。