Python單元測試淺析

来源:https://www.cnblogs.com/mysticbinary/archive/2019/12/25/12099481.html
-Advertisement-
Play Games

測試的意義 人們針對一個具體問題,通過分析和設計,最後用編程語言寫出了一個程式,如果它通過了語言解釋器(編譯器)的檢查,可以運行了,那麼下一步的工作就是設法確認它確實滿足了我們需求。這篇文章就是討論怎麼確認程式是否滿足用戶提出的需求。 滿足需求,換言之就是功能正常,確認功能正常可以從以下幾個方面確認 ...


測試的意義

  人們針對一個具體問題,通過分析和設計,最後用編程語言寫出了一個程式,如果它通過了語言解釋器(編譯器)的檢查,可以運行了,那麼下一步的工作就是設法確認它確實滿足了我們需求。這篇文章就是討論怎麼確認程式是否滿足用戶提出的需求。

滿足需求,換言之就是功能正常,確認功能正常可以從以下幾個方面確認:

  • 定義的函數對於所有正確的參數都能返回正確的結果
  • 寫出的程式對所有合適的輸入都能產生正確的輸出

  量化後的做法就是通過一系列的試運行,檢查程式的行為、輸入和輸出,如果檢查中發現了問題,就糾正、改進。這個也是功能測試和安全測試的初衷。

測試用例

  測試考慮的基本問題就是怎麼運行程式,需要提供什麼數據,才能最大限度的檢查程式的各種行為和情況,最大可能的挖出程式中的錯誤和缺陷。基於設計什麼測試流程、提供什麼參數這種檢查程式運行的一套數據被稱為一個測試用例。一個測試用例就是可量化的測試流程。

確認測試用例又區分兩類方式:

  • 黑盒測試
    就是不看代碼,直接上手程式的使用測試。這裡不討論黑盒

  • 白盒測試
    白盒測試的基礎是看程式的內部結構(代碼)和可能產生的執行路徑,根據內部結構來選擇測試的用例,使程式在試驗性運行中就能表示出儘可能多的不同行為。這個做法的基本理念就是:如果所有可能執行的路徑(順序、條件、while、for、嵌套...執行結構)都能給出正確的結果,那麼程式的正確性就能得到保證。


