第一節:斷言與單元測試
斷言
格式:
assert +【條件表達式】
如果表達式成立,則程序能夠正常向下執行,沒有輸出任何內容,否則拋出**AssertionError
**
使用斷言,可以簡易迅速地對流程結果進行測試,預測結果是否相符;
例:
# 待測函數
def add(a, b):
return a + b
# 使用斷言進行測試:
assert add(3, 4) == 7
執行結果:
系統沒有報錯,斷言是正確的,使用add這個函數得到的結果與預期相符
例:
# 待測函數
def add(a, b):
return a * b
# 使用斷言進行測試:
assert add(3, 4) == 7
這時系統拋出了AssertionError,說明斷言是錯誤的,待測函數add的結果於預期並不一致
單元測試
所謂單元,指的是可測試對象的最小單位,通常指一個函數。單元測試只是對工程中的代碼單元(通常細化到每個函數)進行正確性驗證的工作;最常用的測試
對自己寫的模塊和類進行必要的單元測試,保證嚴謹正確,既是良好的開發習慣,也是一種規範;
Python標準庫中單元測試的模塊是unittest
import unittest
測試用例
【要點】
測試用例類必須繼承unittest.TestCase
具體的測試項函數必須以testxxx
來命名
setUp()
方法會在每個測試項執行前調用,如有必要的初始化工作可以通過覆寫該方法來實現
tearDown()
方法會在每個測試項結束後調用,如有善後工作可以通過覆寫該方法來實現
在整個測試用例中,還有兩個類,setUpClass(cls)
和tearDowwnClass(cls)
也會在測試用例的執行前後各調用一次
在具體的測試項函數中,使用TestCase的assertXXX
系列函數預言結果
如果程序執行結果與預測的一致,測該單項測試通過,否則不通過
【幾個常用斷言方法】
assertFalse(self,expr,msg)
—— 斷言正確
assertTrue(self,expr,msg)
—— 斷言錯誤
assertEqual(self,expr,msg)
—— 斷言相等
【注意】
測試與光標有關,當光標在某函數內時,執行的是此函數的測試,當想測試所有,需把光標放在unittest.main()區域
例:
import unittest
# 待測的工具類
class MathUtil:
# a,b相加
def sum(self, a, b):
return a + b
# a,b相減
def sub(self, a, b):
return a - b
# 判斷a是否大於b
def gt(self, a, b):
return a > b
# 測試用例類,必須繼承於unittest.TestCase
class MathUtilTest(unittest.TestCase):
'''MathUtil工具類測試用例'''
# 測試項初始化方法
def setUp(self):
print("MathUtilTest setUp,測試項正在初始化...")
# 創建實例(用於準備數據)
self.mu = MathUtil()
# 測試項結束時調用
def tearDown(self):
del self.mu # 消毀數據
print("MathUtilTest tearDown,測試項已結束")
'''
一系列的測試方法,都必須以testxxx命名
'''
# 測試MathUtil的sum方法
def testSum(self):
print("正在測試Sum方法...")
# 斷言相等
self.assertEqual(self.mu.sum(3, 4), 7,"Sum函數測試失敗!!!")
# 測試MathUtil的sub方法
def testSub(self):
print("正在測試Sub方法...")
# 斷言相等
self.assertEqual(self.mu.sub(3, 4), 1, "Sub函數測試失敗!!!")
# 測試MathUtil的gt方法
def testGt(self):
print("正在測試Others方法...")
# 斷言真假
self.assertTrue(self.mu.gt(5, 4))
self.assertFalse(self.mu.gt(4, 5))
# 斷言拋出異常
with self.assertRaises(TypeError):
self.mu.sum(1, "2")
# 執行單元測試
if __name__ == '__main__':
# 運行當前模塊中的所有測試用例
unittest.main()
正常執行結果:
非正常執行結果:
測試套件
測試套件,用於單獨測試某個方法,而不必整個測式用例進行測試,相對靈活一些
unittest.main()
方法會執行當前模塊中的所有測試用例類中的所有測試項,這顯得不太靈活;
unittest.TestSuite
類是一個測試用例容器,可以按需添加測試用例於其中,使得單元測試既可以批量進行,又可以自主增減測試項目;
例:
import unittest
from unittest.runner import TextTestRunner
# 待測的工具類
class MathUtil:...
# 測試用例類,必須繼承於unittest.TestCase
class MathUtilTest(unittest.TestCase):...
class MathUtilTest2(unittest.TestCase):...
class MathUtilTest2(unittest.TestCase):...
# 執行單元測試
if __name__ == '__main__':
# 運行當前模塊中的所有測試用例
# unittest.main()
# 定義一個測試套件
suite = unittest.TestSuite()
# 往測試套件裏新增用例類下的所有測試項
suite.addTest(unittest.makeSuite(MathUtilTest))
suite.addTest(unittest.makeSuite(MathUtilTest2))
# 執行測試套件
runner = TextTestRunner() # 執行器
ret = runner.run(suite)
print(ret)
第二節:文檔測試與DEBUG
文檔測試
文檔指的就是Python模塊,文檔測試就是對一個py文件進行整體的測試,是一種簡單粗暴的測試方式;
文檔測試中的測試代碼是以註釋的形式
寫在文檔中;
通過標準庫API來觸發文檔測試:doctest.testmod(target_module)
'''
文檔測試腳本
#預測加法的結果
>>> add(3,4)
7
#預測減法的結果
>>> sub(3,4)
-1
#預測冪的結果
>>> power(3,4)
81
'''
# 正確的加法函數
def add(a,b):
return a + b
# 正確的加法函數
def sub(a,b):
return a - b
# 錯誤的冪函數
def power(a,b):
return a ** b - 1
開始對目標模塊進行測試:
#引入文檔測試模塊
import doctest
# 引入要進行測試的目標模塊uut
import uut
if __name__ == '__main__':
#對uut進行文檔測試
doctest.testmod(uut)
測試結果:
DEBUG
【什麼是DEBUG】
DEBUG是指對程序的執行過程進行逐行逐步調試
;
DEBUG時,程序從第一個斷點處進入暫停狀態
,然後根據用戶的指令,一步一步地進行執行,每執行一步,都能夠從控制檯中查看到程序和數據的所有細節;
【主要操作步驟】
在需要中止的地方打斷點;
在IDE中右鍵選擇“Debug XXX”;
按需【下一步(Step Over)】或【進入方法(Step Into) 】直到流程結束;
在分步執行的過程中,可以:
將重點懷疑的變量右擊添加到觀察(Add to watches);
調試過程中人爲修改可疑變量的值(Set Value);
PS:DEBUG是一種效率不高的調試手段,它應用作程序調試的輔助手段而非主要手段;
例: