目前開發大型應用,測試
是一個很是重要的環節,可是大多數前端開發者對測試相關的知識是比較缺少的。由於可能項目開發週期短根本沒有機會寫,因此你沒有辦法體會到前端自動化測試的重要性。javascript
來講說爲何前端自動化測試如此重要!前端
先看看前端常見的問題:java
速定位bug
增長自動化測試後:node
可靠性
提升代碼質量
方便維護
單元測試(Unit Testing)
es6
單元測試是指對程序中最小可測試單元進行的測試,例如測試一個函數
、一個模塊
、一個組件
...web
集成測試(Integration Testing)
npm
將已測試過的單元測試函數進行組合集成暴露出的高層函數或類的封裝,對這些函數或類進行的測試json
端到端測試(E2E Testing)
打開應用程序模擬輸入,檢查功能以及界面是否正確瀏覽器
TDD是測試驅動開發(Test-Driven Development)
bash
TDD的原理是在開發功能代碼以前,先編寫單元測試用例代碼
BDD是行爲驅動開發(Behavior-Driven Development)
系統業務專家、開發者、測試人員一塊兒合做,分析軟件的需求,而後將這些需求寫成一個個的故事。開發者負責填充這些故事的內容,保證程序實現效果與用戶需求一致。
小結:
TDD是先寫測試再開發 (通常都是單元測試,白盒測試);而BDD則是按照用戶的行爲來開發,再根據用戶的行爲編寫測試用例 (通常都是集成測試,黑盒測試)
看到這裏Facebook
都在推Jest,你還不學嗎? Jest也有一些缺陷就是不能像Karma
這樣直接跑在瀏覽器上,它採用的是jsdom
,優點是簡單、0配置! 後續咱們經過Jest來聊聊前端自動化測試。
在說Jest
測試以前,先來看看之前咱們是怎樣測試的
const parser = (str) =>{
const obj = {};
str.replace(/([^&=]*)=([^&=]*)/g,function(){
obj[arguments[1]] = arguments[2];
});
return obj;
}
const stringify = (obj) =>{
const arr = [];
for(let key in obj){
arr.push(`${key}=${obj[key]}`);
}
return arr.join('&');
}
// console.log(parser('name=webyouxuan')); // {name:'webyouxuan'}
// console.log(stringify({name:'webyouxuan'})) // name=webyouxuan
複製代碼
咱們每寫完一個功能,都先須要手動測試功能是否正常,測試後可能會將測試代碼註釋起來,這樣會產生一系列問題。由於會污染源代碼,全部的測試代碼和源代碼混合在一塊兒。若是刪除掉,下次測試還須要從新編寫。
因此測試框架
就幫咱們解決了上述的問題
Jest是基於模塊
的,咱們須要將代碼包裝成模塊的方式,分別使用 export
將 parser
、stringify
這兩個方法導出。
安裝jest
npm init -y # 初始化pacakge.json
npm i jest
複製代碼
咱們創建一個qs.test.js
來專門編寫測試用例,這裏的用例你能夠認爲就是一條測試功能 (後綴要以.test.js結尾,這樣jest測試時默認會調用這個文件)。
import {parser,stringify} from './qs';
it('測試 parser 是否能正常解析結果',()=>{
// expect 斷言,判斷解析出來的結果是否和 {name:'webyouxuan'}相等
expect(parser(`name=webyouxuan`)).toEqual({name:'webyouxuan'});
})
複製代碼
jest
默認自帶斷言功能,斷言的意思就是判斷是否是這個樣子,我判定你今天沒吃飯~,結果你吃了,說明此次斷言就失敗了,測試就沒法經過。
經過配置scripts
來執行命令
"scripts": {
"test": "jest"
}
複製代碼
執行 npm run test
,惋惜的是默認在node
環境下不支持es6模塊
的語法,須要babel
轉義,固然你也能夠直接使用commonjs規範來導出方法,由於大多數如今開發都採用es6模塊,因此安裝一下便可。
# core是babel的核心包 preset-env將es6轉化成es5
npm i @babel/core @babel/preset-env --save-dev
複製代碼
而且須要配置.babelrc
文件,告訴babel用什麼來轉義
{
"presets":[
[
"@babel/preset-env",{
"targets": {"node":"current"}
}
]
]
}
複製代碼
默認Jest中集成了babel-jest
,運行時默認會調用.babelrc
進行轉義,能夠直接將es6轉成es5語法。 運行 npm run test
出現:
繼續編寫第二個用例
import {parser,stringify} from './qs';
describe('測試qs 庫',()=>{
it('測試 parser 是否能正常解析結果',()=>{
expect(parser(`name=webyouxuan`)).toEqual({name:'webyouxuan'});
});
it('測試 stringify 是否正常使用stringify',()=>{
expect(stringify({name:'webyouxuan'})).toEqual(`name=webyouxuan`)
})
});
複製代碼
describe的功能是給用例分組,這樣能夠更好的給用例分類,其實這就是咱們所謂的單元測試,對某個具體函數和功能進行測試。
在寫第一個測試用例時,咱們一直在使用toEqual
其實這就是一個匹配器,那咱們來看看jest
中經常使用的匹配器有哪些?由於匹配器太多了,因此我就講些經常使用的!
爲了方便理解,我把匹配器分爲三類:判斷相等、不等、是否包含。
it('判斷是否相等',()=>{
expect(1+1).toBe(2); // 至關於 js中的===
expect({name:'webyouxuan'}).toEqual({name:'webyouxuan'}); // 比較內容是否相等
expect(true).toBeTruthy(); // 是否爲 true / false 也能夠用toBe(true)
expect(false).toBeFalsy();
});
it('判斷不相等關係',()=>{
expect(1+1).not.toBe(3); // not取反
expect(1+1).toBeLessThan(5); // js中的小於
expect(1+1).toBeGreaterThan(1); // js中的大於
});
it('判斷是否包含',()=>{
expect('hello world').toContain('hello'); // 是否包含
expect('hello world').toMatch(/hello/); // 正則
});
複製代碼
說了半天,咱們本身來寫個功能測試一下!
export const removeNode = (node) => {
node.parentNode.removeChild(node)
};
複製代碼
核心就是測試傳入一個節點,這個節點是否能從DOM
中刪除
import { removeNode } from './dom'
it('測試刪除節點',()=>{
document.body.innerHTML = `<div><button data-btn="btn"></button</div>`
let btn = document.querySelector('[data-btn="btn"]')
expect(btn).not.toBeNull()
removeNode(btn);
btn = document.querySelector('[data-btn="btn"]');
expect(btn).toBeNull()
})
複製代碼
這個就是咱們所說的jsdom
,在node中操做DOM元素
咱們但願每次更改測試後,自動從新執行測試,修改執行命令:
"scripts": {
"test": "jest --watchAll"
}
複製代碼
從新執行 npm run test
,這時就會監控用戶的修改
提示咱們按下w
,顯示更多信息
這裏我把每一個命令的含義都列好了,有須要能夠本身嘗試一下~
想要知道如何測試異步邏輯,如何mock接口數據,如何深度使用Jest嗎?敬請期待下期文章!