一、單元測驗框架簡介
1. 什么是單元測驗
單元測驗是指在軟體開發程序中,針對軟體的最小單位(函式,方法)進行正確性的檢查測驗,
2. 常用單元測驗框架
2.1 Java 類別
-
junit
-
testng
2.2 Python 類別
-
unittest
-
pytest
3. 單元測驗框架主要作用
-
測驗發現:從多個檔案中找到測驗用例
-
測驗執行:按照一定的順序和規則去執行用例,并生成結果
-
測驗判斷:通過斷言判斷預期結果和實際結果的差異
-
測驗報告:統計測驗進度、耗時、通過率,生成測驗報告
二、自動化測驗框架簡介
1. 什么是自動化測驗框架
自動化測驗框架是指為了完成一個指定的系統的自動化測驗而封裝的一整套的完成的代碼,主要封裝了自動化的基礎模塊、管理模塊、測驗的統計模塊等等,
2. 自動化測驗框架的作用
-
提高測驗效率,降低維護成本
-
減少人工干預,提高測驗的準確性,增加代碼的重用性
-
核心思想是讓不懂代碼的人也能夠通過這個框架去實作自動化測驗
3. 單元測驗框架和自動化測驗框架的關系
單元測驗框架只是自動化測驗框架中的組成部分之一,一套完整的自動化測驗框架還包括:pom設計模式、資料驅動、關鍵字驅動、全域組態檔的封裝、日志監控、類似selenium和requests等功能模塊的二次封裝、斷言系統、測驗報告郵件等許多方面,
三、Pytest 簡介
pytest 是一個非常成熟的 Python 單元測驗框架,比 unittest 更加靈活,功能也更加強大,使用 pytest 主要有以下優點:
-
可以和 selenium,requests,appium 結合實作 web 自動化,介面自動化,app 自動化;
-
可以實作測驗用例的跳過和失敗用例重跑機制;
-
可以和 allure 結合生成非常美觀的測驗報告;
-
可以和 jenkins 持續集成;
-
有很多強大的插件:
-
pytest:指定用例執行方式
-
pytest-html:生成 html 格式的自動化測驗報告
-
pytest-xdist:測驗用例分布執行,多 CPU 分發
-
pytest-ordering:用于改變測驗用例的執行順序
-
pytest-rerunfailures:用例失敗后重跑
-
框架和插件的下載:
1 # 直接通過 pip 下載 2 pip install pytest 3 pip install pytest-html 4 pip install pytest-xdist 5 pip install pytest-ordering 6 pip install pytest-rerunfailures
四、Pytest 的使用
1. 默認規則
在使用 pytest 框架時,需要遵循一些默認的規則(規則不是固定的,可以根據全域組態檔進行規則的修改):
-
模塊名必須以
test_開頭或者以_test結尾; -
測驗類必須以
Test開頭,并且不能有init方法; -
測驗方法必須以
test開頭
如下我們創建一套測驗環境,其中 cases 目錄為自定義目錄,用于存放所有的測驗用例:

2. 測驗用例的執行
構造如下測驗專案:

其中各個用例模塊的代碼內容為:
1 # product_cases/test_product.py 2 def test_out_case(): 3 print("模擬測驗用戶退出操作") 4 ? 5 6 # user_cases/test_login.py 7 def test_other_case(): 8 print("模擬測驗其他情況") 9 ? 10 class TestLogin: 11 ? 12 def test_case_001(self): 13 print("模擬測驗用戶登錄操作") 14 15 ? 16 # user_cases/test_logout.py 17 def test_out_case(): 18 print("模擬測驗用戶退出操作")
pytest 用例的執行主要有以下三種方式:
-
通過主函式執行
-
通過命令模式執行
-
通過讀取
pytest.ini組態檔執行
2.1 通過主函式執行
2.1.1 執行所有用例
我們修改一下用戶登錄的用例:
1 # user_cases/test_login.py 2 # 匯入pytest 3 import pytest 4 ? 5 ? 6 def test_other_case(): 7 print("模擬測驗其他情況") 8 ? 9 ? 10 class TestLogin: 11 ? 12 def test_case_001(self): 13 print("模擬測驗用戶登錄操作") 14 ? 15 ? 16 if __name__ == '__main__': 17 pytest.main() # 執行測驗用例
此時直接執行:

