iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Python

Python探索之旅:從基礎到實踐系列 第 25

DAY 25: 鐵證如山——編寫高效單元測試與極致除錯技巧

  • 分享至 

  • xImage
  •  

在開發過程中,編寫測試與調試應用程序是保障軟體穩定性和減少錯誤的關鍵步驟。透過編寫單元測試來驗證程式碼的正確性,並掌握除錯技巧,可以有效降低應用出現問題的風險,並加快開發迭代速度。


一、單元測試的意義與重要性

單元測試是一種用來測試程式中最小可測單位(通常是函數或方法)的技術。透過單元測試,我們能夠確保每個單元功能按預期運行,並在開發過程中快速檢測錯誤,以下是其重要性:

  1. 增強可靠性:每個單元的測試確保了基礎功能的準確性,降低了程式運行中的不確定性。
  2. 提升開發效率:當程式碼出現問題時,單元測試能快速定位錯誤所在,從而節省時間。
  3. 減少回歸錯誤:透過持續測試,能夠避免在更新或修改程式碼時引入新的錯誤。
  4. 幫助重構:測試幫助開發者有信心進行重構,確保不會破壞原有功能。

二、使用 unittest 編寫單元測試

Python 的 unittest 模組是內建的單元測試框架,能讓開發者方便地編寫、執行測試。以下是基本的測試步驟和範例:

  1. 編寫一個簡單函數

    首先,我們來編寫一個簡單的函數,作為單元測試的對象:

    # math_operations.py
    def add(a, b):
        return a + b
    
    def subtract(a, b):
        return a - b
    
  2. 編寫測試案例

    使用 unittest 來編寫測試案例:

    # test_math_operations.py
    import unittest
    from math_operations import add, subtract
    
    class TestMathOperations(unittest.TestCase):
        def test_add(self):
            self.assertEqual(add(2, 3), 5)
            self.assertEqual(add(-1, 1), 0)
    
        def test_subtract(self):
            self.assertEqual(subtract(5, 3), 2)
            self.assertEqual(subtract(0, 1), -1)
    
    if __name__ == '__main__':
        unittest.main()
    
  3. 執行測試

    在終端中運行測試文件,確認結果:

    python test_math_operations.py
    

    如果測試成功,會返回:

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.001s
    
    OK
    
  4. 測試失敗的處理

    當測試未通過時,會返回詳細的錯誤信息,便於快速定位問題:

    AssertionError: 5 != 6
    

三、進階測試技巧

  1. 測試邊界條件

    測試邊界條件(如最大值、最小值、空值等)是非常重要的,確保程式能正確處理特殊情況:

    def test_add_boundary(self):
        self.assertEqual(add(0, 0), 0)
        self.assertEqual(add(-1, -1), -2)
    
  2. 測試異常處理

    測試應用程式的異常處理能力也是單元測試的重要部分。可以使用 assertRaises 來檢查是否正確拋出預期的異常:

    def test_add_type_error(self):
        with self.assertRaises(TypeError):
            add('a', 1)
    

四、除錯技巧

即便寫了測試,仍然可能會遇到錯誤。學習如何高效除錯是每位開發者的必修課。以下是一些常見的除錯工具與技巧:

  1. 使用 print() 進行基礎除錯

    將變量值打印出來是最簡單的除錯方式。雖然不夠精細,但在簡單場景下依然有效。

    def add(a, b):
        print(f"Adding {a} and {b}")
        return a + b
    
  2. 使用 pdb 進行斷點除錯

    Python 的內建調試器 pdb 提供了更強大的除錯能力。通過設置斷點,可以逐步跟蹤程式的執行流程:

    import pdb
    
    def add(a, b):
        pdb.set_trace()  # 設置斷點
        return a + b
    

    執行程式時會暫停在斷點處,你可以使用 n(next)、c(continue)、q(quit)等命令來進行調試。

  3. 使用 VS Code 內建除錯工具

    在 Visual Studio Code 中,直接利用其內建的除錯功能更加直觀且高效。你可以在程式碼中直接設置斷點,並運行除錯模式。其圖形化界面讓你可以方便地檢視變量值、執行步驟以及堆疊信息。

  4. 分析堆疊跟蹤

    當出現異常時,Python 會打印出錯誤的堆疊信息(stack trace)。分析這些信息能幫助快速定位問題:

    Traceback (most recent call last):
      File "math_operations.py", line 5, in add
        return a / b  # division by zero
    ZeroDivisionError: division by zero
    
  5. 日誌記錄(Logging)

    使用 logging 模組來記錄程式運行中的重要事件。相比 print(),日誌可以更靈活地控制輸出等級(DEBUG、INFO、WARNING、ERROR 等):

    import logging
    logging.basicConfig(level=logging.INFO)
    
    def add(a, b):
        logging.info(f"Adding {a} and {b}")
        return a + b
    

五、測試自動化

當專案變得越來越大,手動測試效率低下且容易出錯。這時候,可以引入測試自動化工具,例如:

  1. 使用 pytest 進行更靈活的測試

    相比 unittestpytest 提供了更加簡潔的語法和豐富的功能。例如,它能夠自動發現測試文件和函數,並支持多種插件擴展。

    安裝並使用 pytest

    pip install pytest
    pytest
    
  2. 持續整合(CI)工具

    使用 CI 工具(如 GitHub Actions、Travis CI)來自動運行測試。在每次推送程式碼時,系統會自動執行測試,確保所有新更改不會引發問題。


六、測試與調試最佳實踐

  1. 從一開始就編寫測試:不要等到程式碼完成後才編寫測試,應該在開發過程中同時進行測試編寫。
  2. 保持測試簡單可讀:測試應該簡單明了,易於理解和維護。
  3. 測試失敗是正常的:不要害怕測試失敗,失敗能幫助你找到問題並改善程式。
  4. 快速定位問題:通過斷點、日誌、堆疊信息等方法快速縮小問題範圍。
  5. 持續運行測試:在每次代碼變更後,都應該運行測試,確保沒有引入新錯誤。

結語

編寫單元測試和學習除錯技巧是成為一名優秀開發者的重要基礎技能。通過這些工具和方法,開發者可以更快地發現和修正問題,提升應用的質量和穩定性。隨著測試的自動化,開發過程變得更加高效,也為後續的大規模應用開發奠定了堅實的基礎。


上一篇
DAY 24: Django 部署巔峰——無縫上線至 Heroku 與多平台攻略
下一篇
DAY 26: 全面出擊——開始進行完整專案實作
系列文
Python探索之旅:從基礎到實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言