單元測試詳解

🍅 點擊文末小卡片,免費獲取軟件測試全套資料,資料在手,漲薪更快

對于軟件測試,我們先按照開發階段來進行劃分,將軟件測試分為單元測試、集成測試、系統測試、驗收測試,下面我們來聊聊單元測試。

1、什么是單元測試?

在正式闡述什么是單元測試之前,我先給大家分享一個工廠組裝手機的例子。

手機組裝流水線按照圖紙將各個電子元件組裝焊接為各個模塊組件(如喇叭,聽筒,麥克,FPC,按鍵板,攝像頭,LCD等),再將各個模塊組件組裝成一部完整的手機。

如果一起順利,在給手機安裝系統后就可以正常使用了。但是很不幸,大多數情況下的手機是無法使用的,那么就需要將已經組裝好的手機重新拆機,逐個模塊排查問題,在每個模塊排查中需要對每個電子元件進行檢測,通過花費大量的時間和精力才能定位到問題原因。

那么在后續的生產中,如何才能避免這種問題的發生呢?

你可能立即就會想到,為什么不在組裝焊接前,就先測試每個要用到的電子元器件呢?這樣你就可以先排除有問題的元器件,最大程度地防止組裝完成后逐級排查問題的事情發生。

實踐也證明,這的確是一個行之有效的好辦法。

如果把手機的生產、測試和軟件的開發、測試進行類比,你可以發現:

  • 電子元器件就像是軟件中的單元,通常是函數或者類,對單個元器件的測試就像是軟件測試中的單元測試;
  • 組裝完成的功能模塊組件如喇叭,聽筒,麥克,FPC,按鍵板,攝像頭,LCD等就像是軟件中的模塊,對功能模塊組件的測試就像是軟件中的集成測試;
  • 手機全部組裝并安裝系統就像是軟件完成了預發布版本,手機全部組裝并安裝系統完成后的開機測試就像是軟件中的系統測試;

通過這個類比,相信你已經體會到了單元測試對于軟件整體質量的重要性,那么單元測試到底是什么呢?

單元測試是指,對軟件中的最小可測試單元在與程序其他部分相隔離的情況下進行檢查和驗證的工作,這里的最小可測試單元通常是指函數或者類。

2、什么是好的單元測試?

好的單元測試應當包含四種特性:正確,清晰,完整,健壯

  • 正確:單元測試是最基礎的要求,必須要保證所寫的函數或者類實現的功能是正確的,如果實現的功能都不能滿足,那就是缺陷!
  • 清晰:單元測試可以幫助其他開發理解函數或者類的實現,所以要求單元測試用例簡潔、清晰,需要有良好的可讀性
  • 完整:單元測試需要考慮輸入與輸出組合的各種場景,保證單元測試的覆蓋率
  • 健壯:健壯性是最容易被忽略的一項,當被測試的類或者函數被修改內部實現或者添加功能時,一個好的單測應該完全不需要被修改或者只有極少的修改。比如?個排序函數的單測實現是完全穩定的,它不應該跟著不同的排序算法的變化

3、怎么寫單元測試?

可能大多數的測試人員不會接觸到單元測試的編寫,因為按照我個人的看法,開發人員根據自己寫的代碼編寫單測用例是最合適不過的,也是最高效的。

雖然我們不需要實際去編寫單測用例,但是我們還是需要了解怎么寫單元測試。

單元測試的代碼結構一般包含三部分:分別是準備、調用與斷言

  • 準備:準備部分的?的是準備好調?所需要的外部環境,如數據,Stub(樁代碼),Mock,臨時變量,調?請求,環境背景變量等等。
  • 調用:調?部分則是實際調?需要測試?法,即函數或者流程本身。
  • 斷言:斷?部分判斷調?部分的返回結果是否符合預期。

每個單元測試都應該能清晰地分出這三部分,當然有時調?斷?兩部分合在?起也是?較常見的。

4、玩轉單元測試

