一、背景
隨著平臺功能越來越多,接口及關(guān)聯(lián)數(shù)據(jù)復(fù)雜,傳統(tǒng)功能測試無法滿足覆蓋測試要求,顧搭建針對TypeScript的自動化單元測試。
該測試體系具有以下優(yōu)點:
- 縮短測試時間:通過自動化測試體系,可以一鍵執(zhí)行測試用例,生成測試報告以及代碼覆蓋率報告。開發(fā)人員可根據(jù)報告分析出問題所在,以及未測試的代碼。
- 更高的投資回報率:自動化測試比傳統(tǒng)功能測試速度更快,且測試用例可重用,避免功能開發(fā)后“關(guān)聯(lián)功能”的重復(fù)測試。減少了測試以及開發(fā)時間,對快速相應(yīng)要求極高的市場極為有益。
- 早期缺陷檢測:編寫白盒測試用例階段,相當于做了一次代碼走查,可分析出代碼存在的淺顯邏輯錯誤;白盒測試執(zhí)行階段,相當于將所有功能執(zhí)行一至多遍,將代碼邏輯缺陷暴露在系統(tǒng)測試之前。
- 更高的測試覆蓋率:自動化單元測試的測試范圍更全面,相較于傳統(tǒng)測試方式,可覆蓋更全面的代碼邏輯以及功能邏輯,從而降低發(fā)布后的故障概率。
二、技術(shù)棧概念
Karma(卡瑪)是一個基于node.js的JavaScript測試執(zhí)行過程管理工具,它可以拉起所有主流瀏覽器,加載測試腳本,然后運行測試用例,完成后關(guān)閉瀏覽器。
Mocha(摩卡)是一個單元測試測試框架/庫,它可以用來寫測試用例。
Chai 是用于節(jié)點和瀏覽器的BDD / TDD斷言庫,可以與任何javascript測試框架完美地配對,支持BDD風格的expect、should和TDD風格的assert。
我們主要就是用Karma與Mocha來實現(xiàn)自動化測試。
三、技術(shù)棧的安裝及使用
Node.js
Node.js是一個基于Chrome V8引擎的JavaScript運行環(huán)境,讓JavaScript運行在服務(wù)端的開發(fā)平臺。是部署自動化單元測試體系不可或缺的環(huán)境。
3.1下載NodeJS
NodeJS安裝包及源碼下載地址為:
NodeJS
根據(jù)不同的系統(tǒng)選擇你需要的安裝包。
3.2Wondows上安裝NodeJS
-
雙擊NodeJs安裝文件,將出現(xiàn)如下界面:
?2、點擊Next按鈕,將出現(xiàn)如下界面,并勾選接受協(xié)議選項,點擊Next按鈕:
3、NodeJs默認安裝目錄為"C:\Program Files\nodejs\",如需更改安裝目錄,請點擊Change按鈕,更改完畢后點擊Next按鈕
4、點擊屬性圖標來選擇需要的安裝模式,然后點擊Next按鈕,如下圖:
5、點擊Install開始安裝NodeJS
6、安裝完成后可以同命令行來檢測是否安裝成功以及環(huán)境變量是否配置成功:
- 同時按住Win+R鍵打開運行面板
- 在運行面板輸入框中輸入cmd并點擊確定
- 在命令行界面輸入path并按回車鍵,查看結(jié)果中是否含有你的NodeJs安裝目錄
- 在命令行界面輸入node --version并按回車鍵,可以查看NodeJs版本
3.3完成NodeJS環(huán)境搭建
至此就完成了NodeJS環(huán)境的搭建了,后續(xù)就可以進行接下來的步驟了,例如:項目的創(chuàng)建、搭建Mocha測試框架等。
四、Mocha
mocha是一個功能豐富的JavaScript測試框架,運行在NodeJs和瀏覽器中。Mocha測試連續(xù)運行,允許靈活和準確的報告,同時將未補貨的異常映射到正確的測試用例。
4.1安裝Mocha
使用NPM全局安裝也可以作為項目的依賴進行安裝
//全局安裝
$ npm install --global mocha
//作為項目依賴進行安裝
$ npm install --save-dev mocha
或直接在項目配置文件package.json中添加相應(yīng)庫的依賴,例如:
"@types/mocha": "^9.1.0",
"mocha": "^9.2.2"
4.2使用Mocha
Mocha中的BBD接口提供了describe、context,it,specify,before,after,beforeEach,afterEach接口。
context接口只是一個別名describe,行為方式相同;它只是提供了一重讓測試更容易閱讀和組織的方法;同樣,specify是別名it。
describe接口是一個描述,用來定義一個測試塊,該測試塊有固定的生命周期:before、after、beforeEach、afterEach以及測試用例it。
用法示例:
describe('test', function() {
// 在本測試塊的所有測試用例之前執(zhí)行且僅執(zhí)行一次
before(function() {
});
// 在本測試塊的所有測試用例之后執(zhí)行且僅執(zhí)行一次
after(function() {
});
// 在測試塊的每個測試用例之前執(zhí)行(有幾個測試用例it,就執(zhí)行幾次)
beforeEach(function() {1
});
// 在測試塊的每個測試用例之后執(zhí)行(同上)
afterEach(function() {17
});
// 測試用例
it('test item1', function () {
})
});
4.3斷言
mocha允許你是用任意你喜歡的斷言庫,若不引入其他斷言庫則會使用NodeJs中內(nèi)置斷言模塊作為斷言。如果能夠拋出一個錯誤,它就能夠運行。本測試體系使用chai作為斷言庫,詳情請參照chai。
五、Chai
chai是一個BDD和TDD診斷庫,可與任何JavaScript測試框架完美搭配。包含三個斷言庫,支持BDD風格的expect、should和TDD風格的assert。
TDD:測試驅(qū)動開發(fā)。是敏捷開發(fā)中的一項核心實踐和技術(shù),也是一種設(shè)計方法論。TDD的原理是在開發(fā)功能代碼之前,先編寫單元測試用例代碼,測試代碼確定需要編寫什么產(chǎn)品代碼。
BDD:行為驅(qū)動開發(fā)。是測試驅(qū)動開發(fā)的延伸,強調(diào)使用DLS描述用戶行為,定義業(yè)務(wù)需求,是需求分析人員、開發(fā)人員與測試人員進行溝通的有效方法。行為驅(qū)動開發(fā)的核心在于“行為”,由“行為”來確定以及推動開發(fā)。
5.1安裝Chai
使用NPM作為項目的依賴進行安裝
$ npm install --save-dev chai
或直接在項目配置文件package.json中添加相應(yīng)庫的依賴后再進行安裝,例如:
"@types/chai": "^4.3.0",
"chai": "^4.3.6"
5.2使用Chai
在您的代碼中導入chai庫,然后選擇您想要使用的樣式之一(assert、expect、should)
const { assert } = require('chai'); // Using Assert style
const { expect } = require('chai'); // Using Expect style
const { should } = require('chai'); // Using Should style
Chai斷言庫具有一定的斷言規(guī)范, 本文主要使用expect斷言庫:
- not對之后的斷言取反;
expect(foo).to.not.equal('bar');
expect(goodFn).to.not.throw(Error);
expect({ foo: 'baz'}).to.have.property('foo').and.not.equal('bar');
- deep設(shè)置deep標記,然后使用equal和property斷言,該標記可以讓其后的斷言不是比較對象本身,而是遞歸比較對象的鍵值對;
expect(foo).to.deep.equal({ bar: 'baz'});
expect({ foo: { bar: { baz: 'quux'}}}).to.have.deep.property('foo.bar.baz', 'quux');
- a(type)/an(type)被測試的值的類型,a和an斷言即可作為語言鏈又可作為斷言使用;
// 類型斷言
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(null).to.be.a('null');
expect(undefined).to.be.an('undefined');
expect(new Error).to.be.an('error');
expect(new Promise).to.be.a('promise');
expect(new Float32Array()).to.be.a('float32array');
expect(Symbol()).to.be.a('symbol');
// es6 overrides
expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo');
// language chain
expect(foo).to.be.an.instanceof(Foo);
- include(value)/contains(value)即可作為屬性類斷言前綴語言鏈又可作為作為判斷數(shù)組、字符串是否包含某值的斷言使用。當作為語言鏈使用時,常用于key()斷言之前;
expect([1, 2, 3]).to.include(2);
expect('foobar').to.include('bar');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
- ok斷言目標為真值;
expect('everything').to.be.ok;
expect(1).to.be.ok;
expect(false).to.not.be.ok;
expect(null).to.not.be.ok;
- true斷言目標為true,注意,這里與ok的區(qū)別是不進行類型轉(zhuǎn)換,只能為true才能通過斷言;
expect(true).to.be.true;
expect(1)to.not.be.true;
-
false斷言目標為false,與true相似;
expect(false).to.be.false;
expect(0).to.not.be.false;
-
null斷言目標為null;
expect(null).to.be.null;
expect(undefined).to.not.be.null;
-
undefined斷言目標為undefined;
expect(undefined).to.be.undefined;
expect(null).to.not.be.undefined;
-
exist斷言目標存在,即非null也非undefined;
let foo = 'hi';
let bar = null;
let baz;
expect(foo).to.exist;
expect(bar).to.not.exist;
expect(baz).to.not.exist;
-
empty斷言目標的長度為0。對于數(shù)組和字符串,它檢查length屬性,對于對象,它檢查可枚舉屬性的數(shù)量;
expect([]).to.be.empty;
expect('').to.be.empty;
expect({}).to.be.empty;
-
equal(value)斷言目標嚴格等于(===)value,另外,如果設(shè)置了deep標記,則斷言目標深度等于value;
expect('hello').to.equal('hello');
expect(42).to.equal(42);
expect(1).to.not.equal(true);
expect({ foo: 'bar'}).to.not.equal({ foo: 'bar'});
expect({ foo: 'bar'}).to.deep.equal({foo: 'bar'});
-
above(value)斷言目標大于(超過)value;
expect(10).to.be.above(5);
-
least(value)斷言目標不小于(大于或等于)value;
expect(10).to.be.at.least(10);
-
below(value)斷言目標小于value;
expect(5).to.be.below(10);
-
most(value)斷言目標不大于(小于或等于)value;
expect(5).to.be.at.most(5);
-
within(start,finish)斷言目標在某個區(qū)間內(nèi);
expect(7).to.be.within(5, 10);
-
instanceof(constructor)斷言目標是構(gòu)造函數(shù)constructor的一個實例
let model = new M3D.Model();
expect(model).to.be.an.instanceof(M3D.Model);
expect([1, 2, 3]).to.be.an.instanceof(Array);
-
string斷言目標字符串包含另一個字符串
expect('foobar').to.have.string('bar');
在您編寫完斷言代碼之后就希望運行這個斷言,判斷該斷言是否正確,這時,就用到了我們的運行環(huán)境Karma庫了。
六、Karma
Karma為前端自動化測試提供了跨瀏覽器測試的能力,它集成了像Jasmine(基于BDD的測試框架)、PhantomJs(無界面的瀏覽器)這些測試套件。還有一些其他又用的功能,比如生成代碼覆蓋率報告等。
該工具可用于測試所有主流 Web 瀏覽器,也可集成到 CI 工具,也可和其他代碼編輯器(例如 VsCode)一起使用。這個測試工具的一個強大特性就是,它可以監(jiān)控(Watch)文件的變化,然后自行執(zhí)行,通過 console.log
顯示測試結(jié)果。主要提供以下功能:
- 提供真實環(huán)境,可以配置各種 chrome、firefox 等各種瀏覽器環(huán)境或者
Phantomjs
等無頭瀏覽器環(huán)境 - 可控制自動化測試流程,比如編輯器保存時自動全部全部測試用例
- 強大適配器,可以在
karma
上面配置jasmine
,mocha
等單元測試框架。 - 配置方便
6.1安裝Karma
使用NPM作為項目的依賴進行安裝
$ npm install karma -g
或直接在項目配置文件package.json中添加相應(yīng)庫的依賴后再進行安裝,例如:
"karma": "^6.3.17"
本測試體系中使用的測試框架為Mocha,所以需添加關(guān)聯(lián)庫karma-mocha
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
本測試體系中使用的斷言庫為Chai,所以需添加關(guān)聯(lián)庫karma-chai
"karma-chai": "^0.1.0",
若單元測試用例語言為TypeScript,則需添加關(guān)聯(lián)庫karma-typescript
"karma-typescript": "^5.5.3",
若需要在谷歌瀏覽器運行測試用例,則需添加關(guān)聯(lián)庫karma-chrome-launcher
"karma-chrome-launcher": "^3.1.1",
若需要生成html的測試報告,則需要添加關(guān)聯(lián)庫karma-htmlfile-reporter
"karma-htmlfile-reporter": "^0.3.8",
當然代碼覆蓋率也同樣少不了關(guān)聯(lián)庫,karma-coverage
"karma-coverage": "^2.2.0",
6.2配置karma
運行Karma之前需初始化:karma init
或直接使用配置文件:
// Karma 相關(guān)配置文件
//karma 的服務(wù)器將我們的服務(wù)內(nèi)容放在了 / base 之下,我們在使用的時候,必須特別注意這一點。
module.exports = function (config) {
config.set({
// 基礎(chǔ)路徑,用在files,exclude屬性上
basePath: '',
// 識別ts
mime: {
'text/x-typescript': ['ts', 'tsx']
},
//依賴的框架
frameworks: ['mocha', 'chai', 'karma-typescript'],
karmaTypescriptConfig: {
compilerOptions: {
module: "commonjs"
},
tsconfig: "./tsconfig.json"
},
// 需要加載到瀏覽器的文件列表
files: [
'TestDemo/TestDemo.ts',
'Test/TestDemo.test.ts',
],
// 排除的文件列表
exclude: [
"node_moudules",
],
// 在瀏覽器使用之前處理匹配的文件
preprocessors: {
'TestDemo/*.ts': ['karma-typescript', 'coverage'],
'Test/*.ts': ['karma-typescript'],
},
//點擊debug按鈕在debug.html中展示測試結(jié)果
client: {
mocha: {
// change Karma's debug.html to the mocha web reporter
reporter: 'html',
// require specific files after Mocha is initialized
//require: [require.resolve('bdd-lazy-var/bdd_lazy_var_global')],
// custom ui, defined in required file above
//ui: 'bdd-lazy-var/global',
//grep: ' <pattern> ',
// expose: [' body '],
//opts: ' test/mocha.opts '
}
},
// 使用測試結(jié)果報告者
reporters: ['mocha', 'html', 'coverage'],
//控制臺生成mocha樣式的測試結(jié)論
mochaReporter: {
output: 'autowatch'
},
//生成本地的測試報告
htmlReporter: {
outputFile: 'reporter/testResult.html',
// Optional
pageTitle: 'Reader 模塊測試用例',
subPageTitle: '讀取模型相關(guān)的單元測試用例類列表',
groupSuites: true,
useCompactStyle: true,
useLegacyStyle: true
},
//覆蓋率
coverageReporter: {
type: 'html',
dir: 'coverage/',
file: 'coverage.html'
},
// 服務(wù)端口號
port: 9877,
// 啟用或禁用輸出報告或者日志中的顏色
colors: true,
// 日志等級
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// 啟用或禁用自動檢測文件變化進行測試
autoWatch: true,
// 測試啟動的瀏覽器
// available browser launchers: https://www.npmjs.com/search?q=keywords:karma-launcher
browsers: ['Chrome'],
// 開啟或禁用持續(xù)集成模式
// 設(shè)置為true, Karma將打開瀏覽器,執(zhí)行測試并最后退出
singleRun: false,
// 并發(fā)級別(啟動的瀏覽器數(shù))
concurrency: Infinity,
})
}
具體karma配置內(nèi)容,可參考官方文檔:https://karma-runner.github.io/latest/config/configuration-file.html
6.3運行karma
Karma的運行命令為karma start
運行的結(jié)果首先可以在控制臺詳細的顯示出來:
其次若配置了測試啟動的瀏覽器,那么就會自動打開瀏覽器進行顯示您的測試結(jié)果
點擊界面上DEBUG按鈕,跳轉(zhuǎn)至全部測試用例界面,可以查看每個測試用例的執(zhí)行情況,并且可以單獨運行某一個測試用例。
配置文件中的coverageReporter
代表著代碼覆蓋率報告相關(guān)配置,例如:
//覆蓋率
coverageReporter: {
type: 'html',//代碼覆蓋率報告類型
dir: 'coverage/',//代碼覆蓋率報告生成路徑
},
- type:指一個記錄類型
-
html(默認) lcov(lcov and html) lcovonly text text-summary cobertura(xml格式的支持Jenkins) teamcity json json-summary in-memory none
- dir:將用于輸出代碼覆蓋率報告
- subdir:將用于補充dir選項來生成完整的輸出目錄路徑。
- file:如果您使用
cobertura
、lcovonly
、teamcity
、text
、text-summary
中的一個,則需要指定輸出的文件。 - check:將用于配置覆蓋率結(jié)果最低閾值,如果不符合,karma將返回一個錯誤。閾值,指定為正數(shù)時所需的最小百分比。當一個閾值被指定為負數(shù)時,它表示允許的未覆蓋實體的最大數(shù)量。
- watermarks:將用于設(shè)置覆蓋閾值顏色。第一個數(shù)字是紅色和黃色之間的閾值,第二個數(shù)字是黃色和綠色之間的閾值。
watermarks: {
statements: [ 50, 75 ],
functions: [ 50, 75 ],
branches: [ 50, 75 ],
lines: [ 50, 75 ]
}
七、示例
下面我們將使用兩種方式配置本單元測試體系進行測試。
7.1新建項目
7.1.1創(chuàng)建項目
以Visual Studio為例
- 啟動Visual Studio,選擇 創(chuàng)建新項目 ;
- 選擇創(chuàng)建TypeScript的空白Node.js應(yīng)用程序;
- 填寫項目名稱、項目存放位置,然后點擊創(chuàng)建。即可生成對應(yīng)的項目;
-
創(chuàng)建成功后項目結(jié)構(gòu)如下:
-
npm文件夾存放項目運行所依賴的庫;
-
package.json為項目描述文件,包含項目名稱、版本、入口文件等相關(guān)信息。
7.1.2添加測試庫依賴
打開項目中package.json文件,在devDependencies節(jié)點添加如下引用(若有重復(fù)請刪除):
具體代碼如下:
"@types/node": "^14.14.7",
"typescript": "^4.0.5",
"@types/chai": "^4.3.0",
"@types/mocha": "^9.1.0",
"chai": "^4.3.6",
"karma": "^6.3.17",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.1",
"karma-coverage": "^2.2.0",
"karma-htmlfile-reporter": "^0.3.8",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-typescript": "^5.5.3",
"mocha": "^9.2.2"
然后在項目的npm節(jié)點點擊鼠標右鍵選擇安裝npm包,等待安裝完成。
7.1.3添加工程文件夾以及代碼文件
- 在工程中的項目名稱位置點擊鼠標右鍵,選擇添加->新建文件夾,輸入文件夾名稱
- 在上一步驟創(chuàng)建的文件夾位置點擊鼠標右鍵,選擇添加->新建項,選擇"TypeScript文件"
- 在上一步驟創(chuàng)建的TypeScript中添加demo邏輯
export class TestDemo {
/**
* @description 計算兩個數(shù)值之和
* @param a 第一個數(shù)值
* @param b 第二個數(shù)值
*/
public static add(a: number, b: number): number {
if (typeof a === "number" && typeof b === "number") {
return a + b;
}
return null;
}
}
7.1.4添加測試文件夾以及測試用例
- 在工程中的項目名稱位置點擊鼠標右鍵,選擇添加->新建文件夾,輸入文件夾名稱
- 在上一步驟創(chuàng)建的文件夾位置點擊鼠標右鍵,選擇添加->新建項,選擇"TypeScript文件"
- 在上一步驟添加的TypeScript文件中添加單元測試用例
import { TestDemo } from "../TestDemo/TestDemo";
const { expect } = require("chai");
describe("TestDemo單元測試用例:參數(shù)為3和5", function () {
it("", function () {
let result = TestDemo.add(3, 5);
expect(result).to.equal(8);
});
});
7.1.5添加karma測試配置文件
在工程中的項目名稱位置點擊鼠標右鍵,選擇添加->新建項,選擇"JavaScript文件",文件名為"karma.conf.js",添加配置json并修改其中加載到瀏覽器的文件列表項:
files: [
'TestDemo/TestDemo.ts',
'Test/TestDemo.test.ts',
],
7.1.6運行測試用例
- 在工程中的項目名稱位置點擊鼠標右鍵,選擇在終端打開:
2、執(zhí)行測試用例,在終端輸入"karma start"后回車
7.2.2添加測試文件夾以及測試用例
- 我的TypeScript工程M3DDemo,工程下存在代碼文件src/Test.js,且存在方法如下:
var add = function (a, b) {
if (typeof a === "number" && typeof b === "number") {
return a + b;
}
return null;
}
- 創(chuàng)建test的測試文件夾,在我的工程中項目名稱位置點擊鼠標右鍵,選擇添加->新建文件夾->輸入test;
- 創(chuàng)建Test.test.js單元測試文件:在上一步驟創(chuàng)建的test文件夾位置點擊鼠標右鍵,選擇添加->新建項,選擇JavaScript文件,修改文件名稱后點擊添加。
- 在上一步驟創(chuàng)建的Test.test.js中添加測試用例:
//JavaScript不能添加require
//const { expect } = require("chai");
describe("Test單元測試用例", function () {
it("add接口單元測試用例:參數(shù)為3和5", function () {
let result = add(3, 5);
expect(result).to.equal(8);
});
});
八、常見問題
8.1 karma無法運行
輸入karma start運行時提示karma:無法將"karma"項識別為 cmdlet、函數(shù)、腳本文件或可運行程序的名稱。請檢查名稱的拼寫,如果包括路徑,請確保路徑正確,然后再試一次。
解決方法:文章來源:http://www.zghlxwxcb.cn/news/detail-426244.html
- 查看所有依賴包是否已安裝完成;
- 在終端執(zhí)行npm install -g karma-cli,全局安裝karma-cli。
8.2 karma無法加載文件,未對karma.ps1進行數(shù)字簽名
解決方法:
- 以管理員身份打開powershell;
- 執(zhí)行Set-ExecutionPolicy -ExecutionPolicy UNRESTRICTED;
- 輸入Y,回車。
8.3 執(zhí)行karma之后未自動啟動瀏覽器
解決方法:
- 檢查是否添加配置karma.conf.js;
- 若不需要添加配置,則在瀏覽器中手動輸入控制臺輸出的地址即可。
8.4 You need to include some adapter that implements _karma_.start method
解決方法:添加karma.conf.js。文章來源地址http://www.zghlxwxcb.cn/news/detail-426244.html
到了這里,關(guān)于Karma、Mocha和Chai自動化測試解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!