詳解如何用JavaScript編寫一個(gè)單元測(cè)試
測(cè)試代碼是確保代碼穩(wěn)定的第一步。能做到這一點(diǎn)的最佳方法之一就是使用單元測(cè)試,確保應(yīng)用程序中的每個(gè)較小的功能都按應(yīng)有的方式運(yùn)行——尤其是當(dāng)應(yīng)用程序接收到極端或無(wú)效輸入,甚至可能有害的輸入時(shí)。
為什么要進(jìn)行單元測(cè)試?
進(jìn)行單元測(cè)試有許多不同的方法,一些主要目的是:
- 驗(yàn)證功能:?jiǎn)卧獪y(cè)試確保代碼做正確的事情并且不做任何不應(yīng)該做的事情——大多數(shù)錯(cuò)誤發(fā)生在這里。
- 防止代碼回歸:當(dāng)我們發(fā)現(xiàn)錯(cuò)誤時(shí),添加單元測(cè)試來(lái)檢查場(chǎng)景可以防止代碼更改在將來(lái)重新引入錯(cuò)誤。
- 記錄代碼:通過(guò)正確的單元測(cè)試,一套完整的測(cè)試和結(jié)果提供了應(yīng)用程序應(yīng)該如何工作的規(guī)范。
- 保護(hù)您的應(yīng)用程序:?jiǎn)卧獪y(cè)試可以檢查可利用的漏洞(例如啟用惡意 SQL 注入的漏洞)。
范圍界定和編寫單元測(cè)試
使用單元測(cè)試框架使我們能夠快速編寫和自動(dòng)化我們的測(cè)試,并將它們集成到我們的開發(fā)和部署過(guò)程中。這些框架通常支持前端和后端 JavaScript 代碼的測(cè)試。
以下是幫助你編寫性能單元測(cè)試和可測(cè)試代碼的一些通用指南。
保持單元測(cè)試簡(jiǎn)短而簡(jiǎn)單
不要編寫過(guò)重的單元測(cè)試,測(cè)試應(yīng)該只有幾行代碼來(lái)檢查應(yīng)用程序的簡(jiǎn)短功能塊。
考慮正面和負(fù)面的測(cè)試用例
雖然編寫正確執(zhí)行函數(shù)的測(cè)試是有用的,但是,編寫更廣泛的測(cè)試集來(lái)檢查函數(shù)在被濫用或在極端情況下是否正確或者失敗同樣重要。這些負(fù)面測(cè)試可能更有價(jià)值,因?yàn)樗鼈冇兄陬A(yù)測(cè)意外情況,例如函數(shù)何時(shí)應(yīng)引發(fā)異常或應(yīng)如何處理接收格式錯(cuò)誤的數(shù)據(jù)。
分解長(zhǎng)而復(fù)雜的函數(shù)
包含大量邏輯的大型函數(shù)難以測(cè)試;包含太多操作則難以有效地測(cè)試每個(gè)變量。如果函數(shù)太復(fù)雜,請(qǐng)將其拆分為較小的函數(shù)以進(jìn)行單獨(dú)測(cè)試。
避免網(wǎng)絡(luò)和數(shù)據(jù)庫(kù)連接
單元測(cè)試應(yīng)該是快速和輕量級(jí)的,但是進(jìn)行網(wǎng)絡(luò)調(diào)用或連接到其他應(yīng)用程序或進(jìn)程的功能需要長(zhǎng)時(shí)間才能執(zhí)行。這使得同時(shí)運(yùn)行多個(gè)操作變得具有挑戰(zhàn)性,且會(huì)產(chǎn)生更脆弱的代碼。你可以在單元測(cè)試中調(diào)用模擬的網(wǎng)絡(luò)或數(shù)據(jù)庫(kù)而非真實(shí)地連接網(wǎng)絡(luò)。而如果要進(jìn)行包含真實(shí)的網(wǎng)絡(luò)和數(shù)據(jù)庫(kù)連接的測(cè)試,應(yīng)當(dāng)在稱為集成測(cè)試(所有的單元或模塊被組合在一起并作為一個(gè)整體進(jìn)行測(cè)試)中進(jìn)行而不是單元測(cè)試。
如何編寫單元測(cè)試
我們已經(jīng)回顧了一些單元測(cè)試的最佳實(shí)踐,現(xiàn)在準(zhǔn)備好用 JavaScript 編寫你的第一個(gè)單元測(cè)試了。
本教程使用 Mocha 框架 —— 最流行的單元測(cè)試之一。每個(gè)測(cè)試框架都略有不同,但它們足夠相似,學(xué)習(xí)基本概念將使你能夠輕松地在它們之間切換。
在開始前,請(qǐng)確保你的電腦上安裝了 Node.js 環(huán)境。
創(chuàng)建一個(gè)新項(xiàng)目
首先打開一個(gè)終端窗口或命令提示符到一個(gè)新的項(xiàng)目文件夾。然后,通過(guò)以下命令在其中創(chuàng)建一個(gè)新的 Node.js 項(xiàng)目。
npm init -y
這會(huì)在文件夾中創(chuàng)建一個(gè)文件 package.json
,使你能夠使用 npm install -D mocha
命令來(lái)安裝 mocha 框架。
接下來(lái),在代碼編輯器中打開 package.json
文件并將 test script 替換為:mocha
"scripts": { "test": "mocha" },
實(shí)現(xiàn)一個(gè)類
接下來(lái),編寫一個(gè)簡(jiǎn)單的紅綠燈系統(tǒng)進(jìn)行單元測(cè)試。
在項(xiàng)目目錄中,創(chuàng)建一個(gè)名為 traffic.js
文件,其中是一個(gè) TrafficLight
的類:
class TrafficLight { constructor() { this.lightIndex = 0; } static get colors() { return [ "green", "yellow", "red" ]; } get light() { return TrafficLight.colors[ this.lightIndex ]; } next() { this.lightIndex++; // This is intentionally wrong! if( this.lightIndex > TrafficLight.colors.length ) { this.lightIndex = 0; } } } module.exports = TrafficLight;
這個(gè)類由四部分組成:
TrafficLight.colors
:交通燈顏色的常量屬性。lightIndex
:一個(gè)變量,跟蹤當(dāng)前交通燈顏色的索引。light
:以字符串形式返回當(dāng)前交通燈顏色的類屬性。next()
:將紅綠燈更改為下一個(gè)燈光顏色的功能。
配置和添加我們的第一個(gè)單元測(cè)試
現(xiàn)在是時(shí)候圍繞代碼添加一些單元測(cè)試了。
在項(xiàng)目中創(chuàng)建一個(gè)名為 test
的目錄,這是 Mocha 默認(rèn)檢查單元測(cè)試的地方。然后,在新的測(cè)試文件夾中添加一個(gè)名為 traffic.test.js
的文件。
接下來(lái),在文件頂部導(dǎo)入 TrafficLight
類:
const TrafficLight = require( "../traffic" );
我們還將使用該 assert
模塊進(jìn)行測(cè)試,因此在你的代碼中需要引入它:
const assert = require( "assert" );
在 Mocha 中我們可以使用 describe()
這個(gè)函數(shù)將單元測(cè)試進(jìn)行分組集合,如下:
describe( "TrafficLight", function () { });
然后,我們將創(chuàng)建一些單元測(cè)試來(lái)驗(yàn)證他們自己的子組中的交通顏色:
describe( "TrafficLight", function () { describe( "colors", function () { }); });
對(duì)于第一個(gè)單元測(cè)試,我們可以驗(yàn)證 colors
只有三種狀態(tài):綠色、黃色和紅色。測(cè)試方式是使用 describe()
組內(nèi)的 it()
函數(shù)定義的,因此編寫測(cè)試如下:
describe( "TrafficLight", function () { describe( "colors", function () { it( "has 3 states", function () { const traffic = new TrafficLight(); assert.equal( 3, TrafficLight.colors.length ); }); }); });
現(xiàn)在讓我們運(yùn)行單元測(cè)試,看看它是否通過(guò)。
在終端窗口中運(yùn)行 npm test
,如果一切正確,Mocha 會(huì)打印出單元測(cè)試運(yùn)行的結(jié)果。
添加更多單元測(cè)試
我們的項(xiàng)目現(xiàn)在已準(zhǔn)備好運(yùn)行單元測(cè)試,因此我們可以添加更多測(cè)試以確保我們的代碼正常工作。
首先,向colors
組中添加一個(gè)單元測(cè)試,以驗(yàn)證紅綠燈顏色是否正確且有序。這是實(shí)現(xiàn)此測(cè)試的一種方法:
it( "colors are in order", function () { const expectedLightOrder = [ "green", "yellow", "red" ]; const traffic = new TrafficLight(); for( let i = 0; i < expectedLightOrder.length; i++ ) { assert.equal( expectedLightOrder[ i ], TrafficLight.colors[ i ] ); } });
其次,測(cè)試next()
方法看它是否正確地改變了交通信號(hào)燈。創(chuàng)建一個(gè)新的子組并添加兩個(gè)單元測(cè)試:一個(gè)檢查燈光是否以正確的順序變化,另一個(gè)檢查燈光是否能循環(huán)在紅燈之后變?yōu)榫G燈:
describe( "next()", function () { it( "changes lights in order", function () { const traffic = new TrafficLight(); for( let i = 0; i < TrafficLight.colors.length; i++ ) assert.equal( traffic.light, TrafficLight.colors[ i ] ); traffic.next(); } }); it( "loops back to green", function () { const traffic = new TrafficLight(); // Change the light 3x to go from green -> yellow -> red -> green for( let i = 0; i < 3; i++ ) { traffic.next(); } assert.equal( traffic.light, TrafficLight.colors[ 0 ] ); }); });
現(xiàn)在,當(dāng)我們重新運(yùn)行測(cè)試時(shí),我們會(huì)看到其中一個(gè)測(cè)試失敗了。這是因?yàn)?TrafficLight
類中有一個(gè)錯(cuò)誤。
修復(fù)錯(cuò)誤
為方便調(diào)試本例提前注明好的錯(cuò)誤代碼位置,我們?cè)俅未蜷_ TrafficLight
類并找到 next()
函數(shù)內(nèi)的這句注釋:// This is intentionally wrong!
。
從單元測(cè)試中我們知道這個(gè)函數(shù)沒有正確地循環(huán)回 green
,我們可以看到代碼是在判斷lightIndex
值超過(guò)交通燈顏色的數(shù)量時(shí)給索引設(shè)置了0
,這顯然是不對(duì)的,我們必須在值達(dá)到確切的顏色數(shù)時(shí)立即將索引修改為0
:
// This is intentionally wrong! if( this.lightIndex === TrafficLight.colors.length ) { this.lightIndex = 0; }
現(xiàn)在你所有的單元測(cè)試都應(yīng)該通過(guò)了。而這帶來(lái)的好處是即使TrafficLight
這個(gè)類被重構(gòu)或大量修改,我們的單元測(cè)試也會(huì)在它到達(dá)用戶之前捕獲這個(gè)錯(cuò)誤。
最后
單元測(cè)試易于設(shè)置,是軟件開發(fā)的有效工具。它們有助于及早消除錯(cuò)誤并防止它們重現(xiàn)。這使項(xiàng)目更易于管理和維護(hù),即使它們變得更大更復(fù)雜——尤其是在大型開發(fā)團(tuán)隊(duì)中。像這樣的自動(dòng)化測(cè)試還使開發(fā)人員能夠重構(gòu)和優(yōu)化他們的代碼,而不必?fù)?dān)心新代碼的行為是否正確。
以上就是詳解如何用JavaScript編寫一個(gè)單元測(cè)試的詳細(xì)內(nèi)容,更多關(guān)于JavaScript單元測(cè)試的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript內(nèi)存分配原理實(shí)例分析
這篇文章主要介紹了javascript內(nèi)存分配原理,結(jié)合實(shí)例形式分析了javascript原始值和引用值內(nèi)存分配的原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-04-04JS對(duì)img標(biāo)簽進(jìn)行優(yōu)化使用onerror顯示默認(rèn)圖像
這篇文章主要介紹了JS對(duì)img標(biāo)簽進(jìn)行優(yōu)化使用onerror顯示默認(rèn)圖像,需要的朋友可以參考下2014-04-04js Array對(duì)象的擴(kuò)展函數(shù)代碼
有時(shí)候我們需要對(duì)js的array對(duì)象擴(kuò)展一些功能,這里簡(jiǎn)單介紹下,方便需要的朋友2013-04-04JavaScript引用類型Function實(shí)例詳解
這篇文章主要介紹了JavaScript引用類型Function,結(jié)合實(shí)例形式詳細(xì)分析了javascript引用類型Function概念、定義、原理、相關(guān)使用技巧與操作注意事項(xiàng),需要的朋友可以參考下2018-08-08JS實(shí)現(xiàn)將對(duì)象轉(zhuǎn)化為數(shù)組的方法分析
這篇文章主要介紹了JS實(shí)現(xiàn)將對(duì)象轉(zhuǎn)化為數(shù)組的方法,結(jié)合實(shí)例形式分析了javascript操作及轉(zhuǎn)換json數(shù)組相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-01-01IE瀏覽器不支持getElementsByClassName的解決方法
這篇文章主要介紹了IE瀏覽器不支持getElementsByClassName的解決方法,本文的方法比較完美的解決了這個(gè)問(wèn)題,需要的朋友可以參考下2014-08-08javascript實(shí)現(xiàn)密碼強(qiáng)度顯示
這篇文章主要介紹了使用javascript實(shí)現(xiàn)密碼強(qiáng)度顯示,十分實(shí)用的功能,從個(gè)人項(xiàng)目中移植出來(lái)的,分享給大家,希望大家能夠喜歡。2015-03-03基于JavaScript實(shí)現(xiàn)簡(jiǎn)單的音頻播放功能
本文給大家?guī)?lái)了基于js實(shí)現(xiàn)簡(jiǎn)單的音頻播放功能,數(shù)據(jù)是由后臺(tái)提供的,具體實(shí)例代碼大家參考下本文2018-01-01兼容Firefox的Javascript XSLT 處理XML文件
這篇文章主要介紹了兼容Firefox的Javascript XSLT 處理XML文件,需要的朋友可以參考下2014-12-12