引言
前面一篇文章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自動化測試感興趣的朋友,可以加入左下方學習交流群,討論交流一下心得。
