React 之 jest 前端自动化测试
一. 自動化測試簡介
-
為什么要前端自動化測試:
自動化測試可以間接的提供代碼的測試,多人協(xié)作時相互之間未知邏輯的改動等產(chǎn)生的未知或新問題的預(yù)警。有效避免一些未考慮到及低級的錯誤。 -
自動化測試需要工作:
自動化測試需要我們手動編寫測試代碼,當(dāng)部分邏輯發(fā)生改變時,也需要同步更新我們的測試代碼。重一定的角度上它也間接的提高了開發(fā)及維護(hù)成本。這點在實際開發(fā)運用中,大家根據(jù)實際項目情況來衡量。 -
前段測試工具概覽:
前端測試工具紛繁復(fù)雜,大致分為測試框架, 斷言庫, 測試覆蓋率工具等。
測試框架
測試框架的作用是提供一些方便的語法來描述測試的用例,以及對用例進(jìn)行分組。
測試框架可分為兩種: TDD(測試驅(qū)動開發(fā))和 BDD(行為驅(qū)動開發(fā))。
常見的測試框架有 Jasmine, Mocha 及 接下來我們要介紹的 Jest
斷言庫
斷言庫主要提供語義化方法,用于對參與測試的值做各種各樣的判斷。 這些語義化方法會返回測試的結(jié)果,要么成功,要么失敗。
產(chǎn)概念的斷言庫有Should.js Chai.js 等
測試覆蓋率工具
用于統(tǒng)計測試用例對代碼的測試情況, 生成響應(yīng)的報表。 比如* istanbul *
- 關(guān)于Jest 測試框架概述
Jest 是Facebook 出品的一個測試框架, 其一大特點是內(nèi)置了常用的測試工具,比如:自帶斷言(expect), 測試覆蓋率工具(coverage),實現(xiàn)了開箱即用等 。
Jest 可以利用其特有的快照測試功能, 通過比對UI代碼生成的快照文件, 實現(xiàn)對React等常見框架的自動化測試。
此外,Jest 測試用例是并行執(zhí)行的, 而且只執(zhí)行發(fā)生改變的文件所對應(yīng)的測試,提升了測試速度。
二. Jest 的實踐
1. 環(huán)境搭建
這里我們主要研究jest的搭建所以,您可以通過官網(wǎng)安裝 Create React App 來搭建一個開發(fā)環(huán)境。
接下來我們需要做如下事情:
-
安裝依賴包
npm i jest babel-jest -D -
添加jest.config.js 文件
- 創(chuàng)建測試代碼文件目錄
在根目錄下創(chuàng)建*tests* 文件夾用來存放測試腳本文件。
注: Jest 的測試腳本名形如 **.test.js 或 *.spec.js。 當(dāng)執(zhí)行npm run test 命令時,
它會執(zhí)行當(dāng)前目錄下的所有 的 *.test.js 或 *.spec.js 文件, 完成測試。
- package.json中添加命令
- 添加對Jest 的 ES6+支持
因為jest是基于Node 環(huán)境運行。 Node默認(rèn)對ES6+語法不全支持。所以如果我們用到了ES6+語法,需要為其添加語法支持。
2. 用法
- 用例的表示
Jest 內(nèi)部使用了 Jasmin2 來進(jìn)行測試, 故其用例語法與 Jasmine相同。==test()==函數(shù)來描述一個測試用例。
執(zhí)行命令 npm run my-test 輸出結(jié)果如下:
單元測試的幾個指標(biāo):
%stmts 是語句覆蓋率(statement coverage):是不是每個語句都執(zhí)行了?
%Branch 分支覆蓋率(branch coverage):是不是每個if代碼塊都執(zhí)行了?
%Funcs 函數(shù)覆蓋率(function coverage):是不是每個函數(shù)都調(diào)用了?
%Lines 行覆蓋率(line coverage):是不是每一行都執(zhí)行了?
- UI 組件測試
擴展
細(xì)心的同學(xué)應(yīng)該注意到了,這個實例中用到了==enzyme,Adapter ==。 這里簡單說下兩者的作用。
(1)Enzyme 簡介 傳送門
(2)Adapter : 在使用 enzyme 時,需要先適配React版本。
npm i enzyme-adapter-react-16 -D //使用 import Adapter from 'enzyme-adapter-react-16' Enzyme.configure({ adapter: new Adapter() })為了避免每次測試文件都這么寫, 可以在test目錄下新建一個配置文件:
import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16';Enzyme.configure({adapter: new Adapter(), });export default Enzyme;然后在測試文件的時候引入這個配置文件即可:
import React from 'react' import Enzyme from './config/Enzyme.config'; ................ const {shallow}=Enzymedescribe('Enzyme的淺渲染測試套件', function () {it('Example組件中按鈕的名字為text的值', function () {const name='按鈕名'let app = shallow(<Example text={name} />)assert.equal(app.find('button').text(),name)}) })3. Jest 之快照測試(Snapshot)
如果你的項目中還沒有任何測試用例,那么使用快照測試將是一個最快的基本保障。
如果你想確保你的一些公共組件(UI)不會被意外的被修改變化,那么快照測試是一個非常有用的工具。
它的基本思想是:在測試文件目錄下生成快照文件目錄“snapshots/**.test.js.snap” 。 每次執(zhí)行測試命令時,都會與該目錄下的對應(yīng)快照文件進(jìn)行內(nèi)容比對。 如果兩個圖像(內(nèi)容)不匹配,則測試失敗。 除非您同步更新了快照為最新版本(即測試用例中承認(rèn)且同意修改更新快照內(nèi)容)。
執(zhí)行測試命令后測試結(jié)果如下:
生成的快照文件內(nèi)容如下:
當(dāng)某人不小心修改了我們的公共UI組件代碼后(注:測試用例沒有修改):
// src/Link.Snapshot.js........... ................ render() {return (<aclassName={this.state.class}href={ (this.props.page + 'udpate udpate !') || '#'} // 假設(shè)修改了此處, 對href 添加了自定義字符串 ‘udpate udpate !’。onMouseEnter={this._onMouseEnter}onMouseLeave={this._onMouseLeave}>{this.props.children}</a>);}.......................................再次執(zhí)行測試命令輸入結(jié)果如下:
Jest 快照測試通過比對上次的快照輸出文件內(nèi)容,發(fā)現(xiàn)不一致。 輸出測試失敗! 表示該UI組件被修改…
如果我們統(tǒng)一本次的修改, 那么可以通過: npm run my-test – -u 命令來同意同步更新歷史快照文件。更新完成后,則測試提示通過。
注: 快照文件應(yīng)該與代碼更改一起提交,并作為代碼審查過程的一部分進(jìn)行審核。
Jest 使用 pretty-format 對快照文件進(jìn)行了處理,代碼會變成可閱讀的文件。
3. 常用API
- Jest 全局方法
Describe(name, fn) : 測試套件,一組相關(guān)的測試用例。第一個參數(shù)是測試套餐的描述,第二個參數(shù)是測試用例。
const my = {name : "fynn",age : 27 } describe("my info", ()=>{test("my name", ()=>{expect(my.name).toBe("fynn")});test("my age", ()=>{expect(my.age).toBe(27)})})- Describe.only(name, fn)
當(dāng)一個file有多個測試套件,但你只想執(zhí)行其中一個測試套件,可以使用 describe.only。
const my = {name : "fynn",age : 27 } let hw = () =>"Hello World!"; describe("my info", ()=>{test("my name", ()=>{expect(my.name).toBe("fynn")});test("my age", ()=>{expect(my.age).toBe(27)})}); describe.only('hw function test suit',()=>{test('hw test',()=>{expect(hw()).toBe("Hello World!");}) })- Describe.skip(name, fn)
一個file中有多個測試套件,如果你想跳過某個測試套件可以使用 describe.skip
- Test
測試用例,可以寫在 describe測試套件中,也可以單獨寫在測試套件外面
const my = {name : "fynn",age: 27 } let hw = ()=>"Hello World!" describe("my info",()=>{test("my name",()=>{expect(my.name).toBe("fynn")});test("my age",()=>{expect(my.age).toBe(27)}) }); test("hw test",()=>{expect(hw()).toBe("Hello World!"); })- Test.only
有多個測試用例或測試套件,只想執(zhí)行其中某一個測試用例時可以用test.only。
const my = {name : "fynn",age : 27 }; let hw = ()=>"Hello World!"; test("my name",()=>{expect(my.name).toBe("fynn"); }) test.only("hw test",()=>{expect(hw()).toBe("Hello World!"); })- Test.skip(name, fn)
當(dāng)有多個測試用例,想跳過某個測試用例可以使用test.skip;
- It(name,fn)
用法和test一樣,不能嵌套在test中!可以嵌套在describe中
const my = {name : "fynn",age : 27 }; let hw = ()=>"Hello World!"; it("my name",()=>{expect(my.name).toBe("fynn"); }) xit("hw test",()=>{expect(hw()).toBe("Hello World!"); })- AfterAll(fn)
當(dāng)file所有test都執(zhí)行完畢后,執(zhí)行afterAll中的方法。
const my = {name :"fynn",age : 27 }; test("my name",()=>{expect(my.name).toBe("fynn") }); test("my age",()=>{expect(my.age).toBe(27) }); afterAll(()=>{console.log("執(zhí)行完所有test!") })- AfterEach(fn)
每當(dāng)一個test執(zhí)行完后,調(diào)用一次afterEach中的方法
const my = {name :"fynn",age : 27 }; test("my name",()=>{expect(my.name).toBe("fynn") }); test("my age",()=>{expect(my.age).toBe(27) }); afterEach(()=>{console.log("執(zhí)行完一個test!") })- BeforeAll(fn)
在所有執(zhí)行test前先調(diào)用beforeAll中的方法
const my = {name :"fynn",age : 27 }; test("my name",()=>{expect(my.name).toBe("fynn") }); test("my age",()=>{expect(my.age).toBe(27) }); beforeAll(()=>{console.log("要開始執(zhí)行test了!") });- BeforeEach(fn)
在每個test執(zhí)行前都會調(diào)用一次beforeEach中的方法
const my = {name :"fynn",age : 27 }; test("my name",()=>{expect(my.name).toBe("fynn") }); test("my age",()=>{expect(my.age).toBe(27) }); beforeEach(()=>{console.log("要開始執(zhí)行一個test了!") })其它相關(guān)API 參考如下地址:
關(guān)于Jest 官方地址 傳送門
未完待續(xù)…
總結(jié)
以上是生活随笔為你收集整理的React 之 jest 前端自动化测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三星 SCX-4521NS 网络打印机
- 下一篇: 一个简单HTML5期末考核大作业,学生个