- 測試可以確保得到預期的結果
- 作為現有程式碼行為的描述
- 促使開發者寫可測試的程式碼,一般可測試的程式碼可讀性也會高一點
- 如果相依的元件有修改,受影響的元件能在測試中發現錯誤
測試類型
- 單元測試
- 單元可以是一個函數,也可以是一個模塊或一個類別
- 基本特徵就是只要輸入不變,必定返回同樣的輸出
- 越容易單元測試,就代表它的模塊化結構越好,模塊之間的耦合越弱
- React 的組件化和函數式程式,適合進行單元測試
- 功能測試
- 相當於是黑盒測試,測試者不瞭解進程的內部情況,不需要具備編程語言的專門知識,只知道進程的輸入、輸出和功能,從用户的角度針對軟體界面、功能和外部結構進行測試,不考慮內部的邏輯
- 集成測試
- 在單元測試的基礎上,將所有模塊按照設計要求組裝成子系統或者系統,進行測試
- 冒煙測試
- 在正式全面的測試之前,對主要功能進行的與測試,確認主要功能是否滿足需要,軟體是否能正常運行
開發模式
- 測試驅動開發 TDD (Testing Driven Development)
- 先寫測試,後寫功能實現
- 強調的是一種開發方式,以測試來驅動整個專案,即先根據接口完成測試程式碼,再編寫功能程式碼
- 行為驅動測試 BDD (Behavior Driven Development)
- 強調的是寫測試的風格,注重以通用語言表達測試,讓整個專案的各個成員(開發者、QA、相關業務人員)都能看懂測試,甚至編寫測試
- TDD 和 BDD 有各自的使用場景,BDD 一般偏向於系統功能和業務邏輯的自動化測試設計;而 TDD 在快速開發並測試功能模塊的過程中則更加高效,以快速完成開發為目的
單元測試技術的實現原理
- 測試框架
- 判斷內部是否存在異常,存在則 console 出對應的 text 信息
- 斷言庫
- 當 actual 值與 expect 值不一樣時,就拋出異常,供外部測試框架檢測到,這就是為什麼有些測試框架可以自由選擇斷言庫的原因,只要可以拋出異常,外部測試框架就可以工作
- mock 函數
- 創建一個新的函數,用這個函數來取代原來的函數,同時在這個新函數上添加一些額外的屬性,例如 called、calledWithArguments 等信息
function describe (text, fn) {
try {
fn.apply(...);
} catch(e) {
assert(text)
}
}
function fn () {
while (...) {
beforeEach();
it(text, function () {
assert();
});
afterEach();
}
}
function it(text, fn) {
...
fn(text)
...
}
function assert (expect, actual) {
if (expect not equla actual ) {
throw new Error(text);
}
}
function fn () {
...
}
function spy(cb) {
var proxy = function () {
...
}
proxy.called = false;
proxy.returnValue = '...';
...
return proxy;
}
var proxy = spy(fn); // 得到一个 mock 函数
如何寫單元測試
- 只考慮測試,不考慮內部實現
- 不要做無謂的斷言
- 讓每個單元測試保持獨立
- 所有的方法都應該寫單元測試
- 充分考慮數據的邊界條件
- 對重點、複雜、核心代碼,重點測試
- 利用 AOP (beforeEach、afterEach),減少測試代碼數量,避免無用功能
- 使用最合適的斷言方式
測試技巧
-
BDD => given 給定、when 當、then 然後
- 我有一個筆記列表,當我試著刪除一個筆記時,然後筆記應從列表中刪除
-
每個測試之間都不能互相污染,可以利用 afterEach(fn) 或 beforeEach(fn)
-
只跑有更新的測試,不用跑全部
jest `gst | grep spec | cut -d":" -f2` -u
node node_modules/jest/bin/jest.js `gst | grep spec | cut -d":" -f2` -u
測試覆蓋率
測試覆蓋率是一個測試指標,用來描述測試用例的程式碼是否都被執行
指標
- 行覆蓋率(line coverage):是否每一行都執行了
- 函數覆蓋率(function coverage):是否每一個函數都調用了
- 分支覆蓋率(branch coverage):是否每個 if 代碼塊都執行了
- 語句覆蓋率(statement coverage):是否每個語句都執行了