軟件測試通常按階段劃分爲:單元測試,集成測試,系統測試。單元測試(unit testing)是指對軟件中的最小可測試單元進行檢查和驗證。 單元測試中單元的含義,單元就是人爲規定的最小的被測功能模塊,如C語言中單元指一個函數,Java裏單元指一個類,圖形化的軟件中能夠指一個窗口或一個菜單等。在實際項目中,單元測試每每由開發人員完成。html
單元測試其實就是構造數據使用一段代碼去測試另外一段代碼,理論上來講,不使用單元測試框架也能進行單元測試。但若是用於單元測試的代碼(即測試用例)增多,在沒有測試框架的狀況下會變得擁擠、不可管理,這個時候引入測試框架就變得尤其重要。python
單元測試框架提供了一種統一的編程模型,能夠將測試定義爲一些簡單的類,這些類中的方法能夠調用但願測試的應用程序代碼。利用單元測試框架,能夠很輕鬆地插入、設置和分解有關測試的功能,能夠直觀方便地管理測試用例。web
主流的單元測試框架,如Java的Junit、TestNg,python的Unittest、Pyunit、Pytest,通用的自動化測試框架Robot Framework等。編程
提供用例組織與執行瀏覽器
提供豐富的斷言方法app
提供豐富的日誌與測試結果框架
Unittest是Python自帶的單元測試框架,不只適用於單元測試,還可用於Web、Appium、接口自動化測試用例的開發與執行。該測試框架可組織執行測試用例,而且提供豐富的斷言方法,判斷測試用例是否經過,並最終生成測試結果。函數
Unittest官方文檔:https://docs.python.org/3/library/unittest.html單元測試
TestCase:即測試用例,Unittest提供testCase類來編寫測試用例,一個TestCase的實例就是一個測試用例。一條測試用例就是一個完整的測試流程,包括測試前準備環境的搭建(setUp),執行測試代碼(run),以及測試後環境的還原(tearDown),經過運行一條測試用例,能夠對某一個問題進行驗證。測試
Fixture:即測試固件,用於測試用例環境的搭建和銷燬。在測試步驟執行前須要爲該測試用例準備環境(SetUp),如啓動app或打開瀏覽器,測試步驟執行後須要恢復環境 (TearDown),如關閉app或瀏覽器,這時候就須要用到Fixture,使代碼更簡潔。
TestSuite:即測試套件,把須要執行的測試用例集合在一塊兒就是TestSuite。使用TestLoader來加載TestCase到TestSuite中。
TextTestRunner:即測試執行器,用於執行測試用例。該模塊中提供run方法執行TestSuite中的測試用例,並返回測試用例的執行結果,如運行的用例總數、用例經過數、用例失敗數。
report:即測試報告。unittest框架沒有自帶的用於生成測試報告的模塊或接口,須要使用第三方的擴展模塊HTMLTestRunner。
斷言在自動化測試腳本中是很重要的內容,只有設置正確合適的斷言才能獲取正確的測試結果。Unittest框架提供了本身的斷言方法,以下:
斷言方法
|
判斷內容
|
---|---|
assertEqual(a, b) | 判斷 a == b |
assertNotEqual(a, b) | 判斷 a != b |
assertTrue(x) | 判斷 bool(x) is True |
assertFalse(x) | 判斷 bool(x) is False |
assertIs(a, b) | 判斷 a is b |
assertIsNot(a, b) | 判斷 a is not b |
assertIsNone(x) | 判斷 x is None |
assertIsNotNone(x) | 判斷 x is not None |
assertIn(a, b) | 判斷 a in b |
assertNotIn(a, b) | 判斷 a not in b |
assertIsInstance(a, b) | 判斷 isinstance(a, b) |
assertNotIsInstance(a, b) | 判斷 not isinstance(a, b) |
注意:
若是斷言成功則該條測試用例經過,斷言失敗則該條測試用例執行失敗,且會拋出AssertionError錯誤。
以上提供的斷言方法中,都有一個msg參數,默認爲None。若是msg參數有對應的值,則斷言失敗後該msg的值會做爲失敗信息返回,如 assertEqual(a, b, msg="a與b不相等!") 。
測試對象:構造一個類Math,其中包含整數的加、減法運算。
calculator.py
class Math(): def __init__(self, a, b): self.a = int(a) self.b = int(b) def sum(self): '''和''' return self.a + self.b def sub(self): '''差''' return self.a - self.b
測試需求:對Math類進行單元測試。接下來針對這個測試需求,使用unittest框架編寫測試用例。
項目目錄結構:後面的例子中,項目結構以下所示。
在Unittest框架下建立測試用例,步驟以下:
1),導入unittest模塊。
2),建立測試類。測試類的命名不作要求,但須要繼承unittest.TestCase類。
3),添加setUp()、tearDown()函數,即測試固件。固然還有setUpClass()、tearDownClass() 函數,區別後面會有介紹。
4),定義測試方法,即測試用例。測試方法名稱必須以test開頭,不然測試時該方法將不會被執行。測試方法裏須要添加斷言。
5),調試執行測試用例。執行當前模塊的測試用例時,調用unittest.main()方法,該方法會搜索該模塊下全部以test開頭的測試用例方法,並執行。其餘方法後面介紹。
針對測試需求,編寫測試用例。目錄結構以下:
test_sum.py
import unittest from calculator import Math class SumTest(unittest.TestCase): '''測試Math類中的sum函數''' def setUp(self): print("開始執行測試用例{}...".format(self)) def test_sum01(self): m = Math(3, 4) self.assertEqual(m.sum(), 7) def test_sum02(self): m = Math(2, 8) self.assertEqual(m.sum(), 11) def tearDown(self): print("測試用例{}執行結束...".format(self)) if __name__ == '__main__': unittest.main()
運行結果:
.F ====================================================================== FAIL: test_sum02 (__main__.SumTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:/Users/xiaoqq/Desktop/test_project/demo/testSum.py", line 15, in test_sum02 self.assertEqual(m.sum(), 11) AssertionError: 10 != 11 ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) 開始執行測試用例test_sum01 (__main__.SumTest)... 測試用例test_sum01 (__main__.SumTest)執行結束... 開始執行測試用例test_sum02 (__main__.SumTest)... 測試用例test_sum02 (__main__.SumTest)執行結束... Process finished with exit code 0
結果顯示:
test_sum01經過,test_sum02失敗。點"."表示經過,"F"表示失敗。
測試類中每一個測試方法(即測試用例)執行前,都先執行setUp()方法,每一個測試方法執行完畢後都要執行tearDown()方法。
斷言失敗會返回一個AssertionError。
在Unittest框架下的測試用例中,使用Fixture有兩種方法,做用於兩個範圍:
setUp()、tearDown(),做用於測試方法。即測試類下的每一個測試方法執行前先運行setUp(),每一個測試方法執行完畢後都要執行tearDown()方法,如testSum.py示例。
setUpClass()、tearDownClass(),做用於測試類。即只在整個測試類執行開始時運行setUpClass(),測試類下全部測試方法執行完後運行tearDownClass()。
test_sum.py修改以下,運行
class SumTest(unittest.TestCase): '''測試Math類中的sum函數''' @classmethod def setUpClass(cls): print("開始執行測試用例{}...".format(cls)) def test_sum01(self): m = Math(3, 4) self.assertEqual(m.sum(), 7) def test_sum02(self): m = Math(2, 8) self.assertEqual(m.sum(), 11) @classmethod def tearDownClass(cls): print("測試用例{}執行結束...".format(cls)) if __name__ == '__main__': unittest.main()
運行結果:
開始執行測試用例<class '__main__.SumTest'>... 測試用例<class '__main__.SumTest'>執行結束... .F
結果顯示,setUpClass()、tearDownClass() 都只運行了一次。注意,這裏須要使用裝飾器@classmethod
在測試用例中,setUp() 或 setUpClass() 作初始化的工做,不是必須有這個函數。一樣tearDown() 和 tearDownClass() 只作清理的工做,在測試類中不是必需要有。
須要測試的Math類,代碼比較簡單,沒有真正須要用到測試夾具的地方,所以這只是個用法演示。
實際自動化過程當中,如Web端UI自動化,通常會將建立瀏覽器實例放在setUp() ,用例執行完後須要關閉瀏覽器,將關閉瀏覽器操做放在tearDown()方法裏。示例以下:
import unittest from selenium import webdriver class BaiduTest(unittest.TestCase): def setUp(self): '''打開瀏覽器,進入百度頁面''' self.driver = webdriver.Chrome() self.driver.maximize_window() self.driver.get('https://www.baidu.com') def test_01(self): print("操做步驟") def tearDown(self): '''關閉瀏覽器''' self.driver.quit()
在testSum.py模塊中,使用了unittest.main()方法執行當前模塊裏的測試用例。除此以外,Unittest還能夠經過測試套件構造測試用例集,再執行測試用例。構造TestSuite經常使用的方法以下:
1),先經過unittest.TestSuite() 建立測試套件實例對象。
2),再經過addTest() 往測試套件裏添加單個測試用例,或經過addTests([...]) 添加多個測試用例(列表中爲用例方法名)。
3),執行測試套件裏的測試用例
run.py示例:
import unittest # 導入測試用例模塊 from testcase.test_sum import TestDemo # 第一步:建立TestSuite實例 suite = unittest.TestSuite() # 第二步:將測試用例添加至TestSuite # 方式1,添加單條測試用例 suite.addTest(TestDemo('test_sum01')) # addTest()裏參數格式爲:測試類('測試方法') suite.addTest(TestDemo('test_sum02')) # 方式2,添加多條測試用例 suite.addTests([TestDemo('test_sum01'), TestDemo('test_sum02')])
1),先經過unittest.TestSuite() 建立測試套件實例對象。
2),再經過unittest.TestLoader()建立加載對象,加載測試用例類
run.py示例:
import unittest # 導入測試用例模塊 from testcase.test_sum import TestDemo # 建立TestSuite實例 suite = unittest.TestSuite() # 建立一個加載對象 loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(TestDemo))
1),經過unittest.defaultTestLoader.discover()將指定路徑的測試用例加載至測試用例集。注意:這裏不須要建立unittest.TestSuite對象
2),以下代碼所示,test_dir爲指定路徑。pattern=test_*.py 表示加載以test_開頭的模塊中的測試用例,指定運行某模塊時pattern參數指定全名便可,如:pattern='test_sum.py'。路徑跟pattern參數均可以自定義。
run.py示例
import unittest test_dir = './testcase' suite = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
編寫測試項目時,推薦使用方法三。固然還有其餘方法,很少作介紹。
unittest框架執行測試用例以前,需先建立TextTestRunner實例,再調用該實例的run()方法。
# 建立TextTestRunner實例 runner = unittest.TextTestRunner() # 使用run()方法運行測試套件(即運行測試套件中的全部用例) runner.run(suite)
run.py修改爲以下示例:
import unittest test_dir = './testcase' suite = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py') runner = unittest.TextTestRunner() runner.run(suite)
運行run.py,結果以下:
.F ====================================================================== FAIL: test_sum02 (test_sum.TestDemo) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\xiaoqq\Desktop\test_project\demo\test_sum.py", line 15, in test_sum02 self.assertEqual(m.sum(), 11) AssertionError: 10 != 11 ---------------------------------------------------------------------- Ran 2 tests in 0.000s FAILED (failures=1) 開始執行測試用例test_sum01 (test_sum.TestDemo)... 測試用例test_sum01 (test_sum.TestDemo)執行結束... 開始執行測試用例test_sum02 (test_sum.TestDemo)... 測試用例test_sum02 (test_sum.TestDemo)執行結束... Process finished with exit code 0
unittest框架執行測試用例完成後會在控制檯輸出如上的結果,但實際測試過程當中,咱們須要輸出測試報告,這個時候咱們須要使用第三方模塊。
HTMLTestRunner模塊能夠直接生成html格式的報告
下載後須要修改:
存放路徑:將修改完成的模塊存放在Python路徑下Lib目錄裏便可。
run.py示例代碼以下:
# -*- coding:utf-8 -*- # @author: 給你一頁白紙 import time import unittest import HTMLTestRunner # 獲取當前時間並指定時間格式,用於測試報告命名 now = time.strftime("%Y-%m-%d_%H_%M_%S") # 測試報告存儲路徑 report_dir = './report/' # 建立報告文件,並以寫的形式打開文件,用於寫入報告內容 fp = open(report_dir + now + "_report.html", 'wb') # 初始化一個HTMLTestRunner實例對象,用來生成報告 runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title="App自動化測試報告", description="測試用例狀況") # 定義測試用例路徑 test_dir='./testcase' # 加載測試用例 suite = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py') # 執行測試用例 runner.run(suite) fp.close()
運行run.py,會看到report中生成了html文件,即爲測試報告
瀏覽器打開該文件,內容以下:
從報告內容中看出HTMLTestRunner.HTMLTestRunner()方法中參數所對應的內容,能夠根據項目的實際須要指定參數內容。
在HTMLTestRunner基礎上美化過的報告
下載地址: 連接:https://pan.baidu.com/s/1Wd_FXJBu3ATgmCQHkzbGag,提取碼:f6uq
放置在Python安裝路徑的Lib文件夾裏
run.py示例代碼以下:
# -*- coding:utf-8 -*- # @author: 給你一頁白紙 import time import unittest import BSTestRunner # 獲取當前時間並指定時間格式,用於測試報告命名 now = time.strftime("%Y-%m-%d_%H_%M_%S") # 測試報告存儲路徑 report_dir = './report/' # 建立報告文件 fp = open(report_dir + now + "_report.html", 'wb') # 初始化一個HTMLTestRunner實例對象,用來生成報告 runner = BSTestRunner.BSTestRunner(stream=fp, title="App自動化測試報告", description="測試用例狀況") # 定義測試用例路徑 test_dir='./testcase' # 加載測試用例 suite = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py') # 執行測試用例 runner.run(suite) fp.close()
生成報告樣式以下:
兩種報告模板可根據本身喜愛任意選擇。