下面我們來聊聊單元測試編寫用例的相關知識,首先我們需要了解單元測試的三個重要部分,即驅動程序、樁程序、Mock

驅動程序:驅動程序(Driver)也稱作驅動模塊,用以模擬被測模塊的上級模塊,能夠調用被測模塊。在測試過程中,驅動模塊接收測試數據,調用被測模塊并把相關的數據傳送給被測模塊。

簡單說就是你負責測試的模塊沒有main()方法入口,所以需要寫一個帶main的方法來調用你的模塊或方法。這個就是驅動測試

樁程序:樁程序(Stub),也稱樁模塊,用以模擬被測模塊工作過程中所調用的下層模塊,即被測模塊本身調用的其他關聯函數。樁模塊由被測模塊調用,它們一般只進行很少的數據處理。

樁是指用來代替關聯代碼或者未實現的代碼,為了讓測試對象可以正常的執行,其實一般會硬編碼一些輸入和輸出,保證被測模塊能夠正常運行

Mock:Mock除了保證Stub的功能之外,還可深入的模擬對象之間的交互方式,如:調用了幾次、在某種情況下是否會拋出異常以及提供數據斷言

接下來我們通過一個實例來學習單元測試用例的編寫

# 待測試的方法
def calculator(type):# 調用樁代碼獲取數據num1 = __stub1()num2 = __stub2()# 調用mockmock_data = __mock_check()# +if type.lower() == 'add':type = 'add'ret = num1+num2assert ret == mock_data[type]print('{} + {} = {}'.format(num1,num2,ret))return ret# -if type.lower() == 'minus':type = 'minus'ret = num1-num2assert ret == mock_data[type]print('{} - {} = {}'.format(num1,num2,ret))return ret# *if type.lower() == 'multiply':type = 'multiply'ret = num1*num2assert ret == mock_data[type]print('{} * {} = {}'.format(num1,num2,ret))return ret# /if type.lower() == 'divide':type = 'divide'if num2 == 0:print('除法分母不能為0')return '除法分母不能為0'else:ret = num1/num2assert ret == mock_data[type]print('{} / {} = {}'.format(num1,num2,ret))return ret# 樁代碼1
def __stub1():output = 20print('my stub的值是{}'.format(output))return output# 樁代碼2
def __stub2():output = 5print('my stub的值是{}'.format(output))return output# Mock代碼 => 提供斷言數據
def __mock_check():mock_result = {}mock_result['add'] = 25mock_result['minus'] = 15mock_result['multiply'] = 100mock_result['divide'] = 4return mock_result# 驅動程序
if __name__=="__main__":print(calculator('add'))print(calculator('minus'))print(calculator('multiply'))print(calculator('divide'))

上面提供的是一個簡單的單元測試,包含了驅動程序、被測對象、樁程序以及Mock代碼

  • 驅動程序__main__作為被測對象的上級模塊,運行時調用被測函數calculator
  • 被測函數calculator被調用后,通過樁代碼__stub1、__stub2提供測試數據
  • 被測函數calculator通過不同的入參匹配不同的場景,不同場景獲取的結果與Mock函數__mock_check進行比對斷言,校驗結果是否符合預期

被測函數成功返回如下:

my stub的值是20
my stub的值是5
20 + 5 = 25
25

被測函數失敗返回如下:

my stub的值是20
Traceback (most recent call last):
my stub的值是5File "/Users/Desktop/demo/unittest_demo/ut_demo.py", line 73, in <module>print(calculator('add'))File "/Users/Desktop/demo/unittest_demo/ut_demo.py", line 21, in calculatorassert ret == mock_data[type]
AssertionError

最后感謝每一個認真閱讀我文章的人,禮尚往來總是要有的,雖然不是什么很值錢的東西,如果你用得到的話可以直接拿走:

這些資料,對于做【軟件測試】的朋友來說應該是最全面最完整的備戰倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!凡事要趁早,特別是技術行業,一定要提升技術功底。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86371.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86371.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86371.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

四款好用的Windows虛擬打印機,文檔轉PDF

