董寧 王波
摘要 運(yùn)行和調(diào)試JavaScript代碼的主要工具是Web瀏覽器,現(xiàn)代Web瀏覽器一般包含調(diào)試JavaScript代碼的控制臺(tái)。JavaScript代碼運(yùn)行中的錯(cuò)誤信息、Ajax調(diào)用、性能分析結(jié)果、命令行執(zhí)行結(jié)果都會(huì)顯示在控制臺(tái)界面上。Firefox瀏覽器的Firebug提供了很多手段,可以將JavaScript代碼運(yùn)行中的信息輸出到Firebug控制臺(tái)。通過(guò)靈活使用控制臺(tái)語(yǔ)句,可以方便地實(shí)現(xiàn)對(duì)JavaScript代碼的單元測(cè)試。
關(guān)鍵詞 JavaScript ;控制臺(tái);單元測(cè)試
DOI DOI: 10.11907/rjdk.162418
中圖分類(lèi)號(hào): TP306
文獻(xiàn)標(biāo)識(shí)碼: A 文章編號(hào) 文章編號(hào): 16727800(2017)002001303
0 引言
在計(jì)算機(jī)編程中,單元測(cè)試[1]是針對(duì)程序模塊(軟件設(shè)計(jì)的最小單位)進(jìn)行正確性檢驗(yàn)的測(cè)試工作。程序單元是最小的測(cè)試部件。在過(guò)程化編程中,一個(gè)單元就是單個(gè)程序、函數(shù)、過(guò)程等;對(duì)于面向?qū)ο缶幊?,最小單元就是方法,包括基?lèi)(超類(lèi))、抽象類(lèi)或者派生類(lèi)(子類(lèi))中的方法。每個(gè)理想的測(cè)試案例獨(dú)立于其它案例。為測(cè)試時(shí)隔離模塊,經(jīng)常使用stubs、mock或fake等測(cè)試馬甲程序。單元測(cè)試通常由軟件開(kāi)發(fā)人員編寫(xiě),用于確保所寫(xiě)代碼符合軟件需求和遵循開(kāi)發(fā)目標(biāo)。
運(yùn)行和調(diào)試JavaScript代碼[2]的主要工具是Web瀏覽器,現(xiàn)代的Web瀏覽器一般包含調(diào)試JavaScript代碼的控制臺(tái)。對(duì)于JavaScript代碼,Mozilla Firefox是最適合運(yùn)行與調(diào)試的瀏覽器之一。Mozilla Firefox瀏覽器的插件Firebug是調(diào)試JavaScript代碼必不可少的,尤其是涉及到Ajax技術(shù)的Web應(yīng)用。在Mozilla Firefox瀏覽器中安裝好Firebug插件后,JavaScript代碼運(yùn)行中的錯(cuò)誤信息、Ajax調(diào)用、性能分析結(jié)果、命令行執(zhí)行結(jié)果都會(huì)顯示在控制臺(tái)界面上。Firebug提供了很多手段可以將JavaScript代碼運(yùn)行中的信息輸出到Firebug控制臺(tái),通過(guò)靈活使用控制臺(tái)語(yǔ)句可以方便實(shí)現(xiàn)對(duì)JavaScript代碼的單元測(cè)試。
1 JavaScript代碼中控制臺(tái)語(yǔ)句使用
在JavaScript代碼中可以使用console.log()方法向控制臺(tái)輸出信息。實(shí)際上,console.log()方法包含在conosle對(duì)象中,而console對(duì)象則是由瀏覽器提供的(IE6及以前瀏覽器不支持console對(duì)象)。
除了最基本的console.log()方法外,conosle對(duì)象還提供了多種方法以便向控制臺(tái)輸出不同類(lèi)型的信息和調(diào)試JavaScript代碼。
(1)不同類(lèi)型輸出方法。
根據(jù)信息的不同性質(zhì),console對(duì)象除了console.log()方法外還有4種輸出信息方法:一般信息console.info()、調(diào)試信息console.debug()、警告提示console.warn()和錯(cuò)誤提示console.error()。
(2)自定義輸出格式。
console對(duì)象所有的輸出方法都可以使用printf風(fēng)格的占位符對(duì)輸出內(nèi)容進(jìn)行格式化。支持的占位符有字符(%s)、整數(shù)(%d或%i)、浮點(diǎn)數(shù)(%f)和對(duì)象(%o)。
(3)分組輸出。
如果在JavaScript代碼運(yùn)行過(guò)程中需要輸出數(shù)據(jù)太多,則可以使用分組的方式輸出到控制臺(tái)以便查看和分析。conosle對(duì)象中的console.group()和console.groupEnd()方法提供了數(shù)據(jù)分組輸出功能。
(4)輸出指定對(duì)象所有屬性和方法。
console.dir()方法可以輸出傳入對(duì)象的所有屬性和方法。
(5)顯示頁(yè)面對(duì)象的HTML代碼。
console.dirxml()方法可以顯示輸入的頁(yè)面對(duì)象HTML代碼,以便查看和調(diào)試。
(6)斷言。
console.assert()方法提供了基本的代碼測(cè)試功能。該方法用來(lái)判斷一個(gè)表達(dá)式或變量是否為真,如果不為真,則在控制臺(tái)輸出一條相應(yīng)信息,并且拋出一個(gè)異常。
(7)跟蹤方法調(diào)用軌跡。
console.trace()方法可以用來(lái)追蹤方法的調(diào)用軌跡,用來(lái)對(duì)遞歸方法或調(diào)用過(guò)程較復(fù)雜的方法進(jìn)行分析。
(8)計(jì)時(shí)方法。
console.time()和console.timeEnd()方法可以用來(lái)記錄并輸出代碼的運(yùn)行時(shí)間。
(9)性能分析方法。
性能分析指分析程序各個(gè)部分的運(yùn)行時(shí)間,console.profile()可以用來(lái)對(duì)JavaScript代碼進(jìn)行性能分析,找出代碼瓶頸。
2 JavaScript代碼單元測(cè)試實(shí)現(xiàn)
如果需要測(cè)試某些不涉及DOM和CSS操作的JavaScript代碼,用Qunit之類(lèi)的第三方JavaScript單元測(cè)試框架[3]略顯繁瑣,效率不高,這類(lèi)JavaScript代碼最適合用控制臺(tái)語(yǔ)句做單元測(cè)試。
例如某項(xiàng)目需要用JavaScript代碼實(shí)現(xiàn)快速排序[4],具體實(shí)現(xiàn)代碼如下:
//swap函數(shù)實(shí)現(xiàn)元素交換
function swap(list,firstIndex,secondIndex){
var temp = list[firstIndex];
list[firstIndex]= list[secondIndex];
list[secondIndex]=temp;
}
//getMiddle函數(shù)獲取中軸點(diǎn)
function getMiddle(list,left,right) {
var pivot = list[Math.floor((right + left)/2)];
var i = left;
var j = right;
while (i <= j) {
while (list[i]< pivot) {
i++;
}
while (list[j]> pivot) {
j--;
}
if (i <= j) {
swap(list,i,j);
i++;
j--;
}
}
return i;
}
//quickSort函數(shù)以遞歸方式完成快速排序
function quickSort(list,left,right) {
var index;
if (list.length > 1) {
index = getMiddle(list,left,right);
if (left < index - 1) {
quickSort(list,left,index - 1);
}
if (index < right) {
quickSort(list,index,right);
}
}
return list;
}
上述快速排序的實(shí)現(xiàn)代碼可以使用控制臺(tái)語(yǔ)句中的斷言部分完成測(cè)試,具體如下:
//待排序list
var array=[6,2,9,8,1,7];
//預(yù)期的結(jié)果
var result=[1,2,6,7,8,9];
//測(cè)試swap函數(shù)
swap(array,1,5);
console.assert(array[1]==7&&array[5]==2,"swap函數(shù)錯(cuò)誤!");
//測(cè)試getMiddle函數(shù)
var m = getMiddle(array,0,array.length-1);
console.assert(m==5,"getMiddle函數(shù)錯(cuò)誤!");
//測(cè)試quickSort函數(shù)
quickSort(array,0,array.length-1);
console.assert(array.toString()==result.toString(),"quickSort函數(shù)錯(cuò)誤!");
//單元測(cè)試結(jié)束
console.info("測(cè)試完成!");
通過(guò)控制臺(tái)語(yǔ)句中的console.assert()方法可以分別測(cè)試代碼中的swap函數(shù)、getMiddle函數(shù)和quickSort函數(shù)。如果測(cè)試通過(guò),則會(huì)看到在控制臺(tái)中輸出帶有信息提示圖標(biāo)的“測(cè)試完成!”字樣。
如果其中某一個(gè)函數(shù)出錯(cuò)則會(huì)有相應(yīng)提示,如圖1所示。
上述針對(duì)快速排序模塊的測(cè)試很簡(jiǎn)單,測(cè)試結(jié)果也沒(méi)有問(wèn)題。但是對(duì)單元測(cè)試來(lái)說(shuō),這個(gè)測(cè)試用例太單一和普通了。為了提高測(cè)試用例[5]覆蓋率,最好寫(xiě)一個(gè)輔助函數(shù)tester來(lái)調(diào)用被測(cè)試代碼和使用控制臺(tái)語(yǔ)句輸出結(jié)果,具體做法如下:
function tester(name,result,expect){
//使用分組語(yǔ)句輸出測(cè)試用例名
console.group(name);
if(result==expect){
//測(cè)試通過(guò),信息提示
console.info("通過(guò)!");
}else{
//測(cè)試失敗,警告提示
console.warn("失敗");
}
//分組結(jié)束
console.groupEnd();
}
如果用上述tester函數(shù)測(cè)試完成快速排序的quickSort函數(shù),可以這樣實(shí)現(xiàn):
//待排序list
var array1=[6,2,9,8,1,7];
//預(yù)期的結(jié)果
var result1=[1,2,6,7,8,9];
//待排序list2
var array2= [6,2,9,8,1,7,85,12,48,56,78,987,45,
12,-78,45,0,58,96,12.56,12.3,7.36];
//預(yù)期的結(jié)果2
var result2 = [-78,0,1,2,6,7,7.36,8,9,12,12,12.3,
12.56,45,45,48,56,58,78,85,96,987];
//錯(cuò)誤結(jié)果測(cè)試
tester("測(cè)試錯(cuò)誤輸入",1,0);
//測(cè)試快速排序
quickSort(array1,0,array1.length-1);
tester("常規(guī)測(cè)試",array1.toString(),result1.toString());
quickSort(array2,0,array2.length-1);
tester("包含負(fù)數(shù)與小數(shù)測(cè)試",array2.toString(),result2.toString());
代碼運(yùn)行結(jié)果如圖2所示。
可使用tester函數(shù)添加許多測(cè)試用例,并且還能為用例命名,在控制臺(tái)中直接顯示每個(gè)用例是否通過(guò),同時(shí)用不同顏色標(biāo)記,使結(jié)果一目了然。至此一個(gè)基本的單元測(cè)試就完成了。
3 結(jié)語(yǔ)
快速排序算法的JavaScript代碼,靈活使用控制臺(tái)語(yǔ)句可快速完成代碼模塊的單元測(cè)試,比起專業(yè)的第三方JavaScript單元測(cè)試框架更高效,學(xué)習(xí)曲線也不那么陡峭。但是,利用控制臺(tái)語(yǔ)句實(shí)現(xiàn)JavaScript代碼單元測(cè)試主要適用于邏輯代碼,而前端開(kāi)發(fā)很多時(shí)候要和UI關(guān)聯(lián),雖然UI相關(guān)的代碼也可以進(jìn)行單元測(cè)試,但很麻煩,比起邏輯代碼難度大得多。隨著單元測(cè)試的普及,尤其是敏捷開(kāi)發(fā)的推動(dòng),涌現(xiàn)了許多優(yōu)秀的JavaScript單元測(cè)試框架,如Qunit和Jasmine等,每個(gè)都有各自擅長(zhǎng)的領(lǐng)域。對(duì)于基于JavaScript語(yǔ)言的前端項(xiàng)目單元測(cè)試,結(jié)合控制臺(tái)語(yǔ)句,精心選擇框架,綜合考慮項(xiàng)目實(shí)際情況,一定可以寫(xiě)出合適的測(cè)試代碼。
參考文獻(xiàn):
[1] 張軍,李攀,邢光輝,等.軟件測(cè)試的認(rèn)知誤區(qū)和單元測(cè)試實(shí)戰(zhàn)流程[J].科技創(chuàng)新與應(yīng)用,2016 (25):120120.
[2] 張令芬.JavaScript API自動(dòng)化測(cè)試方案的管理設(shè)計(jì)與實(shí)現(xiàn)[J].電子設(shè)計(jì)工程,2016,24(2):3537,41.
[3] 王婷婷,申啟杰.JavaScript調(diào)試器軟件架構(gòu)[J].湖南師范大學(xué)學(xué)報(bào),2014(6):8892.
[4] 王善坤,陶禎蓉.一種三路劃分快速排序的改進(jìn)算法[J].計(jì)算機(jī)應(yīng)用研究,2012,29(7):25132516.
[5] 張智軼,陳振宇,徐寶文,等.測(cè)試用例演化研究進(jìn)展[J].軟件學(xué)報(bào),2013,24(4):663674.
(責(zé)任編輯:杜能鋼)