測試代碼是確保代碼穩定的第一步。能做到這一點的最佳方法之一就是使用單元測試,確保應用程序中的每個較小的功能都按應有的方式運行——尤其是當應用程序接收到極端或無效輸入,甚至可能有害的輸入時。
為什么要進行單元測試?
進行單元測試有許多不同的方法,一些主要目的是:
- 驗證功能:單元測試確保代碼做正確的事情并且不做任何不應該做的事情——大多數錯誤發生在這里。
- 防止代碼回歸:當我們發現錯誤時,添加單元測試來檢查場景可以防止代碼更改在將來重新引入錯誤。
- 記錄代碼:通過正確的單元測試,一套完整的測試和結果提供了應用程序應該如何工作的規范。
- 保護您的應用程序:單元測試可以檢查可利用的漏洞(例如啟用惡意 SQL 注入的漏洞)。
范圍界定和編寫單元測試
使用單元測試框架使我們能夠快速編寫和自動化我們的測試,并將它們集成到我們的開發和部署過程中。這些框架通常支持前端和后端 JavaScript 代碼的測試。
以下是幫助你編寫性能單元測試和可測試代碼的一些通用指南。
保持單元測試簡短而簡單
不要編寫過重的單元測試,測試應該只有幾行代碼來檢查應用程序的簡短功能塊。
考慮正面和負面的測試用例
雖然編寫正確執行函數的測試是有用的,但是,編寫更廣泛的測試集來檢查函數在被濫用或在極端情況下是否正確或者失敗同樣重要。這些負面測試可能更有價值,因為它們有助于預測意外情況,例如函數何時應引發異?;驊绾翁幚斫邮崭袷藉e誤的數據。
分解長而復雜的函數
包含大量邏輯的大型函數難以測試;包含太多操作則難以有效地測試每個變量。如果函數太復雜,請將其拆分為較小的函數以進行單獨測試。
避免網絡和數據庫連接
單元測試應該是快速和輕量級的,但是進行網絡調用或連接到其他應用程序或進程的功能需要長時間才能執行。這使得同時運行多個操作變得具有挑戰性,且會產生更脆弱的代碼。你可以在單元測試中調用模擬的網絡或數據庫而非真實地連接網絡。而如果要進行包含真實的網絡和數據庫連接的測試,應當在稱為集成測試(所有的單元或模塊被組合在一起并作為一個整體進行測試)中進行而不是單元測試。
如何編寫單元測試
我們已經回顧了一些單元測試的最佳實踐,現在準備好用 JavaScript 編寫你的第一個單元測試了。
本教程使用 Mocha 框架 —— 最流行的單元測試之一。每個測試框架都略有不同,但它們足夠相似,學習基本概念將使你能夠輕松地在它們之間切換。
在開始前,請確保你的電腦上安裝了 Node.js 環境。
創建一個新項目
首先打開一個終端窗口或命令提示符到一個新的項目文件夾。然后,通過以下命令在其中創建一個新的 Node.js 項目。
npm init -y
這會在文件夾中創建一個文件 package.json ,使你能夠使用 npm install -D mocha 命令來安裝 mocha 框架。
接下來,在代碼編輯器中打開 package.json 文件并將 test script 替換為:mocha
"scripts": {
"test": "mocha"
},
實現一個類
接下來,編寫一個簡單的紅綠燈系統進行單元測試。
在項目目錄中,創建一個名為 traffic.js文件,其中是一個 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;
這個類由四部分組成:
TrafficLight.colors:交通燈顏色的常量屬性。lightIndex:一個變量,跟蹤當前交通燈顏色的索引。light:以字符串形式返回當前交通燈顏色的類屬性。next():將紅綠燈更改為下一個燈光顏色的功能。
配置和添加我們的第一個單元測試
現在是時候圍繞代碼添加一些單元測試了。
在項目中創建一個名為 test 的目錄,這是 Mocha 默認檢查單元測試的地方。然后,在新的測試文件夾中添加一個名為 traffic.test.js 的文件。
接下來,在文件頂部導入 TrafficLight 類:
const TrafficLight = require( "../traffic" );
我們還將使用該 assert 模塊進行測試,因此在你的代碼中需要引入它:
const assert = require( "assert" );
在 Mocha 中我們可以使用 describe() 這個函數將單元測試進行分組集合,如下:
describe( "TrafficLight", function () {
});
然后,我們將創建一些單元測試來驗證他們自己的子組中的交通顏色:
describe( "TrafficLight", function () {
describe( "colors", function () {
});
});
對于第一個單元測試,我們可以驗證 colors 只有三種狀態:綠色、黃色和紅色。測試方式是使用 describe() 組內的 it() 函數定義的,因此編寫測試如下:
describe( "TrafficLight", function () {
describe( "colors", function () {
it( "has 3 states", function () {
const traffic = new TrafficLight();
assert.equal( 3, TrafficLight.colors.length );
});
});
});
現在讓我們運行單元測試,看看它是否通過。
在終端窗口中運行 npm test,如果一切正確,Mocha 會打印出單元測試運行的結果。
添加更多單元測試
我們的項目現在已準備好運行單元測試,因此我們可以添加更多測試以確保我們的代碼正常工作。
首先,向colors組中添加一個單元測試,以驗證紅綠燈顏色是否正確且有序。這是實現此測試的一種方法:
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 ] );
}
});
其次,測試next()方法看它是否正確地改變了交通信號燈。創建一個新的子組并添加兩個單元測試:一個檢查燈光是否以正確的順序變化,另一個檢查燈光是否能循環在紅燈之后變為綠燈:
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 ] );
});
});
現在,當我們重新運行測試時,我們會看到其中一個測試失敗了。這是因為 TrafficLight 類中有一個錯誤。
修復錯誤
為方便調試本例提前注明好的錯誤代碼位置,我們再次打開 TrafficLight 類并找到 next() 函數內的這句注釋:// This is intentionally wrong!。
從單元測試中我們知道這個函數沒有正確地循環回 green,我們可以看到代碼是在判斷lightIndex值超過交通燈顏色的數量時給索引設置了0,這顯然是不對的,我們必須在值達到確切的顏色數時立即將索引修改為0:
// This is intentionally wrong!
if( this.lightIndex === TrafficLight.colors.length ) {
this.lightIndex = 0;
}
現在你所有的單元測試都應該通過了。而這帶來的好處是即使TrafficLight這個類被重構或大量修改,我們的單元測試也會在它到達用戶之前捕獲這個錯誤。
最后
單元測試易于設置,是軟件開發的有效工具。它們有助于及早消除錯誤并防止它們重現。這使項目更易于管理和維護,即使它們變得更大更復雜——尤其是在大型開發團隊中。像這樣的自動化測試還使開發人員能夠重構和優化他們的代碼,而不必擔心新代碼的行為是否正確。
以上就是詳解如何用JavaScript編寫一個單元測試的詳細內容,更多關于JavaScript單元測試的資料請關注其它相關文章!