1&#xff0c;Microsoft Print To PDF 2&#xff0c;Foxit Reader PDF Printer 3&#xff0c;Adobe PDF 4&#xff0c;clawPDF 參考文檔&#xff1a; https://mp.weixin.qq.com/s/_mt4J2RwhqQE36DRAvc-Rg

《map和set的使用介紹》

引言&#xff1a; 上次我們學習了第一個高階數據結構—二叉搜索樹&#xff0c;趁熱打鐵&#xff0c;今天我們就再來學習兩個數據結構—map和set。 一&#xff1a;序列式容器和關聯式容器 前面我們已經接觸過STL中的部分容器如&#xff1a;string、vector、list、deque、arra…

PostgreSQL(二十六)分區表管理

目錄 一、分區表特點 1、概念&#xff1a; 2、好處&#xff1a; 3、特點&#xff1a; 二、范圍分區介紹 1、簡介 2、范圍分區實驗&#xff1a; 三、list分區介紹 1、簡介 2、list分區表實驗 四、hash分區介紹 1、簡介 2、hash分區表實驗 五、混合分區介紹 1、簡…

概率論中的生日問題,違背直覺?如何計算? 以及從人性金融的角度分析如何違背直覺的?

一、生日問題的概率計算&#xff1a;為何23人就有50%概率撞生日&#xff1f; 1. 問題背景與直覺矛盾 生日問題指&#xff1a;在n個人中&#xff0c;至少有兩人生日相同的概率超過50%時&#xff0c;n的最小值是多少&#xff1f; 直覺判斷&#xff1a;因一年有365天&#xff0c…

Qt for WebAssembly官方說明文檔

鏈接 Qt for WebAssembly | Qt 5.15

前端自主實現將vue頁面轉為pdf文件下載

1.vue 轉 PDF 在 Vue 項目中將 HTML 頁面轉換為 PDF 文件是一個常見需求&#xff0c;特別是在需要生成報告或打印頁面時。本文將介紹如何使用 html2canvas 和 jspdf 庫實現這一功能。 2.安裝依賴 首先&#xff0c;我們需要安裝兩個庫&#xff1a;html2canvas 和 jspdf 。可以…

TCP 堅持定時器詳解:原理、配置與最佳實踐?

一、TCP 堅持定時器基礎原理 1.1 堅持定時器的設計目的 TCP 堅持定時器 (TCP Persist Timer) 是 TCP 協議中用于處理接收窗口為零情況的重要機制&#xff0c;其核心設計目的是防止 TCP 連接在窗口更新 ACK 丟失時陷入死鎖狀態。當 TCP 連接的接收方通告一個窗口大小為 0 的 A…

大廠測開實習和小廠開發實習怎么選

先說選擇&#xff0c;這個可以百分百確定選大廠&#xff0c;title很重要。 要想弄清楚那個選擇對自己最有利&#xff0c;可以思考下實習的意義是什么&#xff1f; 實習無非就是給簡歷加分&#xff0c;拿到好offer&#xff0c;高薪offer。 那這就需要思考&#xff0c;簡歷怎么讓…

Unity中的urp和普通的標準渲染管線區別在哪

Unity中的URP&#xff08;Universal Render Pipeline&#xff09;與內置標準渲染管線&#xff08;Built-in Render Pipeline&#xff09;的區別深刻反映了Unity渲染技術的演進方向。以下從架構、性能、功能、工作流等多個維度進行深度分析&#xff1a; 1. 底層架構與設計哲學 標…

Vscode 編寫Markdown支持 plantuml書寫

1&#xff1a; 下載PlantUml 插件&#xff1a; 2&#xff1a; 安裝java https://www.oracle.com/java/technologies/downloads/ 3&#xff1a; 安裝Graphviz https://graphviz.org/download/ 4&#xff1a; 下載plantuml.jar https://plantuml.com/zh/download 5&…

設計模式(C++/Qt)-工廠模式

