在inputParser章節中,我們通過不斷改進getArea函數對輸入參數的處理方法,引入這樣一個觀點:一個可靠的科學工程計算項目必須有一套測試系統,才能防止開發的過程中算法退化,工程項目的推進必須在算法開發和算法測試之間不斷迭代完。在inputParser章節的最后,還根據直覺提出了一個測試系統所應該有的基本功能。在本章中,我們將學習MATLAB提供的測試解決方案:MATLAB單元測試(MATLAB Unit Test)。
基于函數的(Function-Based)單元測試的構造
MATLAB基于函數的單元測試構造很簡單,如圖1所示:用戶通過一個主測試函數和若干局部測試函數(也叫做測試點,Local Function)來組織各個測試。而測試的運行則交給MATLAB的單元測試架構(以下簡稱Framework)去完成。
圖1 單元測試Framework和測試函數
主測試函數和局部測試函數看上去和普通的MATLAB函數沒有區別,其結構如圖2所示,只是命名上有一些規定而已,這些特殊的規定是為了Framework可以和測試函數契合而規定的。
圖2 簡單的主測試函數和若干局部的測試函數構成的一個單元測試
命名規則如下:
主函數的名稱由用戶任意指定,和其他的MATLAB函數文件一樣,該文件的名稱需要和函數的名稱的相同(如果主函數的名稱是testmainfunc,該文件名稱則是testmainfunc.m)
在主函數中,必須調用一個叫做functiontests的函數,搜集該函數中的所有局部函數,產生一個包含這些局部函數的函數局部的測試矩陣并返回給Framework
如下所示:
其中localfunctions是一個MATLAB函數,用來返回所有局部函數的函數句柄。局部函數的命名必須以test開頭,局部函數只接受一個輸入參數,即測試對象,即下面例子中的形參testCase:
其中testCase由單元測試Framework提供,即Framework將自動的調用該函數,并且提供testCase參數。按照規定,要運行單元測試中的所有測試,必須調用runtests函數:
下面用我們用基于函數的單元測試來給getArea函數的構造其單元測試。
getArea函數的單元測試:版本 I
首先給主測試文件起個名字叫做testGetArea,該名字是任意的,為了便于理解名字里面通常包含test,并包含要測試的主要函數的名字:
在該主函數中,localfunctions將搜集所有的局部函數,構造函數句柄數組并返回測試矩陣。這里自然會有一個問題,這個tests句柄數組將返回給誰,這就要了解Framework是如何和測試相互作用的。如圖3所示,整個測試從runtests('testmainfunc.m')命令開始, 命令函數,Framework將首先調用testGetArea的主函數,得到所有的局部函數的函數句柄,如空心箭頭線段所示,然后Framework再負責調用每一個測試局部函數,并且把testCase當做參數提供給每個局部函數,如虛線線段所示。我們可以把Framework想象成一個流水線,用戶只需要通過runtests('testmainfunc.m')把“testmainfunc.m”放到流水線上并且“打開開關”就可以了。它是MATLAB的類matlab.unittest.FunctionTestCase的對象。
圖3 單元測試Framework和測試函數的相互作用
返回的testCase是類matlab.unittest.FunctionTestCase的對象,有很多成員驗證方法可以提供給用戶調用,我們的第一版的getArea函數如下, 要求函數接受兩個參數,并且都是數值類型:
我們先給這個getArea寫第一個測試點,確保測試getArea函數在接受兩個參數的時候,能給出正確的答案:
我們給testGetArea.m添加一個局部函數叫做testTwoInputs,按照規定,該局部函數的名字要以test開頭,后面的名字要能夠盡量反應該測試點的實際測試的內容。verifyTrue是一個testCase對象所支持的方法,它用來驗證其第一個參數,作為一個表達式,是否為真。verifyTrue的第二個參數接受字符串,在測試失敗時提供診斷提示。一個很常見的問題是:getArea是一個極其簡單的函數,內部的工作就是把兩個輸入相乘,在這里驗證getArea(10,22) == 220真的有必要嗎?請讀者記住這個問題,它是理解單元測試的精要之一。下面我們來運行這個測試:
測試返回一個matlab.unittest.TestResult對象,其中包括運行測試的結果,不出意料我們的函數通過了這輪簡單的測試。如果函數沒有通過測試,比如我們故意要驗證一個錯誤的結果:getArea(10,22) ==0。
Framework將給出詳盡的錯誤報告, 其中Test Diagnostic欄目中報告的就是verifyTrue函數中的第二個參數所提供的診斷信息。
我們再添加一個負面測試,回憶第一版的函數getArea不支持單個參數,如下:
我們可以利用lasterr函數得到了這個錯誤的Error ID,這個Error ID將在負面測試中用到。下面是這個負面測試,驗證在只有一個輸入的情況下,getArea函數能夠如預期報錯。我們給測試添加一個新的測試點,叫做testTwoInputsInvalid。
在testTwoInputsInvalid中,我們使用了測試對象的verifyError成員函數,它的第一個參數是函數句柄,即要執行的語言(會出錯的語句),第二個參數是要驗證的MATLAB錯誤的Error ID, 就是我們前面用lasterr函數得到的信息。verifyError內部還有try和catch,可以運行函數句柄,捕捉到錯誤,并且把Error ID和第二個參數做比較。再舉一個例子,我們先在getArea函數中規定所有的輸入必須是數值類型,所以如果輸入的是字符串,getArea將報錯,先再命令行中實驗一下,以便得到Error ID:
然后再把這個負面測試添加到testGetArea中去:
運行一遍,一個正面測試,一個負面測試都全部通過。
getArea函數的單元測試: 版本II & III
測試的準備和清理工作: Tests Fixtures
驗證方法: Types of Qualification
測試方法論和以測試驅動開發(Test-Driven Development)
-
字符串
+關注
關注
1文章
585瀏覽量
20617 -
函數
+關注
關注
3文章
4349瀏覽量
63033
發布評論請先 登錄
相關推薦
嵌入式系統開發中的測試方法 嵌入式系統開發與AI結合應用
開發者必讀!CircleCI?組件測試與單元測試全解析
汽車軟件單元測試的重要性
嚴格的單元測試造就完美的軟件
![](https://file1.elecfans.com/web1/M00/F5/A2/wKgZoWdAM1mAYNcJAAJec6WT0X8605.jpg)
嵌入軟件單元/集成測試工具專業分析
matlab神經網絡工具箱結果分析
接口測試的工具有哪些種類
影響氣密性測試結果的原因分析及解決方案分享
![影響氣密性<b class='flag-5'>測試</b><b class='flag-5'>結果</b>的原因<b class='flag-5'>分析</b>及解決方案分享](https://file.elecfans.com/web2/M00/89/08/poYBAGO3lnqAFjqcAAEZo95iNrY513.png)
LitePoint推出其最新的5G O-RAN無線電單元測試技術
鴻蒙OS開發實戰:【自動化測試框架】使用指南
![鴻蒙OS開發實戰:【自動化<b class='flag-5'>測試</b>框架】使用指南](https://file1.elecfans.com/web2/M00/C8/4D/wKgaomYTkbOALFH9AADHmxFMlig306.jpg)
單元/集成測試服務
![<b class='flag-5'>單元</b>/集成<b class='flag-5'>測試</b>服務](https://file1.elecfans.com/web2/M00/C3/03/wKgaomXgFcKAAaSrAAAsexl2ass355.png)
評論