從終端的列印可以看到,用例檔案中的用例方法 test_other_case 以及測驗類中的測驗方法 test_case_001 都被執行了,
我們再來修改一下產品操作的用例,并執行看看效果:
1 # product_cases/test_product.py 2 import pytest 3 ? 4 def test_product_case(): 5 print("模擬測驗產品相關的操作") 6 ? 7 ? 8 if __name__ == '__main__': 9 pytest.main()

可見,只需要在對應的用例檔案中呼叫主函式,就可以自動執行檔案中的所有用例,但是在實際的使用中,我們一般會將用例分類寫在不同目錄下的不同用例檔案里,且執行時要批量去執行所有的用例,所以我們往往會將主函式寫在一個與用例檔案夾平級的 py 檔案中,pytest 內部設有對應的機制,會自動掃描全域,執行所有的用例檔案,

1 # all.py 2 import pytest 3 ? 4 if __name__ == '__main__': 5 pytest.main()
執行 all.py 檔案,從終端輸出可以看到,所有的用例都被執行了:

2.1.2 運行指定模塊
1 # all.py 2 import pytest 3 ? 4 if __name__ == '__main__': 5 pytest.main(["./user_cases/test_logout.py"]) # 只運行用戶退出操作用例

2.1.3 運行指定目錄
1 # all.py 2 import pytest 3 ? 4 if __name__ == '__main__': 5 pytest.main(["./user_cases"]) # 只運行用戶目錄下的所有用例

2.1.4 通過nodeid指定用例運行
注:nodeid 由模塊名、分隔符、類名、方法名、函式名組成
1 # all.py 2 import pytest 3 ? 4 if __name__ == '__main__': 5 # 只運行用戶登錄用例模塊中的 test_other_case 測驗方法 6 pytest.main(["-vs", "./user_cases/test_login.py::test_other_case"]) 7 # 只運行用戶登錄用例模塊中的 TestLogin 測驗類中的 test_case_001 測驗方法 8 pytest.main(["-vs", "./user_cases/test_login.py::TestLogin::test_case_001"])
2.2 通過命令模式去執行
2.2.1 執行所有用例
直接通過 pytest 命令就可以執行當前目錄下所有的測驗用例,所以要想執行專案中所有的用例,只需要將執行目錄切換到根目錄即可:

2.2.2 運行指定模塊
pytest ./product_cases/test_product.py

2.2.3 運行指定的目錄
pytest ./product_cases

2.2.4 通過nodeid指定用例運行
pytest ./user_cases/test_login.py::test_other_case
pytest ./user_cases/test_login.py::TestLogin::test_case_001


2.3 通過組態檔去執行
在真正的專案中,都是通過配置全域的組態檔來執行測驗用例的,其余兩種執行方式在撰寫和除錯用例時比較方便,對于組態檔,有以下幾點要求:
-
組態檔的名字必須為
pytest.ini -
組態檔一般放置在專案的根目錄
-
組態檔必須時 ANSI 編碼
pytest.ini 是 pytest 框架的核心組態檔,它可以改變 pytest 的默認行為,不管是通過主函式還是命令模式去執行用例,都會先去讀取組態檔,
1 # pytest.ini 2 [pytest] 3 # 命令列引數,多個引數用空格隔開 4 addopts = -vs --reruns=2 5 # 測驗用例檔案夾,可自己配置 6 testpaths = ./user_cases 7 # 配置測驗搜索的模塊名稱,如下表示搜索的模塊必須以test_開頭 8 python_files = test_*.py 9 # 配置測驗搜索的測驗類名,如下表示搜索的測驗類必須以Test開頭 10 python_classes = Test* 11 # 配置測驗搜索的測驗函式名 12 python_functions = test
修改完配置后,再去執行用例時就會按照配置上要求去執行:

