React 之 jest 前端自动化测试
一. 自動化測試簡介
-
為什么要前端自動化測試:
自動化測試可以間接的提供代碼的測試,多人協作時相互之間未知邏輯的改動等產生的未知或新問題的預警。有效避免一些未考慮到及低級的錯誤。 -
自動化測試需要工作:
自動化測試需要我們手動編寫測試代碼,當部分邏輯發生改變時,也需要同步更新我們的測試代碼。重一定的角度上它也間接的提高了開發及維護成本。這點在實際開發運用中,大家根據實際項目情況來衡量。 -
前段測試工具概覽:
前端測試工具紛繁復雜,大致分為測試框架, 斷言庫, 測試覆蓋率工具等。
測試框架
測試框架的作用是提供一些方便的語法來描述測試的用例,以及對用例進行分組。
測試框架可分為兩種: TDD(測試驅動開發)和 BDD(行為驅動開發)。
常見的測試框架有 Jasmine, Mocha 及 接下來我們要介紹的 Jest
斷言庫
斷言庫主要提供語義化方法,用于對參與測試的值做各種各樣的判斷。 這些語義化方法會返回測試的結果,要么成功,要么失敗。
產概念的斷言庫有Should.js Chai.js 等
測試覆蓋率工具
用于統計測試用例對代碼的測試情況, 生成響應的報表。 比如* istanbul *
- 關于Jest 測試框架概述
Jest 是Facebook 出品的一個測試框架, 其一大特點是內置了常用的測試工具,比如:自帶斷言(expect), 測試覆蓋率工具(coverage),實現了開箱即用等 。
Jest 可以利用其特有的快照測試功能, 通過比對UI代碼生成的快照文件, 實現對React等常見框架的自動化測試。
此外,Jest 測試用例是并行執行的, 而且只執行發生改變的文件所對應的測試,提升了測試速度。
二. Jest 的實踐
1. 環境搭建
這里我們主要研究jest的搭建所以,您可以通過官網安裝 Create React App 來搭建一個開發環境。
接下來我們需要做如下事情:
-
安裝依賴包
npm i jest babel-jest -D -
添加jest.config.js 文件
- 創建測試代碼文件目錄
在根目錄下創建*tests* 文件夾用來存放測試腳本文件。
注: Jest 的測試腳本名形如 **.test.js 或 *.spec.js。 當執行npm run test 命令時,
它會執行當前目錄下的所有 的 *.test.js 或 *.spec.js 文件, 完成測試。
- package.json中添加命令
- 添加對Jest 的 ES6+支持
因為jest是基于Node 環境運行。 Node默認對ES6+語法不全支持。所以如果我們用到了ES6+語法,需要為其添加語法支持。
2. 用法
- 用例的表示
Jest 內部使用了 Jasmin2 來進行測試, 故其用例語法與 Jasmine相同。==test()==函數來描述一個測試用例。
執行命令 npm run my-test 輸出結果如下:
單元測試的幾個指標:
%stmts 是語句覆蓋率(statement coverage):是不是每個語句都執行了?
%Branch 分支覆蓋率(branch coverage):是不是每個if代碼塊都執行了?
%Funcs 函數覆蓋率(function coverage):是不是每個函數都調用了?
%Lines 行覆蓋率(line coverage):是不是每一行都執行了?
- UI 組件測試
擴展
細心的同學應該注意到了,這個實例中用到了==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” 。 每次執行測試命令時,都會與該目錄下的對應快照文件進行內容比對。 如果兩個圖像(內容)不匹配,則測試失敗。 除非您同步更新了快照為最新版本(即測試用例中承認且同意修改更新快照內容)。
執行測試命令后測試結果如下:
生成的快照文件內容如下:
當某人不小心修改了我們的公共UI組件代碼后(注:測試用例沒有修改):
// src/Link.Snapshot.js........... ................ render() {return (<aclassName={this.state.class}href={ (this.props.page + 'udpate udpate !') || '#'} // 假設修改了此處, 對href 添加了自定義字符串 ‘udpate udpate !’。onMouseEnter={this._onMouseEnter}onMouseLeave={this._onMouseLeave}>{this.props.children}</a>);}.......................................再次執行測試命令輸入結果如下:
Jest 快照測試通過比對上次的快照輸出文件內容,發現不一致。 輸出測試失敗! 表示該UI組件被修改…
如果我們統一本次的修改, 那么可以通過: npm run my-test – -u 命令來同意同步更新歷史快照文件。更新完成后,則測試提示通過。
注: 快照文件應該與代碼更改一起提交,并作為代碼審查過程的一部分進行審核。
Jest 使用 pretty-format 對快照文件進行了處理,代碼會變成可閱讀的文件。
3. 常用API
- Jest 全局方法
Describe(name, fn) : 測試套件,一組相關的測試用例。第一個參數是測試套餐的描述,第二個參數是測試用例。
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)
當一個file有多個測試套件,但你只想執行其中一個測試套件,可以使用 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
有多個測試用例或測試套件,只想執行其中某一個測試用例時可以用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)
當有多個測試用例,想跳過某個測試用例可以使用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)
當file所有test都執行完畢后,執行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("執行完所有test!") })- AfterEach(fn)
每當一個test執行完后,調用一次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("執行完一個test!") })- BeforeAll(fn)
在所有執行test前先調用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("要開始執行test了!") });- BeforeEach(fn)
在每個test執行前都會調用一次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("要開始執行一個test了!") })其它相關API 參考如下地址:
關于Jest 官方地址 傳送門
未完待續…
總結
以上是生活随笔為你收集整理的React 之 jest 前端自动化测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三星 SCX-4521NS 网络打印机
- 下一篇: java 图片识别提取_老司机帮您Jav