引言
在編寫介面自動化用例時,我們一般針對一個介面建立一個.py檔案,一條介面測試用例封裝為一個函式(方法),但是在批量執行的過程中,如果其中一條出錯,後面的用例就無法執行,還有在執行大量的介面測試用例時測試資料如何管理和載入。針對測試用例載入以及執行控制,python語言提供了unittest單元測試框架,將測試用例編寫在unittest框架下,使用該框架可以單個或者批量載入互不影響的用例執行及更靈活的執行控制,對於更好的進行測試資料的管理和載入,這裡我們引入資料驅動的模組:ddt,測試資料和測試指令碼的分離,通過ddt資料驅動來載入測試資料到測試用例指令碼中,通常在介面自動化測試中會將unittest和ddt結合起來使用,從而實現測試用例指令碼和測試資料的載入來完成測試的執行。下面來看看unittest框架和ddt這兩個模組具體的應用。
一、unittest測試框架
unittest單元測試框架是python語言的一套標準模組,封裝提供了諸多操作測試用例和用例載入、測試前置和場景恢復以及測試結果輸出等一系列類和方法。
1.unittest框架中最核心四個元件概念:
(1)TestCase:測試用例類,編寫測試用例指令碼時需要繼承該類,從而具有該類的屬性和方法,一個TestCase例項就是一個測試用例,其中測試用例方法都以test開頭。
(2)TestSuite:測試集,也就是測試用例的集合,用來組織用例。
(3)testrunner:用來執行測試用例,並返回測試用例的執行結果,可以用圖形或者文字將測試結果形象地展現出來,HTMLTestRunner用來生成圖形化的報告,TextTestRunner用來生成簡單的文字測試結果。
(4)testfixure:測試夾件,主要用於測試用例的前置初始化和執行後的銷燬。
2.testcase----測試用例
- 新建一個的.py測試用例檔案必須是test開頭,如test_login.py,主要後續用於識別測試用例檔案
- 編寫測試用例的類,必須繼承unittest.TestCase,做為測試類
- 測試類中用例的方法名稱必須以test開頭,用於識別測試用例數
- 測試類中的用例執行順序,按照以test開頭的方法後的Ascill碼順序執行(0~9,A~Z,a~z)
3.testfixure----測試夾件
- 也叫測試夾具,主要是用例前置的初始化以及執行後的銷燬
- 測試夾件提供兩種方法,一種是類級別的:setup()和teardown(),一種是方法級別的:setUpClass()和tearDownClass()
- 類級別的測試夾件,每一條測試用例執行之前與之後都要執行一次setup()和teardown();方法級別的測試夾件,所有測試用例執行之前到執行完成只執行一次setUpClass()和tearDownClass()
下面通過簡單的程式碼示例看看TestCase與TestFixure的使用
(1)使用setup()和teardown(),建立test_666.py檔案編輯如下程式碼:
import unittest class test_unittest(unittest.TestCase): def setUp(self): print("測試環境初始化,開始執行setup") def tearDown(self): print("測試執行完成,執行teardown") print("------------------------------") def test_a(self): print("開始執行test_a用例") def test_A(self): print("開始執行test_A用例") def test_1(self): print("開始執行test_1用例") def notest_1(self): print("不執行notest_1用例") if __name__ == "__main__": unittest.main()
執行後,輸出如下:
在程式碼中我們編寫了4個def用例方法,只執行了3個def,因為最後一個def不是test開頭。可以看到每執行一個def用例,setup()和teardown()都會執行一次,其中按照執行順序:test_1最先執行,test_A其後,test_a最後執行
(2)使用setUpClass()和tearDownClass()
對於setUpClass()和tearDownClass()我們只需將上面程式碼,稍微修改即可
import unittest class test_unittest(unittest.TestCase): @classmethod def setUpClass(cls): print("測試環境初始化,開始執行setup") @classmethod def tearDownClass(cls): print("測試執行完成,執行teardown") print("------------------------------") def test_a(self): print("開始執行test_a用例") def test_A(self): print("開始執行test_A用例") def test_1(self): print("開始執行test_1用例") if __name__ == "__main__": unittest.main()
執行效果如下:
可以看到所有用例都執行完後,setUpClass()和tearDownClass()只執行了一次。因此在編寫一個測試指令碼時,裡面寫了多個測試用例,
這時我們希望的是所有用例執行完成後再銷燬環境,這時使用
setUpClass()
和tearDownClass()就比較好了。
3.TestSuite----測試集
unittest框架下提供了unittest.TestSuite()和unittest.TestLoader()類,這兩個類下封裝了載入用例的方法,用於載入測試用例到測試集中
(1)unittest.TestSuite()提供單個用例載入方法
addTest():單個用例載入,當然也可以將多個用例的方法名放入列表中新增到addTest()中,載入多條測試用例
(2)unittest.TestLoader()提供批量載入或發現用例的方法
loadTestsFromTestCase(測試類名):新增一個測試類
loadTestsFromModule(模組名):新增一個模組
discover(測試用例的所在目錄):指定目錄去載入,會自動尋找這個目錄下所有符合命名規則的測試用例
4.testrunner----測試執行
testrunner就是用來執行測試用例的,並且可以生成相應的測試報告。測試報告有兩種展示形式,一種是text文字,一種是html格式。
html格式的就是HTMLTestRunner了,HTMLTestRunner是 Python 標準庫的 unittest 框架的一個擴充套件,它可以生成一個直觀清晰的 HTML 測試報告。使用的前提就是要下載 HTMLTestRunner.py,下載完後放在python的安裝目錄下的scripts目錄下即可。
通過程式碼示例看看testsuite和testrunner這兩個元件的使用,上面的test_666.py用例檔案我們已經寫好了3條用例了,現在我們來載入這些用例
新建run_case.py檔案,該檔案和test_666.py檔案放置在同一個包檔案:test下,run_case.py檔案編輯如下程式碼執行:
import unittest from test.test_666 import test_unittest # 單個用例載入 suite = unittest.TestSuite() case1 = test_unittest('test_1') case2 = test_unittest('test_a') suite.addTest(case1) suite.addTest(case2) print(suite) print("------------------") # 批量用例載入 case_path = r"E:\api_test\test" # 按檔案路徑載入,注意該檔案為包檔案即檔案下有__init__.py all_case = unittest.defaultTestLoader.discover(case_path,pattern="test_666*.py",top_level_dir=None) all_case1 = unittest.defaultTestLoader.loadTestsFromTestCase(test_unittest) # 按類名稱載入 print(all_case) print("------------------") print(all_case1)
輸出結果如下:
E:\api_test\Scripts\python.exe E:/api_test/test_bak/run_case.py <unittest.suite.TestSuite tests=[<test.test_666.test_unittest testMethod=test_1>, <test.test_666.test_unittest testMethod=test_a>]> ------------------ <unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<test_666.test_unittest testMethod=test_1>, <test_666.test_unittest testMethod=test_A>, <test_666.test_unittest testMethod=test_a>]>]>]> ------------------ <unittest.suite.TestSuite tests=[<test.test_666.test_unittest testMethod=test_1>, <test.test_666.test_unittest testMethod=test_A>, <test.test_666.test_unittest testMethod=test_a>]> Process finished with exit code 0
通過unittest框架下提供的載入用例的諸多方法,我們就可以單個或者批量載入用例,後續可以將載入的用例集引入到HTMLTestRunner.py模組生成視覺化的測試報告
5.assert----測試斷言
無論是什麼樣的測試用例,最後都需要有用例執行後的驗證,在介面自動化測試中我們執行完介面用例也需要驗證斷言用例執行是否滿足我們的預期。unittest提供了豐富的斷言方法,常見的斷言如下表:
二、ddt資料驅動
- @ddt:類的裝飾器,繼承的是TestCase類
- @data():@data裝飾符可以把引數當成測試資料,引數可以是單個值、列表、元祖、字典這些型別,用於輸入測試資料
- @unpack:分解資料標誌,主要是把元祖和列表解析成多個引數
- @file_data():輸入檔案,如json或者yaml型別檔案
import unittest from ddt import data,unpack,ddt @ddt class myddt(unittest.TestCase): @data("123") # 單個值 def test1(self,testdata1): print(testdata1) print("------------------") @data([1,2,3],[4,5,6]) # 列表 def test2(self,testdata2): print(testdata2) print("------------------") """ @data((1, 2, 3)) # 元組 def test2(self, testdata3): print(testdata3) print("------------------") @data({'zhangshan':1,'wangwu':2,'lisi':3}) # 字典 def test2(self, testdata4): print(testdata4) print("------------------") """ if __name__ == '__main__': unittest.main()
(2)使用@unpack對複雜資料結構,如元組、列表資料進行分解
程式碼示例:
import unittest from ddt import data,unpack,ddt @ddt class myddt(unittest.TestCase): @data([1,2],[3,4]) # 列表 @unpack def test2(self, testdata1,testdata2): print("拆解的第一個引數:",testdata1) print("拆解的第二個引數:", testdata2) print("------------------") if __name__ == '__main__': unittest.main()
執行後輸出如下:
(3)使用@file_data()輸入檔案格式測試資料
編輯一個data.json的檔案,程式碼示例:
import unittest from ddt import file_data,ddt @ddt class myddt(unittest.TestCase): @file_data(r"E:\api_test\test\data.json") def test1(self, *value): print(value) if __name__ == '__main__': unittest.main()
通過ddt和unittest框架的結合就可以實現測試用例指令碼編寫、測試執行控制以及測試資料的批量載入,從而完成不同介面測試用例的批量執行和覆蓋測試不同測試場景。