3. 執行時使用引數
我們在執行用例時,可以通過添加相關的引數實作不同的執行效果,提升測驗效率,
-
- s:用于輸出除錯資訊,包括列印輸出的資訊
1 # 通過main函式執行 2 pytest.main(["-s", "./product_cases/test_product.py"]) 3 # 通過命令模式執行 4 pytest -s ./product_cases/test_product.py

-
-v:顯示更詳細的資訊
1 # 通過main函式執行 2 pytest.main(["-v", "./product_cases/test_product.py"]) 3 # 通過命令模式執行 4 pytest -v ./product_cases/test_product.py

-
-vs:將 -v 和 -s 引數效果結合,推薦使用

-
-n:支持多執行緒或者分布式運行測驗用例
1 # 通過main函式執行 2 # 開兩個執行緒去執行用戶操作目錄下所有的用例 3 pytest.main(["-vs", "./user_cases", "-n=2"]) 4 5 # 通過命令模式執行 6 pytest -vs ./user_cases -n 2
為了方便看出測驗效果,我們給用戶操作目錄下的每個測驗方法中都添加一個睡眠延時:
1 # user_cases/test_login.py 2 import time 3 4 def test_other_case(): 5 time.sleep(2) 6 print("模擬測驗其他情況") 7 8 class TestLogin: 9 10 def test_case_001(self): 11 time.sleep(2) 12 print("模擬測驗用戶登錄操作") 13 14 15 # user_cases/test_logout.py 16 import time 17 18 def test_out_case(): 19 time.sleep(2) 20 print("模擬測驗用戶退出操作")
正常執行結果:

開啟執行緒執行結果:

-
--reruns:失敗用例重跑
1 # 通過main函式執行 2 # 如果用例執行失敗,該用例再執行2次 3 pytest.main(["-vs", "./user_cases", "--reruns=2"]) 4 5 # 通過命令模式執行 6 pytest -vs ./user_cases --reruns 2
為了方便測驗重跑機制,我們將用戶操作用例中的 test_other_case 測驗方法添加一個斷言,使其報錯
1 # user_cases/test_login.py 2 def test_other_case(): 3 print("模擬測驗其他情況") 4 assert 1 == 2 # 執行到此時報錯,該用例不會通過 5 6 class TestLogin: 7 8 def test_case_001(self): 9 print("模擬測驗用戶登錄操作")

-
-x:只要有一個用例失敗,就停止執行
1 # 通過main函式執行 2 pytest.main(["-vs", "./user_cases", "-x"]) 3 4 # 通過命令模式執行 5 pytest -vs ./user_cases -x

-
--maxfail:出現失敗的用例數達到規定值時停止測驗
1 # 通過main函式執行 2 # 失敗的用例數達到兩個時停止測驗 3 pytest.main(["-vs", "./user_cases", "--maxfail=2"]) 4 5 # 通過命令模式執行 6 pytest -vs ./user_cases --maxfail 2
-
-k:根據測驗用例的部分字串指定用例執行
1 # 通過main函式執行 2 # 只執行用例名字中包含01的用例 3 pytest.main(["-vs", "./user_cases", "-k=01"]) 4 5 # 通過命令模式執行 6 pytest -vs ./user_cases --k="01"

如果指定的字串是被測驗類包含的,那么測驗類中所有的測驗方法都會被執行,
-
--html:用例執行完成后生成 html 格式的測驗報告

執行完成后,在本地的 report 檔案夾中生成了對應的測驗報告,打開可以看到用例執行的詳情,

4. 用例執行順序
我們再往 test_product.py 中添加一些測驗方法:
1 # product_cases/test_product.py 2 def test_product_case(): 3 print("模擬測驗產品相關的操作") 4 5 6 def test_case_002(): 7 print("測驗方法_002") 8 9 10 def test_case_003(): 11 print("測驗方法_003") 12 13 14 def test_case_001(): 15 print("測驗方法_001") 16 17 18 def test_case_004(): 19 print("測驗方法_004") 20 21 22 def test_case_005(): 23 print("測驗方法_005")
執行該測驗模塊:

從執行的列印可以看出來,pytest 對于用例的執行順序是按照從上到下執行的,并不像 unittest 那樣是按照用例名的 ASCII 大小來執行的,當然我們也是有方法可以改變用例的執行順序的,
1 # product_cases/test_product.py 2 import pytest 3 4 def test_product_case(): 5 print("模擬測驗產品相關的操作") 6 7 # 通過裝飾器方法 @pytest.mark.run() 可以改變用例的執行順序 8 # order引數表示該用例要排在第幾個執行 9 @pytest.mark.run(order=2) 10 def test_case_002(): 11 print("測驗方法_002") 12 13 14 @pytest.mark.run(order=3) 15 def test_case_003(): 16 print("測驗方法_003") 17 18 19 @pytest.mark.run(order=1) 20 def test_case_001(): 21 print("測驗方法_001") 22 23 24 def test_case_004(): 25 print("測驗方法_004") 26 27 28 def test_case_005(): 29 print("測驗方法_005")

從終端輸出的結果可以看到,被裝飾器裝飾的測驗用例都按照了指定的順序執行,沒有被裝飾到的用例還是按照從上到下的順序執行,
5. 分組執行用例
在實際的測驗業務中,我們常常需要去測驗某些模塊中的某些用例,例如冒煙測驗、分模塊執行、分介面和web執行等測驗場景中就常常涉及到這種需求,pytest 提供了十分便捷的分組執行用例的方式,
-
第一步,使用裝飾器去裝飾要執行的用例,
@pytest.mark.name,其中name為自定義的名稱
1 #################### product_cases/test_product.py ###################### 2 import pytest 3 4 def test_product_case(): 5 print("模擬測驗產品相關的操作") 6 7 def test_case_002(): 8 print("測驗方法_002") 9 10 def test_case_003(): 11 print("測驗方法_003") 12 13 @pytest.mark.product_manage 14 def test_case_001(): 15 print("測驗方法_001") 16 17 @pytest.mark.smoke 18 def test_case_004(): 19 print("測驗方法_004") 20 21 @pytest.mark.product_manage 22 def test_case_005(): 23 print("測驗方法_005") 24 25 26 ################## user_cases/test_login.py ####################### 27 import pytest 28 29 def test_other_case(): 30 print("模擬測驗其他情況") 31 32 class TestLogin: 33 @pytest.mark.user_manage 34 def test_case_001(self): 35 print("模擬測驗用戶登錄操作") 36 37 38 ################### user_cases/test_logout.py ######################## 39 def test_out_case(): 40 print("模擬測驗用戶退出操作")
-
第二步,去
pytest.ini中添加分組配置,配置名必須和裝飾器中的name值一致
1 [pytest] 2 addopts = -vs --reruns=2 3 testpaths = . 4 python_files = test_*.py 5 python_classes = Test* 6 python_functions = test 7 # 分組配置 8 markers = 9 smoke:冒煙用例 10 user_manage:用戶管理用例 11 product_manage:商品管理用例
-
第三步,執行時通過引數
-m指定要執行的用例的分組類別
pytest -m "smoke"

6. 跳過用例
對于某些我們不想執行的用例,可以使用 pytest 提供的裝飾器方法跳過該用例不去執行,
6.1 無條件跳過
裝飾器語法:@pytest.mark.skip(reason="") ,reason 引數可選,表示跳過該測驗方法的原因
1 #################### product_cases/test_product.py ###################### 2 import pytest 3 4 @pytest.mark.skip(reason="無意義的測驗方法") 5 def test_product_case(): 6 print("模擬測驗產品相關的操作") 7 8 9 def test_case_001(): 10 print("測驗方法_001") 11 12 13 def test_case_002(): 14 print("測驗方法_002")

6.2 有條件跳過
裝飾器語法:@pytest.mark.skipif(判斷條件, reason="") ,reason 引數可選,表示跳過該測驗方法的原因
1 import pytest 2 3 num = 20 4 5 @pytest.mark.skip(reason="無意義的測驗方法") 6 def test_product_case(): 7 print("模擬測驗產品相關的操作") 8 9 @pytest.mark.skipif(num > 18, reason="超過限定條件") 10 def test_case_001(): 11 print("測驗方法_001") 12 13 def test_case_002(): 14 print("測驗方法_002")

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/545030.html
標籤:其他
下一篇:類方法和物件方法