在軟件開發中&#xff0c;對象創建是基礎但關鍵的任務——工廠模式提供了一種優雅的解決方案&#xff0c;讓您的代碼擺脫硬編碼的依賴關系 一、為什么需要工廠模式&#xff1f; 在C/Qt開發中&#xff0c;我們經常面臨這樣的困境&#xff1a; 對象創建邏輯分散在代碼各處新增…

Pydantic 模型

本文將詳細介紹 Pydantic 模型 和 BaseModel 的核心概念&#xff0c;并通過實際代碼示例如何從零開始編寫自己的 Pydantic 模型。 1. Pydantic 是什么&#xff1f; Pydantic 是一個 Python 庫&#xff0c;主要用于&#xff1a; 數據驗證&#xff1a;確保輸入數據符合預期的類…

【Unity智能模型系列】MediaPipeUnityPlugin 實現人臉數據獲取

目錄 一、MediaPipeUnity 簡介 二、MediaPipeUnity 的核心組成 1. Graph 構建系統 2. 解決方案類(Solution) 3. 解釋注釋Annotation 系統 三、MediaPipeUnity 的典型使用流程 四、典型示例解析 1、案例 Face Detection圖形人臉檢測 2、案例 Face Detection圖形人臉檢…

iOS App 上架步驟解析:適合資源有限團隊的上架流程與注意事項

對于不少創業型或初創階段的開發團隊來說&#xff0c;人員配置緊湊、設備有限是常態。在這種背景下&#xff0c;完成一次合規、高效的iOS應用發布往往不是技術難點&#xff0c;而是流程協同與資源調配的問題。 我們是一支5人團隊&#xff0c;開發一款社交類工具型App&#xff…

Redis雪崩、穿透、擊穿原理及解決方案

以下是 Redis 緩存穿透、擊穿與雪崩的原理及解決方案的深度解析&#xff0c;結合工業級實踐整理&#xff1a; &#x1f50d; ?一、問題原理與區別? ?問題類型??觸發條件??核心特征??危害??緩存穿透?查詢?不存在的數據?繞過緩存直擊數據庫&#xff0c;導致無效查…

DFX 動態重構的概念和實現

DFX 動態重構的概念和實現 背景介紹 本文內容當前僅限于XILINX或者和XILINX具有相同結構的FPGA器件。 FPGA 技術提供了在現場進行編程和重新編程的靈活性&#xff0c;而無需通過重新制造流程來實現設計修改。動態功能交換&#xff08;Dynamic Function eXchange, DFX&#x…

hutool 導出數據報錯:org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException

Excel 導出報錯 org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Fail to save: an error occurs while saving the package : The part /docProps/core.xml failed to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marsh…

【學習】win 本地部署qwen3

這里寫自定義目錄標題 環境搭建下載Ollama安裝olama修改模型下載位置&#xff08;可以不設置&#xff09;通過ollama下載/啟動模型常用命令其他 環境搭建 下載Ollama 安裝olama 默認安裝位置是c盤 安裝到指定位置使用以下命令 OllamaSetup.exe /DIR"d:\Ollama"修改…

python的__init__.py

在此之前先確認一個概念是否弄清 模塊命名空間 1. 目錄結構 假設你有以下結構&#xff1a; testpkg/__init__.pyfool.pymaybe.py內容如下&#xff1a; fool.py # testpkg/fool.py class Fool:passmaybe.py # testpkg/maybe.py class Maybe:pass__init__.py &#xff08…

四核 A53+工業級存儲:移遠 SC200L 與 pSLC SD NAND 如何重構 T-BOX 性能邊界?

博客目錄 一、移遠 SC200L&#xff1a;T-BOX 的 “智慧大腦”二、米客方德 MKDN064GIL-ZA T-BOX&#xff1a;數據安全的堅固堡壘三、深度協同&#xff1a;拓展 T-BOX 應用邊界 在車聯網浪潮席卷而來的當下&#xff0c;T-BOX 作為汽車與外界交互的核心樞紐&#xff0c;其性能優劣…