日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

React 之 jest 前端自动化测试

發(fā)布時間:2024/3/26 HTML 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React 之 jest 前端自动化测试 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一. 自動化測試簡介

  • 為什么要前端自動化測試:
    自動化測試可以間接的提供代碼的測試,多人協(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)建: jest.config.js// 配置文檔 //https://jestjs.io/docs/zh-Hans/configuration module.exports = {// Automatically clear mock calls and instances between every testclearMocks: true,// The directory where Jest should output its coverage filescoverageDirectory: "coverage",// An array of regexp pattern strings used to skip coverage collectioncoveragePathIgnorePatterns: ["\\\\node_modules\\\\"],// An array of file extensions your modules usemoduleFileExtensions: ["js","jsx",],// A list of paths to directories that Jest should use to search for files inroots: null,// The test environment that will be used for testingtestEnvironment: "node",// The glob patterns Jest uses to detect test filestestMatch: ["**/__tests__/**/*.js?(x)",//"**/?(*.)+(spec|test).js?(x)"],// An array of regexp pattern strings that are matched against all test paths, matched tests are skippedtestPathIgnorePatterns: ["\\\\node_modules\\\\"],// A map from regular expressions to paths to transformerstransform: {"^.+\\.js$": "babel-jest"},// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformationtransformIgnorePatterns: ["\\\\node_modules\\\\"], };
  • 創(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中添加命令
"scripts":{"my-test": "jest --colors --coverage" }
  • 添加對Jest 的 ES6+支持
    因為jest是基于Node 環(huán)境運行。 Node默認(rèn)對ES6+語法不全支持。所以如果我們用到了ES6+語法,需要為其添加語法支持。
// 為了避免版本沖突,將babel版本全部升級為7,或者將版本全部降到6: // 即: @babel/* 7.* "@babel/core": "^7.8.4","@babel/preset-env": "^7.8.4","@babel/preset-react": "^7.8.3","babel-jest": "^24.9.0","babel-loader": "^8.0.6",

2. 用法

  • 用例的表示
    Jest 內(nèi)部使用了 Jasmin2 來進(jìn)行測試, 故其用例語法與 Jasmine相同。==test()==函數(shù)來描述一個測試用例。
// Demo 普通函數(shù)// src/sum.js const sum = (a, b) => {return a+b } export default sum;// __tests__/demo.test.js import sum from '../src/sum';test('adds 1 + 2 to equal 3', () => {expect(sum(1,2)).toBe(3) })

執(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 組件測試
// Demo UI 組件測試// src/commentItem.js import React from 'react'const CommentItem = (props) => (<div className={props.list.length>=1?'btn-expand':''}>{props.list.map((item, index) => {return <p key={index}>{item}</p>})}</div> ) export default CommentItem// __tests__/demo.ui.test.jsimport React from 'react' import Enzyme, { shallow } from 'enzyme' import CommentItem from '../src/commentItem' import Adapter from 'enzyme-adapter-react-16' Enzyme.configure({ adapter: new Adapter() })describe('測試評論列表項組件', () => {// 這是mocha的玩法,jest可以直接兼容it('測試評論內(nèi)容小于等于200時不出現(xiàn)展開收起按鈕', () => {const propsData = {name: 'hj',content: '測試標(biāo)題',list:['l1','l2','l3']}const item = shallow(<CommentItem {...propsData} />);// 這里的斷言實際上和chai的expect是很像的expect(item.find('.btn-expand').length).toBe(0);})// 這是jest的玩法,推薦用這種test('兩數(shù)相加結(jié)果為兩個數(shù)字的和', () => {expect(3).toBe(3);}); })

擴展
細(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)容)。

// snapshot test demo// src/Link.Snapshot.js import React from 'react';const STATUS = {HOVERED: 'hovered',NORMAL: 'normal', };export default class Link extends React.Component {constructor() {super();this.state = {class: STATUS.NORMAL,};}_onMouseEnter = () => {this.setState({class: STATUS.HOVERED});};_onMouseLeave = () => {this.setState({class: STATUS.NORMAL});};render() {return (<aclassName={this.state.class}href={this.props.page || '#'}onMouseEnter={this._onMouseEnter}onMouseLeave={this._onMouseLeave}>{this.props.children}</a>);} }// __tests__/snapshot.test.js import React from 'react'; import Link from '../src/Link.Snapshot'; import renderer from 'react-test-renderer';it('renders correctly', () => {const tree = renderer.create(<Link page="http://www.instagram.com">Instagram</Link>).toJSON();expect(tree).toMatchSnapshot(); });

執(zhí)行測試命令后測試結(jié)果如下:

生成的快照文件內(nèi)容如下:

// __tests__/__snapshots__/snapshot.test.js.snap// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders correctly 1`] = ` <aclassName="normal"href="http://www.instagram.com"onMouseEnter={[Function]}onMouseLeave={[Function]} >Instagram </a> `;

當(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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。