js單元測試框架
前端測試框架對比(js單元測試框架對比)
本文主要目的在於橫評業界主流的幾款前端框架,順帶說下相關的一些內容。
測試分類
通常應用會有 單元測試(Unit tests) 和 功能測試(Functional tests),復雜大型應用可能會有整合測試(Integration tests)。
其中:
- 單元測試:關注應用中每個零部件的正常運轉,防止后續修改影響之前的組件。
- 功能測試:確保其整體表現符合預期,關注能否讓用戶正常使用。
- 整合測試:確保單獨運行正常的零部件整合到一起之后依然能正常運行。
詳細資料1
詳細資料2
開發人員主要關注單元測試,作為開發中的反饋。本文重點討論的單元測試框架。
單元測試的好處: - 如果能通過單元測試,那么通過后續測試且軟件整體正常運行的概率大大提高。
- 單元測試發現的問題定位到細節,容易修改,節省時間。
- 追蹤問題變得更加方便。
選擇單元測試框架
單元測試應該:簡單,快速執行,清晰的錯誤報告。
測試框架基本上都做了同一件事兒:
- 描述你要測試的東西
- 對其進行測試
- 判斷是否符合預期
選擇框架會考慮下面的點: - 斷言(Assertions):用於判斷結果是否符合預期。有些框架需要單獨的斷言庫。
- 適合 TDD / BDD:是否適合 測試驅動型 / 行為驅動型 的測試風格。
- 異步測試:有些框架對異步測試支持良好。
- 使用的語言:大部分 js 測試框架使用 js。
- 用於特定目的:每個框架可能會擅長處理不同的問題。
- 社區是否活躍。
注: - TDD:測試驅動型的開發方式,先寫測試代碼,之后編寫能通過測試的業務代碼,可以不斷的在能通過測試的情況下重構。
- BDD:與 TDD 很相似,測試代碼的風格是預期結果,更關注功能,看起來像需求文檔。
其實都是先寫測試代碼,感覺BDD 風格更人性。
參考鏈接
測試工具的類型
組合使用工具很常見,即使已選框架也能實現類似的功能
- 提供測試框架(Mocha, Jasmine, Jest, Cucumber)
- 提供斷言(Chai, Jasmine, Jest, Unexpected)
- 生成,展示測試結果(Mocha, Jasmine, Jest, Karma)
- 快照測試(Jest, Ava)
- 提供仿真(Sinon, Jasmine, enzyme, Jest, testdouble)
- 生成測試覆蓋率報告(Istanbul, Jest, Blanket)
- 提供類瀏覽器環境(Protractor, Nightwatch, Phantom, Casper)
解釋上面提到的點: - 測試框架,即組織你的測試,當前流行 BDD 的測試結構。
- 快照測試(snapshot testing),測試 UI 或數據結構是否和之前完全一致,通常 UI 測試不在單元測試中
- 仿真(mocks, spies, and stubs):獲取方法的調用信息,模擬方法,模塊,甚至服務器
相關資料
各框架特點
Jest
- facebook 坐庄
- 基於 Jasmine 至今已經做了大量修改添加了很多特性
- 開箱即用配置少,API簡單
- 支持斷言和仿真
- 支持快照測試
- 在隔離環境下測試
- 互動模式選擇要測試的模塊
- 優雅的測試覆蓋率報告,基於Istanbul
- 智能並行測試(參考)
- 較新,社區不十分成熟
- 全局環境,比如 describe 不需要引入直接用
- 較多用於 React 項目(但廣泛支持各種項目)
Mocha
- 靈活(不包括斷言和仿真,自己選對應工具)
流行的選擇:chai,sinon - 社區成熟用的人多,測試各種東西社區都有示例
- 需要較多配置
- 可以使用快照測試,但依然需要額外配置
Jasmine
- 開箱即用(支持斷言和仿真)
- 全局環境
- 比較'老',坑基本都有人踩過了
AVA
- 異步,性能好
- 簡約,清晰
- 快照測試和斷言需要三方支持
Tape
- 體積最小,只提供最關鍵的東西
- 對比其他框架,只提供最底層的 API
總結一下,Mocha 用的人最多,社區最成熟,靈活,可配置性強易拓展,Jest 開箱即用,里邊啥都有提供全面的方案,Tape 最精簡,提供最基礎的東西最底層的API。
選擇測試框架並不是非黑即白的事兒,就像你並不能證明PHP不是最好的語言。
個人傾向 Jest,原因:容易上手,開箱即用,功能全面。
社區意見
下面是在 stackshare 最流行的三個測試框架如下,但應考慮到 Jest 比較年輕,參與投票的時間較短的因素。
下面是三個框架在過去一年里 google 的搜索熱度,但應該考慮到 Jest 比較年輕,大家嘗試新東西,解決新問題,可能會帶來較大搜索量。
下面是用戶使用情況的調查,可以看出, Jest 忠誠度較高,使用后棄用的概率較低,Mocha 和 Jasmine 知名度最高。數據統計於 2017 年。
參考
代碼樣例
要測試的代碼
'use strict' var Math = { add(a, b) { return a + b; } } module.exports = Math;
AVA
const test = require('ava'); const math = require('../Math'); const firstOperand = 2; const secondOperand = 3; test("Math add function", t => { const result = math.add(firstOperand, secondOperand); t.is(result, firstOperand + secondOperand); });
Jasmine
var math = require('../Math'); describe("Math", function() { var firstOperand; var secondOperand; beforeEach(function() { firstOperand = 2; secondOperand = 3; }); it("should add two numbers", function() { var result = math.add(firstOperand, secondOperand); expect(result).toEqual(firstOperand + secondOperand); }); });
Jest
jest.unmock('../Math'); // unmock to use the actual implementation of Math var math = require('../Math'); describe("Math", function() { var firstOperand; var secondOperand; beforeEach(function() { firstOperand = 2; secondOperand = 3; }); it("should add two numbers", function() { var result = math.add(firstOperand, secondOperand); expect(result).toEqual(firstOperand + secondOperand); }); });
Mocha
var assert = require('assert'); // nodejs 內建斷言 var math = require('../Math'); describe("Math", function() { var firstOperand; var secondOperand; beforeEach(function() { firstOperand = 2; secondOperand = 3; }); it("should add two numbers", function() { var result = math.add(firstOperand, secondOperand); assert.equal(result, firstOperand + secondOperand); }); });
Tape
var test = require('tape'); var math = require('../Math'); var firstOperand = 2; var secondOperand = 3; test("Math add function", function(t) { var result = math.add(firstOperand, secondOperand); t.equal(result, firstOperand + secondOperand); t.end(); });