一、pytest簡潔和好處
- 自動發現測試用例 testloader
- 斷言方便 ,自定義錯誤提示 assert 正則匹配
- 靈活運行指定的測試用例,指定模塊,制定測試類,測試用例 -k 標簽化,回歸 正向 冒煙 登陸
- 環境管理靈活。
- 豐富的插件,測試報告,插件介紹 allure(比較成熟的測試報告體系,unittest不支持這個插件)
- 和unittest / nose兼容,pytest中標簽、生成allure、分析最慢的測試用例和unittest兼容
unittest的好處:
1.標准庫,兼容性好
2.更加容易理解
pytest和unittest兼容是有條件的,pytest使用以下功能就不能和unittes兼容:
- parametrize
- fixture(autouse=True的可以) 不能和setUp同時使用
- Custom hooks
二、自動發現測試用例原理,命名方式
- 文件名必須以test_*.py 和 *_test.py開頭或結尾,
- 如果有類名,必須以Test開頭,沒有__init__函數,測試方法名以test_開頭的函數
- 沒有類,那么以函數為單位的函數名必須以test_開頭
三、斷言: 自定義提示文案
assert 1==1, "提示文案"
四、運行方式
1.在控制台指定執行范圍
- 在指定文件中輸入pytest,此時會收集該文件中所有測試用例
- 指定某個模塊,例如 pytest test_demo1.py
- 指定某個目錄及其子目錄的所有測試文件,pytest 文件名,例pytest testcase
- 指定某個模塊下某個類的某個用例,pytest 模塊名::類名::方法名,例pytest test_demo2.py::TestDemo2::test_success
- 指定某個模塊下的某個方法,pytest 模塊名::方法名,例pytest test_demo1.py::test_fail
- python -m pytest/unittest
2.編輯器
Run -->Run...-->Edit Configurations-->+ -->python test -->pytest -->Run
3.通過python代碼執行pytest
直接執行pytest.main(),自動查找當前目錄下,以test_開頭的文件或者以_test結尾的py文件
五、自定義查找規則(在根目錄下pytest.ini)
[pytest] python_files = test_*.py check_*.py example_*.py python_functions = *_test python_classes = *Suite
四、mark隨機測試(冒煙測試,給測試用例打標簽)
第一步:mark注冊,新建ini文件
#pytest.ini
[pytest] markers = login demo
第二步:
1.把標簽貼到測試用例(方法)上,一個測試用例上可以貼多個標簽,標簽不僅可以貼到測試用例上,還可以貼到測試類上
@pytest.mark.標簽名
2.貼標簽第二種方法:標記在測試類中,固定寫法
pytestmark = [pytest.mark.標簽名, pytest.mark.標簽名]
import pytest class TestDemo4: pytestmark = [pytest.mark.login] # @pytest.mark.login def test_demo_4(self): assert 1 == 1
第三步:運行的時候指定標簽,在Terminal輸入pytest -m "mark1 and not mark2"
注意:一定要使用雙引號,單引號會報錯
五、跳過函數
@pytest.mark.skip(reason='out-of-data api')
# skipif 當滿足某個條件時就跳過
@pytest.mark.skipif(sys.plafform == "win32", reason="does not run on windows")
# 跳過預見錯誤
@pytest.mark.xfail(gen.__version__ < '0.2.0', reason='not supported until v0.2.0')
def test_api():
id_1 = gen.unique_id()
id_2 = gen.unique_id()
assert id_1 != id_2
六、pytest的用例執行順序
pytest有自己內置的執行順序規則,一般從上到下,可以通過安裝插件pytest.ordering:run your tests in order
七、參數化
ddt數據驅動只是unittest支持數據驅動的一種庫 ddt != 數據驅動
ddt模塊不能和fixture共用,所以要換用pytest的參數化實現ddt
參數化會和unittest沖突,因為setUp這些東西都不會運行了!要改成pytest,不要繼承unittest.TestCase
方法一:使用pytest.mark.parametrize()方式進行參數化
import pytest Data = [1, 2, 3] @pytest.mark.parametrize("data", Data) def test_mock(data): print('測試開始') assert data == 2, "備注信息"
方法二:使用pytest.fixture()方式進行參數化,fixture裝飾的函數可以作為參數傳入其他函數
1.在固件中添加返回值
2.然后在測試方法中傳入固件
3.在測試方法中,用固件名來表示其返回值
test_demo.py
import pytest class TestDemo1: # 定義參數列表 list_a = [1, 2, 3] # 定義固件名is_success,並設置返回值 @pytest.fixture(params=list_a) def is_success(self, request): return request.param # 在測試方法中傳入固件名 @pytest.mark.success def test_success(self, is_success): assert is_success == 1
方法三:測試數據和用例分離
可以采用conftest.py文件存儲參數化數據和函數,模塊下的用例執行時,會自動讀取conftest.py文件中的數據
1.先定義一個固件is_success
conftest.py
import pytest # 准備測試數據 list_a = [1, 2, 3] # params中需要傳入list @pytest.fixture(params=list_a) def is_success(request): return request.param
2.在測試類中傳入固件名稱
test_demo4.py
import pytest class TestDemo4: @pytest.mark.test def test_demo_4(self, is_success): # print('測試一下') assert is_success == 1
八、fixture的使用(原文鏈接:https://blog.csdn.net/BearStarX/article/details/101000516)
fixture相對於setUp和tearDown來說的優勢:
- 命名方式靈活,不局限於setUp和tearDown這幾個命名
- conftest.py配置里可以實現數據共享,不需要import就能自動找到一些配置
- scope = "module"可以實現多個.py跨文件共享前置
- scope = "session"可以實現多個.py跨文件使用一個session來完成多個用例
通過yield生成器實現了前置條件和后置條件的組合
1.先在根目錄conftest.py文件中定義一個名為init_web的固件
import pytest @pytest.fixture() def init_web(): print("啟動瀏覽器") yield driver print("關閉瀏覽器")
2.作為參數傳到測試用例中
def test_demo(init_web):
3.接收這個東西
driver = init_web
import pytest class TestDemo3: @pytest.mark.login def test_demo3(self, init_web): driver = init_web assert driver == 2
注意:
1.pytest 運行默認不會打印固件中print(),如果想打印,那么使用python -m login -s 或者 pytest --capture=no
九、重運行
安裝插件:pip install pytest -rerunfailures
pytest --reruns 3 --reruns-delay 5
十、測試報告
各種插件地址:https://plugincompat.herokuapp.com/
html:--html=\report\demo.html
需要安裝:
pip install pytest-html
# log
--resultlog=report/demo.txt 相對路徑
# xml,jenkins使用
--junitxml=report/demo.xml
# html
--html=report/demo.html
main.py
import pytest
import time if __name__ == '__main__':
ts = time.time() pytest.main(['-m test', '-s', '--resultlog=report/{}.txt'.format(ts), '--junitxml=report/demo.xml', '--html=report/demo.html'])
在Terminal輸入:python main.py
查看結果:在根目錄下會生成一個含有各種報告的report文件夾