趙衛(wèi)東 彭偲



摘? 要: 單元測試是軟件測試中的最底層的一種測試活動,是軟件開發(fā)中不可忽視的一個環(huán)節(jié),但我國高校軟件單元測試的教學(xué)效果并不理想。本文分析了傳統(tǒng)實驗教學(xué)存在的問題,引入先進(jìn)流行的開源測試框架,設(shè)計了單元測試實驗課程教學(xué)內(nèi)容;采用任務(wù)驅(qū)動教學(xué)方法,以理論知識為基礎(chǔ),以企業(yè)需求為標(biāo)桿,對實驗教學(xué)方法進(jìn)行了改革,收到了良好的教學(xué)效果。
關(guān)鍵詞: 單元測試教學(xué);軟件開發(fā);實驗課程;JUnit
中圖分類號: TP311.56; G712? ? 文獻(xiàn)標(biāo)識碼: A? ? DOI:10.3969/j.issn.1003-6970.2019.07.042
【Abstract】: Unit testing is the lowest level of testing activities in software testing. It is a link that cannot be ignored? in software development. However, the teaching effect of software unit testing in Chinese universities is not ideal. This paper analyzes the problems existing in traditional experimental teaching, introduces the advanced and popular open source testing framework, and designs the teaching content of the unit test experiment course. It adopts the task-driven teaching method, based on the theoretical knowledge, and takes the enterprise demand as the benchmark to carry out the experimental teaching method. The reform received good teaching results.
【Key words】: Unit test teaching; Software development; Experimental lesson; JUnit
0? 引言
近年來,隨著計算機(jī)軟件走進(jìn)社會的各個領(lǐng)域,軟件測試的重要性也在不斷提高。企業(yè)更加重視并且愿意投入更多時間和人力成本在軟件測試上[1],因此許多高校也將軟件測試設(shè)為獨立課程,力求為國家和企業(yè)培養(yǎng)出更多測試領(lǐng)域的人才。
然而,單元測試的教學(xué)效果仍然不盡人意,原因主要有兩方面:一方面,單元測試不僅需要專業(yè)測試人員,還需要開發(fā)者的積極配合和參與。如今部分開發(fā)工程師、項目經(jīng)理仍然懷著傳統(tǒng)的觀念,認(rèn)為軟件測試是測試工程師的工作,開發(fā)工程師不需要參與,甚至認(rèn)為讓開發(fā)工程師參與就是“浪費時間”,會影響項目的開發(fā)進(jìn)度[1]。這種觀念影響了高校學(xué)生,部分學(xué)生誤認(rèn)為開發(fā)工程師無需學(xué)習(xí)測試相關(guān)知識。學(xué)生對測試課程的不重視,使得教學(xué)工作開展并不順利。
另一方面,部分高校的單元測試教學(xué)課程設(shè)計也不盡合理[3]。主要存在兩個問題:一是課程的內(nèi)容相對陳舊,與軟件行業(yè)發(fā)展的進(jìn)度嚴(yán)重脫節(jié)。部分高校使用的教材或者案例都來自多年前的資料,其技術(shù)已經(jīng)過時或者不適合現(xiàn)在的軟件開發(fā)。二是缺乏實驗課程,學(xué)生在課上學(xué)到的理論知識無法通過實踐來鞏固,不僅容易遺忘,而且在日后的工作中也無法得到運用。
為了提高單元測試的教學(xué)效果,本文針對這兩個方面,設(shè)計了一種基于開源測試框架的,任務(wù)驅(qū)動式單元測試實驗課程教學(xué)方法,使學(xué)生可以更高效的學(xué)習(xí)單元測試,并有能力將其運用于實際工作或項目中。
1? 單元測試框架的選擇
1.1? 當(dāng)今流行的單元測試工具
由于單元測試中測試的對象為具體代碼段,所以絕大多數(shù)的單元測試框架都只能服務(wù)于一種特定的開發(fā)語言。現(xiàn)在較為流行的幾種開發(fā)語言為Java語言、C系列語言、Python語言以及JavaScript語言,每種語言都有得到業(yè)內(nèi)認(rèn)可的單元測試框架。例如,Java語言的JUnit框架,C++語言的GoogleTest框架以及Python語言的unittest框架都是非常優(yōu)秀的單元測試框架。
1.2? JUnit測試框架的優(yōu)勢
本課程綜合分析了多種開發(fā)語言和測試框架,最終選擇Java語言的JUnit作為教學(xué)框架,其原因如下:
(1)Java仍然是使用最廣泛的語言。近年來隨著智能手機(jī)的發(fā)展,許多企業(yè)都在開發(fā)手機(jī)App來為用戶提供更便捷的服務(wù),而Android系統(tǒng)作為市場份額占有率最高的系統(tǒng),其主要開發(fā)語言就是Java。此外,Java是最常用的服務(wù)端開發(fā)語言,目前大多數(shù)系統(tǒng)的服務(wù)端使用Java開發(fā)。
(2)JUnit本身功能十分強(qiáng)大,是Java語言中最受歡迎的單元測試框架[2]。傳統(tǒng)的單元測試方法是在程序中內(nèi)嵌代碼輸出數(shù)據(jù),然后再由人工查看來判斷程序是否存在問題。這種方式不僅繁瑣、代碼侵入性高,也可能出現(xiàn)失誤。引入了JUnit框架后,利用其斷言功能編寫相應(yīng)的測試代碼,可以解決上述問題,并且方便進(jìn)行回歸測試。JUnit提供了擴(kuò)展功能,能讓用戶自定義斷言的方法或者Runner來進(jìn)行個性化測試[5]。測試完成后,JUnit能幫助用戶分析失敗原因和定位問題所在。
(3)JUnit擁有良好的生態(tài)圈[6]。由于JUnit在Java項目和Android App項目中被廣泛使用[7],主流的集成開發(fā)環(huán)境(例如Eclipse、IDEA和Android Studio)都為JUnit提供了官方插件,用戶在這些開發(fā)環(huán)境中使用起來極為方便。例如,可以一鍵生成對應(yīng)的測試報告,或是一鍵重新測試上一次未通過部分等等。此外,部分常用的Java第三方框架(例如Spring)也為JUnit提供了原生支持。
2? 實驗內(nèi)容設(shè)計
2.1? 實驗?zāi)康?/p>
實驗的目的包括以下幾點:
(1)掌握在IntelliJ IDEA開發(fā)環(huán)境中引入開源框架JUnit的方法。
(2)掌握使用JUnit進(jìn)行單元測試的基本步驟與操作方法。
(3)掌握J(rèn)Unit的注解功能。
(4)掌握使用JUnit進(jìn)行參數(shù)化測試的方法。
2.2? 實驗內(nèi)容
實驗的內(nèi)容主要包括:
(1)使用IntelliJ IDEA創(chuàng)建項目,編寫業(yè)務(wù)邏輯代碼作為受測程序。
(2)在IntelliJ IDEA中引入JUnit框架,針對業(yè)務(wù)代碼編寫對應(yīng)的測試代碼。
(3)執(zhí)行測試操作和觀察測試結(jié)果。
(4)編寫多個測試方法,利用集成開發(fā)環(huán)境提供的功能進(jìn)行批量測試和回歸測試。
(5)理解JUnit的注解功能。
(6)結(jié)合理論知識,為一個特定功能單元設(shè)計一套完整的測試用例,并學(xué)習(xí)參數(shù)化測試,以便同時測試多個測試用例。
(7)學(xué)習(xí)打包測試功能,同時測試多個測試類。
2.3? 實驗教學(xué)思路
本實驗課程共包含4個學(xué)時,分2次授課。授課時不采取傳統(tǒng)的先講后練的模式,而是采用更高效的任務(wù)驅(qū)動課程的形式[8],將講解和練習(xí)結(jié)合在一起。每堂課由數(shù)個任務(wù)組成,每次講解并演示完一個任務(wù)后,提供足夠的練習(xí)時間供學(xué)生實踐,學(xué)生在明確任務(wù)以后,就開始進(jìn)行準(zhǔn)備工作[9]。
下文將介紹每個任務(wù)的實驗步驟[10]。
2.3.1? 任務(wù)一:編寫受測程序代碼
(1)啟動IDEA,新建一個Java項目。
(2)在項目的src文件夾下新建一個計算器類Calculator,作為受測程序。
(3)在Calculator類下添加add、subtract等方法并編寫相應(yīng)代碼用于測試,如圖1所示。
2.3.2? 任務(wù)二:引入JUnit并編寫測試代碼
(1)在項目的根目錄下建立一個test文件夾,然后將此文件夾設(shè)定為測試源代碼目錄。
(2)在Calculator類名上右擊并依次點擊“Go To”和“Test”,在彈出的浮窗中選擇“Create New Test”選項。
(3)在彈出的對話框中,點擊Fix來添加IDEA內(nèi)置的JUnit依賴到項目中,在Testing Library中選擇JUnit 4,填寫類名CalculatorTest,全選要測試的方法并點擊確認(rèn),如圖2所示。
(4)在JUnit生成的模板代碼的基礎(chǔ)上,利用斷言編寫測試代碼,如圖3所示。
2.3.3? 任務(wù)三:執(zhí)行單個方法測試和批量方法測試
(1)點擊方法名左側(cè)的綠色三角形按鈕來進(jìn)行單個方法的測試。
(2)點擊類名左側(cè)的雙綠色三角形按鈕來進(jìn)行整個類的批量測試。
(3)觀察測試結(jié)果,對于未通過的測試,根據(jù)JUnit給出的提示來糾正原程序代碼,然后通過“執(zhí)行上一次未通過的測試”功能校驗效果。
2.3.4? 任務(wù)四:利用注解優(yōu)化代碼
(1)在CalculatorTest類新建一個Calculator類的成員變量,并新建一個init方法,在init方法中將其實例化。
(2)在init方法上方添加注解@Before。
(3)去掉測試方法中實例化Calculator的代碼,使用成員變量的實例代替,如圖4所示。
(4)運行檢驗是否可以通過,并思考@Before注解的作用。
(5)分別使用@After、@BeforeClass、@AfterClass注解來了解其作用,思考他們的觸發(fā)時機(jī)、順序和實際用途。
2.3.5? 任務(wù)五:使用參數(shù)化測試來測試多個用例
(1)新建一個ParamAddTest類,并添加@RunWith (Parameterized.class)注解。
(2)在ParamAddTest類下新建三個成員變量input1、input2、output,在構(gòu)造函數(shù)中將其初始化。
(3)按同樣的思路編寫測試代碼,與普通測試不同的是,要將其中的參數(shù)對應(yīng)替換成input1、input2和output。
(4)新建一個data方法用來提供參數(shù),并在此方法加上@Parameters注解,如圖5所示。
(5)執(zhí)行測試,若測試未通過,JUnit會指出導(dǎo)致未通過的測試用例以助于分析原因。
2.3.6? 任務(wù)六:使用打包測試進(jìn)行批量類測試
(1)新建一個SuiteTest類。
(2)在SuiteTest類的類名上方添加@RunWith (Suite.class)注解。
(3)在SuiteTest類的類名上方添加@Suite. SuiteClasses({***})注解,其中***部分填寫要打包測試的類名,例如@Suite.SuiteClasses({Param AddTest.class, CalculatorTest.class}),如圖6所示。
(4)執(zhí)行測試,若測試未通過,JUnit會指出未通過的測試類以及錯誤信息。
3? 實驗教學(xué)方法
3.1? 傳統(tǒng)的教學(xué)方法的弊端
相比較其他測試活動而言,單元測試需要開發(fā)工程師的參與,甚至是以開發(fā)工程師為主體的。大多數(shù)企業(yè)都比較重視單元測試,部分企業(yè)甚至對于單元測試有強(qiáng)制性要求[11]。傳統(tǒng)的課程沒有強(qiáng)調(diào)這一點,使用的技術(shù)與教材也相對陳舊,這容易讓學(xué)生產(chǎn)生“單元測試已經(jīng)過時”或者“開發(fā)者對于測試課程只需了解”的誤解,讓學(xué)生對課程的積極性較低。
正因為單元測試是由開發(fā)工程師為主的,所以它更強(qiáng)調(diào)實踐和編碼[12]。傳統(tǒng)的教學(xué)方法講述理論知識占用時間比例較大,分配的實驗課程時間則較少甚至根本沒有。教學(xué)內(nèi)容枯燥,學(xué)生積極性不高[13]。這導(dǎo)致了理論與實踐相分離,學(xué)生無法將學(xué)到理論知識進(jìn)行實際運用,在課后也沒有進(jìn)一步學(xué)習(xí)的方向,學(xué)習(xí)效率很低[14]。
3.2? 改進(jìn)的教學(xué)方法總結(jié)
改進(jìn)的教學(xué)方法更注重于用實驗來鞏固理論,將二者有機(jī)結(jié)合在一起,做到不僅能讓學(xué)生掌握必備的理論知識,還能用代碼將其體現(xiàn)出來,直接將學(xué)到的知識運用于今后的實習(xí)項目或工作中。
教學(xué)使用到的前置知識為較基礎(chǔ)的必修課程,只需掌握J(rèn)ava基礎(chǔ)即能上手,不會使學(xué)生喪失學(xué)習(xí)積極性。隨后通過循序漸進(jìn)的任務(wù)式教學(xué),逐步加深課程難度,即使基礎(chǔ)薄弱也能跟上節(jié)奏;課后提出思考問題,學(xué)有余力的學(xué)生則能找到課后深入學(xué)習(xí)的思路和方向,有效的提高了教學(xué)效果。
4? 實驗教學(xué)方法展望
改進(jìn)的實驗方法切實有效的提高了教學(xué)效果,但是仍然有改進(jìn)空間。實驗中使用了Java作為教學(xué)語言,但使用的教學(xué)案例相對較基礎(chǔ)。調(diào)查發(fā)現(xiàn),在學(xué)習(xí)軟件測試課程之前,大部分學(xué)生已經(jīng)學(xué)習(xí)過較多的編碼課程,擁有一定的知識儲備和實踐能力,可以考慮進(jìn)一步提高課程深度。
考慮到Java的語言目前主要運用于Android和Web的項目中[15],二者目前對JUnit都有相應(yīng)的支持。在后續(xù)的教學(xué)中,可以根據(jù)實際情況,將JUnit融入Android或Web項目中進(jìn)行教學(xué),提高課程深度的同時,與企業(yè)需求直接接軌,可更好的提升教學(xué)效果。
參考文獻(xiàn)
[1] 徐福禎. 計算機(jī)軟件測試方法及應(yīng)用實踐[J]. 信息與電腦(理論版), 2018(02): 14-16.
[2] 朱冬玲. 基于先進(jìn)工作過程的軟件測試課程教學(xué)[J]. 電腦與電信, 2013(11): 33-34.
[3] 陳站華. 軟件單元測試[J].無線電通信技術(shù), 2003(05): 50-51.
[4] Vahid Garousi Yusifo?lu, Yasaman Amannejad, Aysu Betin Can. Software test-code engineering: A systematic mapping [J]. Information and Software Technology, 2015, 58.
[5] 白凱, 崔冬華. 基于JUnit自動化單元測試的研究[J]. 計算
機(jī)與數(shù)字工程, 2010, 38(02): 52-54+103.
[6] Mourad Badri, Fadel Toure,Luc Lamontagne. Predicting Unit Testing Effort Levels of Classes: An Exploratory Study based on Multinomial Logistic Regression Modeling[J]. Procedia Computer Science, 2015, 62.
[7] 劉升貴. 基于MVP模式的Android應(yīng)用程序?qū)崿F(xiàn)及其單元測試研究[J]. 福建電腦, 2017, 33(07): 94-95.
[8] 王艷輝. 基于任務(wù)驅(qū)動的軟件測試課程教學(xué)模式研究與應(yīng)用[J]. 濟(jì)南職業(yè)學(xué)院學(xué)報, 2017(03): 57-58+67.
[9] 周洪茜, 劉丹. 基于思維導(dǎo)圖的翻轉(zhuǎn)課堂教學(xué)模式研究[J]. 軟件, 2018, 39(4): 63-67.
[10] 王芳, 鄧一星, 秦映波. 敏捷軟件項目管理課程教學(xué)方案研究與實踐[J]. 軟件, 2018, 39(4): 77-81.
[11] 董威. 單元測試及測試工具的研究與應(yīng)用[J]. 微型電腦應(yīng)用, 2008(05): 24-26+23+5.
[12] 蔡高亮. 軟件單元測試[J]. 信息技術(shù)與標(biāo)準(zhǔn)化, 2008(Z1): 41-43.
[13] 閆實, 劉占波, 王曉麗. 云計算技術(shù)在高校計算機(jī)基礎(chǔ)教學(xué)中的應(yīng)用[J]. 軟件, 2018, 39(6): 167-169.
[14] 鞠小林, 陳翔, 文萬志, 張艷梅. “產(chǎn)教研”融合的軟件測試課程案例庫構(gòu)建[J]. 計算機(jī)教育, 2019(03): 121-125.
[15] 馬金鳴. 計算機(jī)軟件開發(fā)中JAVA編程語言的應(yīng)用[J]. 電子技術(shù)與軟件工程, 2017(17): 53.