第九章:調試與測試

第一節:斷言與單元測試

斷言

格式: 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)

例:有一個待測試的模塊uut.py

'''
文檔測試腳本

#預測加法的結果
>>> 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是一種效率不高的調試手段,它應用作程序調試的輔助手段而非主要手段;

例:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章