測試函數功能案例

  各類的語言都會提供單元測試的庫,Python也不例外,python一般使用PyUnit(unittest)庫,unittest是Python自帶的單元測試框架,用於編寫和運行可重覆的測試,下麵介紹怎麼用unittest來測試函數的用法,我這裡只是簡單用了幾個測試方法,更多測試方法請查閱官網(https://docs.python.org/3/library/unittest.html)。

3個需要測試的函數:

def mysum(a, b):
    return a + b

def mysubtraction(a, b):
    return a - b

def is_evenNumbers(x):
    if (x % 2) == 0:
        return True
    else:
        return False

測試函數的方法:

import unittest
import testbox.mymath as mymath


class Test(unittest.TestCase):
    def setUp(self):
        print("The unit test function start.")

    def test_mysum(self):
        self.assertEqual(mymath.mysum(1, 2), 3, "mysum function have error!")

    def test_mysubtraction(self):
        self.assertEqual(mymath.mysubtraction(2, 1), 1, "mysubtraction function have error!")

    def test_is_evenNumbers(self):
        self.assertTrue(mymath.is_evenNumbers(2), "error")

    def test_is_evenNumbers2(self):
        self.assertFalse(mymath.is_evenNumbers(3), "error")

    def tearDown(self):
        print("The unit test end.")

if __name__ == '__main__':
    unittest.main()

輸出:

Testing started at 12:26 PM ...
The unit test function start.
The unit test end.
The unit test function start.
The unit test end.
The unit test function start.
The unit test end.
The unit test function start.
The unit test end.

assert關鍵字的用法

  功能其實和上面測試函數用法是一樣的,只不過assert可以直接使用在代碼里。這個關鍵字也比較生僻,也沒見什麼場景需要用它,也就這裡為了做個案例,我才用它寫了個demo。

def testasserts(a):
    assert a == 2, Exception("parameter a not is 2, so have a error.")
    if a == 2:
        print("function run.")
    print("OK. function end.")

if __name__ == '__main__':
    testasserts(1)
    print("Program is end.")

輸出:

Traceback (most recent call last):
  File "/Users/Mysticbinary/Document/code/personage/python/TestPython1/testbox/testadd.py", line 9, in <module>
    testasserts(1)
  File "/Users/Mysticbinary/Document/code/personage/python/TestPython1/testbox/testadd.py", line 2, in testasserts
    assert a == 2, Exception("parameter a not is 2, so have a error.")
AssertionError: parameter a not is 2, so have a error.


測試類功能案例

  類功能的測試和函數測試一樣,只不過有一個竅門就是,測試、使用類的時候都需要先實例化類,而實例化類的操作,都可以放在setUp()裡面操作。

需要測試的類:

class Library:
    allBook = ["php", "java"]

    def __init__(self):
        print("Library class create completion.")

    def savebook(self, bookname):
        self.allBook.append(bookname);
        return self.allBook

    def showbook(self):
        print(self.allBook)
        return self.allBook

測試類的方法:

import unittest
import testbox.myclass as myc

class TestClass(unittest.TestCase):
    def setUp(self):
        print("The unit test class start.")
        self.library = myc.Library()
        self.newbook = "python"

    def test_savebook(self):
        self.assertIn(self.newbook, self.library.savebook(self.newbook), "errow 1")

    def test_showbook(self):
        self.assertIn(self.newbook, self.library.showbook(), "errow 2")

    def tearDown(self):
        print("The unit test end.")

if __name__ == '__main__':
    unittest.main()

輸出:

Testing started at 12:31 PM ...
The unit test class start.
Library class create completion.
The unit test end.
The unit test class start.
Library class create completion.
['php', 'java', 'python']
The unit test end.


安全測試案例-簡訊轟炸

  我前面說過,功能測試和安全測試都有同樣的初衷,但是具體的測試手法兩者不太一樣,但是一些特定的場景下,使用單元測試的方法,也是能測試一些安全問題的,比如說測介面越權、簡訊介面重覆導致的簡訊轟炸問題等。我這裡只是拋磚引玉一下通過單元測試的手法來做安全測試的例子,但為做深入研究。

def send_message(phone):
    keys = phones_dict.keys()
    if phone not in keys:
        phones_dict[phone] = 0
    else:
        if phones_dict[phone] < 10:
            # 執行發簡訊的流程
            phones_dict[phone] = (phones_dict[phone] + 1)
            print("已經發送了{}次簡訊".format(phones_dict[phone]))
            return "success"
        else:
            print("抱歉,該{}手機號 已經達到今天發簡訊的上限,請明天再來。".format(phone))
            return "error"

測試發簡訊函數安全的測試用例:

    def test_send_message(self):
        result = list()
        for i in range(0, 11):
            result.append(sms.send_message("13193388105"))
        print(result)
        self.assertNotIn("error", result, "send_message have error.")

輸出:

Testing started at 9:48 PM ...
The unit test function start.
已經發送了1次簡訊
已經發送了2次簡訊
已經發送了3次簡訊
已經發送了4次簡訊
已經發送了5次簡訊
已經發送了6次簡訊
已經發送了7次簡訊
已經發送了8次簡訊
已經發送了9次簡訊
已經發送了10次簡訊
[None, 'success', 'success', 'success', 'success', 'success', 'success', 'success', 'success', 'success', 'success']
The unit test end.


__main__全局變數解釋

  除了單元測試,設置模塊的運行入口(main)也是一種測試方式,就是針對每個模塊單獨的調用裡面的函數。__main__其實是一個全局變數,解釋器發現如果該模塊是被導入的,那麼__main__就會被賦值為這個模塊的名字,如果這個模塊是作為主模塊啟動時,那麼解釋器就會給__main__賦值為“main”字元串。


總結

  1. 建議不要在程式上線的時候還帶著assert、print之類的調試語句、避免信息泄露。
  2. 單元測試不單隻用於功能測試,也可以用在一些特定的安全測試里(具體範圍有那些,我沒有研究,如果有需求的話,我可能繼續深入研究)。
  3. unittest的斷言非常簡單易用,基本看一眼就能懂,但是懂斷言的用法,不代表你就會寫測試用例,能看到程式代碼的執行結構才是寫出測試的關鍵所在。一句話就是:寫斷言易,看代碼不易。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Vue.js 入門:從零開始做一個極簡 To Do 應用 寫作時間:2019 12 10版本信息:Vue.js 2.6.10官網文檔: "https://cn.vuejs.org/" 前言 學習 Vue 的最佳方式之一是「請立刻查閱 Vue.js 的 "官方文檔" 」,簡單看一下「基礎」部分,配合本 ...
  • CISC的英文全稱為“Complex Instruction Set Computer”,即“複雜指令系統電腦”,從電腦誕生以來,人們一直沿用CISC指令集方式。早期的桌面軟體是按CISC設計的,並一直沿續到現在。目前,桌面電腦流行的x86體繫結構即使用CISC。微處理器(CPU)廠商一直在走 ...
  • 微服務是當下最流行的應用架構技術了,它跟容器服務、DevOps合稱雲時代的三劍客,可以幫我們化解業務發展過快導致的產品迭代壓力,讓我們可以自由選擇最適合團隊的技術棧,讓系統能夠承載互聯網海量用戶的訪問,讓我們可以更加輕鬆地運維大型的互聯網系統。近些年在廠商、社區和用戶等各方努力推動下,微服務相關的理... ...
  • 一、手動拋出異常1.自定義無效名字異常: (1)編譯時異常,直接繼承Exception (2)運行時異常,直接繼承RuntimeException 舉例子:註意點:throws會向上拋出異常,跑到最上面的話,也就是到了main主方法了,就不要再拋了,使用try...catch....列印出來吧,當然 ...
  • 0.關於 動態規劃 是編程解題的一種重要手段。 年美國數學家 等人,根據一類多階段問題的特點,把多階段決策問題變換為一系列互相聯繫的單階段問題,然後逐個加以解決。與此同時,他提出瞭解決這類問題的“最優化原理”,從而創建瞭解決最優化問題的一種新方法: 動態規劃 。 動態規划算法 通常用於求解具有 某種 ...
  • GC 中文直譯垃圾回收,是一種回收記憶體空間避免記憶體泄漏的機制。 ...
  • 轉載清註明原文地址,謝謝。 OS:Windows 10 第一步,從Python官方下載安裝包 Windows端下載地址:https://www.python.org/downloads/windows/ Win端64位3.8.0安裝包:https://www.python.org/ftp/pytho ...
  • 磁力搜索嗅探器裝成BT ague-dht ague-dht 是一個磁力鏈接嗅探器,它偽裝成BT下載客服端,加入DHT網路,嗅探磁力鏈接.每秒發送1000條請求時,平均3秒收到1次帶有infohash的announce_peer請求;10次get_peer請求. 環境要求 需要JDK11,MAVEN3 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...