前端如何实现网络速度测试功能_前端组件单元测试
從軟件質(zhì)量說起
日常生活中,商品質(zhì)量永遠(yuǎn)是我們進(jìn)行選擇時(shí)需要著重考慮的因素,計(jì)算機(jī)軟件也不例外。優(yōu)秀的軟件應(yīng)當(dāng)如我們預(yù)期的一樣工作,能夠正確地處理所有功能性需求。優(yōu)秀的軟件應(yīng)當(dāng)如我們預(yù)期一樣,持續(xù)穩(wěn)定運(yùn)行直到地老天荒。然而,現(xiàn)實(shí)生活中的軟件似乎永遠(yuǎn)是那么脆弱不堪。Bug這個(gè)計(jì)算機(jī)行話隨著普遍存在的計(jì)算機(jī)軟件缺陷,逐漸變成了可能是被行外人最熟悉的詞匯。由此可見,保障軟件質(zhì)量實(shí)在不是一件容易的事情。
在改進(jìn)軟件質(zhì)量這件事情上,人類付出了巨大的努力與探索。在一些最為關(guān)鍵的技術(shù)領(lǐng)域,比如分布式系統(tǒng)的一致性問題中,如 Amazon、Microsoft 等公司采用了形式化驗(yàn)證的方式檢查軟件系統(tǒng)的正確性。例如,這篇文章介紹了 Amazon 如何利用 TLA+ 檢查并發(fā)現(xiàn) DynamoDB 中若干可以導(dǎo)致數(shù)據(jù)丟失的設(shè)計(jì) bug。然而在更一般的場(chǎng)景中,我們并不需要?jiǎng)佑眯问交?yàn)證這種大殺器,而是采取軟件測(cè)試的方式進(jìn)行。
到底軟件測(cè)試是啥?
大部分人接觸“軟件測(cè)試”這個(gè)概念的時(shí)間遠(yuǎn)早于他們的預(yù)期。小時(shí)候的網(wǎng)絡(luò)游戲,第一次向廣大玩家普及了“內(nèi)測(cè)”、“公測(cè)”這樣的概念,雖然可能很多人都并不能意識(shí)到這個(gè)關(guān)乎軟件測(cè)試,但這應(yīng)該是大部分人第一次接觸“軟件測(cè)試”這個(gè)概念的契機(jī)。再往后,更多人是在本科階段的《軟件工程》這門課程中接觸到軟件測(cè)試。無論早期的瀑布開發(fā)模型亦或是后期的敏捷開發(fā)模型再到更現(xiàn)代的極限編程模型,軟件測(cè)試都是軟件開發(fā)生命周期中不可缺少的一環(huán),書籍中都會(huì)對(duì)其進(jìn)行詳細(xì)的介紹。但,到底什么是軟件測(cè)試呢?
書本上對(duì)軟件測(cè)試的正式定義形形色色,但這里我說說自己的理解。最廣義的說,我們?nèi)粘C看巍斑\(yùn)行”軟件,其實(shí)就能看成一次測(cè)試;而最狹義的測(cè)試?yán)?#xff0c;我們會(huì)定義軟件的規(guī)格,定義軟件的邊界條件,書寫測(cè)試用例,編寫自動(dòng)化測(cè)試代碼或者以文檔形式寫出軟件操作步驟,并交于專人驗(yàn)證開發(fā)人員提交的程序是否符合規(guī)格定義。但是,一般地說,驗(yàn)證軟件行為是否符合需求的行為就叫做軟件測(cè)試。
由此可見,要理解軟件測(cè)試,先要理解軟件需求。
功能性需求與非功能性需求
需求定義了軟件。功能性需求和非功能性需求分別告訴開發(fā)者「做什么」和「做成什么樣」。比如對(duì)于即時(shí)通信軟件,「發(fā)送消息」、「接收消息」、「顯示歷史消息」等就屬于功能性需求,他們定義了一個(gè)一個(gè)的功能點(diǎn),而「軟件崩潰率小于千分之一」,「能夠支持多平臺(tái)操作系統(tǒng)」等就屬于非功能性需求。軟件測(cè)試就是為了檢驗(yàn)軟件是否能滿足定義的需求而進(jìn)行的活動(dòng)。
為什么單元測(cè)試需要開發(fā)人員來寫?
在具有一定規(guī)模的軟件開發(fā)組織中,必然有專業(yè)負(fù)責(zé)產(chǎn)品質(zhì)量保證的QA團(tuán)隊(duì),也即通常意義上的測(cè)試團(tuán)隊(duì)。他們對(duì)軟件最終出產(chǎn)的質(zhì)量負(fù)責(zé),他們會(huì)針對(duì)軟件發(fā)版時(shí)定格的需求,規(guī)劃測(cè)試用例,進(jìn)行手動(dòng)、半自動(dòng)或全自動(dòng)測(cè)試。還會(huì)引入混沌工程,幫助找出一些常規(guī)測(cè)試手段與使用方法下無法發(fā)現(xiàn)的潛在故障。甚至還會(huì)找到目標(biāo)用戶,邀請(qǐng)他們?cè)囉密浖a(chǎn)品,并鼓勵(lì)他們幫助團(tuán)隊(duì)尋找軟件中的潛藏缺陷。微軟就曾經(jīng)以巨額獎(jiǎng)金召集廣大用戶向其提交使用過程中遇到的缺陷。
那么,既然有如此專業(yè)的測(cè)試團(tuán)隊(duì),為什么我們還需要讓開發(fā)人員來寫單元測(cè)試呢?
單元測(cè)試能夠幫助大中型系統(tǒng)快速迭代
對(duì)于大中型系統(tǒng),多人協(xié)作與持續(xù)改進(jìn)迭代是常態(tài)。一個(gè)經(jīng)過長期迭代的大中型系統(tǒng)中包含了海量特性,這也就使得未來的迭代往往可能牽一發(fā)而動(dòng)全身。尤其是當(dāng)某個(gè)新增的功能點(diǎn)需要變更軟件底層設(shè)計(jì)的時(shí)候,我們所做的修改很容易使得看上去相同的對(duì)外接口在一些特定條件下表現(xiàn)出不同的行為。具有單元測(cè)試的項(xiàng)目就可以在修改模塊內(nèi)部實(shí)現(xiàn)后,對(duì)模塊對(duì)外表現(xiàn)的功能,尤其是需要滿足的特定邊界條件進(jìn)行測(cè)試,從而很容易將隱藏其中的一些問題充分暴露出來。
單元測(cè)試能夠幫助開發(fā)人員改進(jìn)軟件設(shè)計(jì)
所有的自動(dòng)化軟件測(cè)試,最終都要落腳到斷言上。那么為了使得被測(cè)試的程序可以被斷言,開發(fā)人員不得不事前規(guī)劃軟件設(shè)計(jì),使得每一個(gè)單元的關(guān)鍵執(zhí)行結(jié)果都可被斷言。因此,當(dāng)開發(fā)人員注意到代碼可測(cè)試性后,開發(fā)者就會(huì)對(duì)代碼中每一個(gè)被測(cè)單元的輸入與輸出都非常清晰,依賴也變得清晰,無用的依賴會(huì)自然減少,軟件設(shè)計(jì)變得凝練,可維護(hù)性增強(qiáng)。
什么是前端的單元
在談了測(cè)試的重要性以及單元測(cè)試為何需要開發(fā)人員編寫之后,我們來看看什么是單元。單元測(cè)試位于所有測(cè)試的最底層,粒度最小,執(zhí)行速度最快,通常由開發(fā)工程師編寫并執(zhí)行,那么對(duì)于前端開發(fā)來說,什么是「單元」?從目前主流的三大框架的視角看過去,前端的MVVM架構(gòu)將前端應(yīng)用分為了三塊主要部分:View、Model和ViewModel,我們逐一來看:
- View層,JSX或者template,通常的表現(xiàn)形式為無狀態(tài)組件或者純函數(shù)式組件,給定Props的情況下一定會(huì)有相同的DOM或者VDOM被渲染出來。
- Model層,狀態(tài)管理工具所處的位置,通常會(huì)利用Vuex、Redux、MobX、RxJS等工具進(jìn)行編寫,視圖無關(guān),通常從ViewModel中得到輸入,執(zhí)行一些副作用,或者將輸出更新到ViewModel上。
- ViewModel層,通常與View層雙向綁定,但是當(dāng)View與其不能完美適配時(shí),ViewModel層負(fù)責(zé)將數(shù)據(jù)依據(jù)View的需求進(jìn)行轉(zhuǎn)化,因此該層是大量工具函數(shù)的應(yīng)用之處。如各種各樣的Formatter、各種各樣的Filter等往往位于這一層。
從這里我們就能發(fā)現(xiàn),前端的單元與后端不同,既有以類為單位的單元,也有以函數(shù)為單位的單元,也有以組件為單位的單元。而這三類不同領(lǐng)域的單元測(cè)試又各有特色,讓我們逐一來看。
測(cè)試三部曲
在具體討論View、Model與ViewModel層的測(cè)試前,先說說單元測(cè)試中三個(gè)重要的組成部分。我們可以把單元測(cè)試想象成一場(chǎng)考試,一個(gè)一個(gè)代碼單元就是這場(chǎng)考試中的考生,測(cè)試用例是考試的考題,預(yù)期結(jié)果是考試的答案。那么測(cè)試三部曲包括了考生、考題與答案,即被測(cè)代碼、測(cè)試用例與預(yù)期結(jié)果。
我個(gè)人認(rèn)為,在測(cè)試三部曲中,測(cè)試用例占據(jù)了核心地位。測(cè)試用例是軟件需求的具體表現(xiàn)形式,它以代碼的形式具體地定義了軟件需要支持的功能,應(yīng)當(dāng)做出的反應(yīng),需要考慮的邊界條件。被測(cè)代碼是測(cè)試三部曲必不可少的組成部分,也是我們工作的核心成果。而預(yù)期結(jié)果跟隨測(cè)試用例,自然就會(huì)浮出水面。
View層單元測(cè)試
A JavaScript library for building user interfaces,React的主頁上如此介紹它自己,事實(shí)上也是如此。相較Vue和Angular,React確實(shí)專注于更好地進(jìn)行View層的抽象,無論是提出View = f(props)的思想,還是單向數(shù)據(jù)流,都創(chuàng)造性地使得JavaScript構(gòu)建穩(wěn)定大型的富交互Web應(yīng)用成為可能。我們以利用React構(gòu)建的View層為例說明View層單元測(cè)試。
View層單元測(cè)試的關(guān)注點(diǎn)
關(guān)于View層是否需要編寫單元測(cè)試,一直有很大的爭(zhēng)議。
眾所周知,端應(yīng)用會(huì)隨著需求不斷迭代更新,View層測(cè)試究竟測(cè)試到什么粒度是一個(gè)需要重點(diǎn)權(quán)衡的問題。如果測(cè)試粒度過細(xì),往往不堪需求變更之?dāng)_,而如果測(cè)試粒度過粗,與無測(cè)試覆蓋也并無差別。
業(yè)界目前采用的實(shí)踐,是對(duì)底層組件庫如類似于Antd之類的,完全與業(yè)務(wù)無關(guān),組成用戶界面最基本單元的這些空間進(jìn)行嚴(yán)格的單元測(cè)試。以Antd為例,所有的組件位于Antd工程目錄的components文件夾下,每個(gè)組件目錄下的測(cè)試都放在__test__文件夾下,在__test__文件夾中,我們可以看到所有有關(guān)該組件的單元測(cè)試,其中值得關(guān)注的是__snapshot__這個(gè)文件夾,該文件夾中存放了組件在給定條件下的DOM結(jié)構(gòu),這也意味著Antd的組件渲染測(cè)試到DOM這一層級(jí)截止。它認(rèn)為,DOM結(jié)構(gòu)一致即可滿足其對(duì)于渲染穩(wěn)定性的要求。假如瀏覽器的渲染方式或兼容性發(fā)生改變,對(duì)于同一份DOM渲染結(jié)果與之前的版本不同,這時(shí)Antd組件就有可能出現(xiàn)渲染錯(cuò)誤,但是Antd的單元測(cè)試并不能發(fā)現(xiàn)這一點(diǎn)。這體現(xiàn)了Antd對(duì)于渲染測(cè)試的取舍與判斷。
更細(xì)粒度的測(cè)試其實(shí)也是可以做的,比如我們可以啟動(dòng)一個(gè)瀏覽器,然后將渲染結(jié)果截圖保存,之后每次運(yùn)行測(cè)試,同樣截圖并利用類似 Resemble.js 之類的工具進(jìn)行逐像素比對(duì),這樣測(cè)試能夠?qū)ψ罱K渲染視覺效果負(fù)責(zé),但是隨之而來的問題是,一像素的誤差都會(huì)導(dǎo)致測(cè)試告警,測(cè)試在很多情況下都處于失敗狀態(tài),這無疑也沒有意義。因此如何取舍也是一個(gè)見仁見智的問題。
除了渲染測(cè)試之外,View層測(cè)試還要關(guān)注組件內(nèi)state的變化,通常state的變化會(huì)由組件內(nèi)部事件或者外部事件進(jìn)行推動(dòng)的,如點(diǎn)擊事件,表單值改變事件或者網(wǎng)絡(luò)請(qǐng)求。
基于React的View層測(cè)試需要用到的工具
Jest
Jest 是 Facebook 出品的一個(gè)測(cè)試框架,相對(duì)其他測(cè)試框架,其一大特點(diǎn)就是就是內(nèi)置了常用的測(cè)試工具,比如自帶斷言、測(cè)試覆蓋率工具,實(shí)現(xiàn)了開箱即用。而作為一個(gè)面向前端的測(cè)試框架, Jest 可以利用其特有的快照測(cè)試功能,通過比對(duì) UI 代碼生成的快照文件,實(shí)現(xiàn)對(duì) React 等常見框架的自動(dòng)測(cè)試。此外, Jest 的測(cè)試用例是并行執(zhí)行的,而且只執(zhí)行發(fā)生改變的文件所對(duì)應(yīng)的測(cè)試,提升了測(cè)試速度。目前在 Github 上其 star 數(shù)已經(jīng)破萬;而除了 Facebook 外,業(yè)內(nèi)其他公司也開始從其它測(cè)試框架轉(zhuǎn)向 Jest ,比如 Airbnb 的嘗試 ,相信未來 Jest 的發(fā)展趨勢(shì)仍會(huì)比較迅猛。
Jest 可以通過 npm 或 yarn 進(jìn)行安裝。以 npm 為例,既可用 npm install -g jest 進(jìn)行全局安裝;也可以只局部安裝、并在 package.json 中指定 test 腳本:
{"scripts": {"test": "jest"} }Jest的基本使用
表示測(cè)試用例是一個(gè)測(cè)試框架提供的最基本的 API , Jest 內(nèi)部使用了 Jasmine 2 來進(jìn)行測(cè)試,故其用例語法與 Jasmine 相同。test()函數(shù)來描述一個(gè)測(cè)試用例,舉個(gè)簡單的例子:
// hello.js module.exports = () => 'Hello world' // hello.test.js let hello = require('hello.js')test('should get "Hello world"', () => {expect(hello()).toBe('Hello world') // 測(cè)試成功// expect(hello()).toBe('Hello') // 測(cè)試失敗 })其中toBe('Hello world')便是一句斷言( Jest 管它叫 “matcher” ,想了解更多 matcher 請(qǐng)參考文檔)。寫完了用例,運(yùn)行在項(xiàng)目目錄下執(zhí)行npm test,即可看到測(cè)試結(jié)果:
若測(cè)試失敗,會(huì)標(biāo)識(shí)出失敗的斷言位置,結(jié)果如下:
Jest中,你還可以對(duì)每個(gè)測(cè)試前需要做的工作和測(cè)試后需要做的工作進(jìn)行統(tǒng)一處理,對(duì)測(cè)試文件中所有的用例進(jìn)行統(tǒng)一的預(yù)處理,可以使用 beforeAll() 函數(shù);而如果想在每個(gè)用例開始前進(jìn)行都預(yù)處理,則可使用 beforeEach() 函數(shù)。至于后處理,也有對(duì)應(yīng)的 afterAll() 和 afterEach() 函數(shù)。
如果只是想對(duì)某幾個(gè)用例進(jìn)行同樣的預(yù)處理或后處理,可以將先將這幾個(gè)用例歸為一組。使用 describe() 函數(shù)即可表示一組用例,再將上面提到的四個(gè)處理函數(shù)置于 describe() 的處理回調(diào)內(nèi),就實(shí)現(xiàn)了對(duì)一組用例的預(yù)處理或后處理:
describe('test testObject', () => {beforeAll(() => {// 預(yù)處理操作})test('is foo', () => {expect(testObject.foo).toBeTruthy()})test('is not bar', () => {expect(testObject.bar).toBeFalsy()})afterAll(() => {// 后處理操作}) })我們還可以使用 jest 測(cè)試異步代碼。異步代碼的測(cè)試關(guān)鍵在于告知測(cè)試框架,待測(cè)的異步代碼如何完成。Jest提供了兩種常見的異步代碼調(diào)用方式的測(cè)試方法。
回調(diào)函數(shù):
// asyncHello.js module.exports = (name, cb) => setTimeout(() => cb(`Hello ${name}`), 1000) // asyncHello.test.js let asyncHello = require('asyncHello.js')test('should get "Hello world"', (done) => {asyncHello('world', (result) => {expect(result).toBe('Hello world')done()}) })jest會(huì)給測(cè)試函數(shù)注入done函數(shù),你只需要在回調(diào)函數(shù)執(zhí)行末尾調(diào)用done函數(shù),即可告訴jest,改異步調(diào)用已經(jīng)完成。
Promise:
// promiseHello.js module.exports = (name) => {return new Promise((resolve) => {setTimeout(() => resolve(`Hello ${name}`), 1000)}) } // promiseHello.test.js let promiseHello = require('promiseHello.js')it('should get "Hello world"', () => {expect.assertions(1); // 確保至少有一個(gè)斷言被調(diào)用,否則測(cè)試失敗return promiseHello('world').then((data) => {expect(data).toBe('Hello world')}) })對(duì)于Promise形式的異步執(zhí)行方式,可以直接在promise之后的then中進(jìn)行斷言。
另外,jest還支持async/await的異步執(zhí)行方式,與同步一樣,只需要在await后直接斷言即可。
Jest還通過集成Istanbul支持了測(cè)試覆蓋率統(tǒng)計(jì)??梢酝ㄟ^增加命令行參數(shù) --coverage 實(shí)現(xiàn),也可在 package.json 文件中進(jìn)行更詳細(xì)的配置。
// branches.js module.exports = (name) => {if (name === 'Levon') {return `Hello Levon`} else {return `Hello ${name}`} } // branches.test.js let branches = require('../branches.js')describe('Multiple branches test', ()=> {test('should get Hello Levon', ()=> {expect(branches('Levon')).toBe('Hello Levon')});// test('should get Hello World', ()=> {// expect(branches('World')).toBe('Hello World')// }); })運(yùn)行 jest --coverage 可看到在根目錄下生成一個(gè)測(cè)試覆蓋率報(bào)告目錄 coverage ,打開其中的 index.html :
該網(wǎng)頁展示了代碼覆蓋率和未測(cè)試的行數(shù),具體統(tǒng)計(jì)方式可以查看Istanbul的詳細(xì)說明。
如果我們?nèi)サ?branches.test.js 中的注釋,測(cè)試覆蓋率則變成100%:
react-test-renderer
Jest提供了快照測(cè)試功能,而 react-test-renderer 可以根據(jù) React 的 Virtual DOM 結(jié)構(gòu)生成一個(gè)符合 Jest 規(guī)范的快照,如此,便可以對(duì)渲染結(jié)果進(jìn)行基于 DOM 的比對(duì):
import React from 'react'; import Link from '../Link.react'; import renderer from 'react-test-renderer';it('renders correctly', () => {const tree = renderer.create(<Link page="http://www.facebook.com">Facebook</Link>).toJSON();expect(tree).toMatchSnapshot(); });我們先構(gòu)造上述測(cè)試,運(yùn)行后得到下述快照文件:
exports[`renders correctly 1`] = ` <aclassName="normal"href="http://www.facebook.com"onMouseEnter={[Function]}onMouseLeave={[Function]} >Facebook </a> `;exports[`renders correctly 1`] = ` <aclassName="normal"href="http://www.facebook.com"onMouseEnter={[Function]}onMouseLeave={[Function]} >Facebook </a> `;這個(gè)可讀的快照文件以可讀的形式展示了 React 渲染出的 DOM 結(jié)構(gòu)。相比于肉眼觀察效果的 UI 測(cè)試,快照測(cè)試直接由Jest進(jìn)行比對(duì)、速度更快;而且由于直接展示了 DOM 結(jié)構(gòu),也能讓我們?cè)跈z查快照的時(shí)候,快速、準(zhǔn)確地發(fā)現(xiàn)問題。
Enzyme & React Testing Library
Jest 提供了單元測(cè)試最基本的一些功能:獨(dú)立的測(cè)試環(huán)境,統(tǒng)一的setup、teardown,斷言庫,異步測(cè)試功能,函數(shù) mock 、stub 和 spy,測(cè)試覆蓋率統(tǒng)計(jì)等,但是我們的View層測(cè)試還是需要將 React 組件進(jìn)行渲染,并在渲染的組件上進(jìn)行一些操作的。React 官方提供了 Test Utility,而 Enzyme 和 React Testing Library 則是在官方的 Test Utility 基礎(chǔ)之上進(jìn)行了封裝,使得測(cè)試更加方便。
Enzyme 介紹的文章較 React Testing Library 更多,但是在 React 16 出現(xiàn)后,尤其是 React Hooks 出現(xiàn)后,Enzyme采取的打補(bǔ)丁的適配方式有一些根本問題無法解決。React Testing Library在FAQ中談了關(guān)于Enzyme的一些看法:
What about enzyme is "bloated with complexity and features" and "encourage poor testing practices"?
Most of the damaging features have to do with encouraging testing implementation details. Primarily, these are shallow rendering, APIs which allow selecting rendered elements by component constructors, and APIs which allow you to get and interact with component instances (and their state/properties) (most of enzyme's wrapper APIs allow this).
The guiding principle for this library is:
The more your tests resemble the way your software is used, the more confidence they can give you. - 17 Feb 2018
React Testing Library的作者認(rèn)為測(cè)試應(yīng)當(dāng)模仿用戶使用產(chǎn)品時(shí)進(jìn)行的操作,而非對(duì)實(shí)現(xiàn)細(xì)節(jié)進(jìn)行測(cè)試。即應(yīng)當(dāng)進(jìn)行黑盒測(cè)試而非白盒。
官網(wǎng) https://testing-library.com/docs/recipes 的 recipe 是單元測(cè)試非常不錯(cuò)的指南,值得一看。這個(gè)可讀的快照文件以可讀的形式展示了 React 渲染出的 DOM 結(jié)構(gòu)。相比于肉眼觀察效果的 UI 測(cè)試,快照測(cè)試直接由Jest進(jìn)行比對(duì)、速度更快;而且由于直接展示了 DOM 結(jié)構(gòu),也能讓我們?cè)跈z查快照的時(shí)候,快速、準(zhǔn)確地發(fā)現(xiàn)問題。
Model層單元測(cè)試
前端的Model層有一個(gè)更加廣為人知的名字:狀態(tài)管理。細(xì)說起來又是流派之爭(zhēng):以單向數(shù)據(jù)流和函數(shù)式思想為基石的Redux,同樣受單向數(shù)據(jù)流影響,但又受到響應(yīng)式編程啟發(fā)的MobX,FPR流派代表的Rxjs。然后由于Redux并不支持異步操作,于是又孕育而生許多異步中間件以增強(qiáng)Redux的功能比如redux-thunk,redux-saga,redux-observer等等。斯坦福大學(xué)iOS開發(fā)課上,教授介紹MVC時(shí)說了這么一句話:Model定義了軟件應(yīng)用。那么由此可見,不同的應(yīng)用下,不同的Model層解決方案應(yīng)該各有其優(yōu)勢(shì)與劣勢(shì)。
我們以Redux為例說明Model層測(cè)試的關(guān)注點(diǎn)。在Redux中我們通常會(huì)分開測(cè)試reducer和actionCreator。Reducer必是純函數(shù),所以其測(cè)試相對(duì)容易,通常也不會(huì)有什么外部依賴出現(xiàn),即使存在,由于其純函數(shù)特性,也很容易進(jìn)行mock。而actionCreator相對(duì)復(fù)雜,由于使用不同的中間件,actionCreator的形式差別會(huì)很大,但是歸根究底,就是要測(cè)試其在各個(gè)流程中是否能如預(yù)期的那樣完成各個(gè)異步操作,并創(chuàng)建出符合預(yù)期的,最終交付給reducer的action對(duì)象。
Model層測(cè)試常見的工具除了View層也需要用到的Jest測(cè)試框架外,還需要根據(jù)工程中的Model層庫選型選擇相對(duì)應(yīng)的工具,這些工具的主要目的是為了提供一些測(cè)試輔助的手段,比如Redux的測(cè)試需要?jiǎng)?chuàng)造一個(gè)假的store來使整個(gè)程序能夠運(yùn)行起來。RxJS則需要模擬其復(fù)雜的異步事件流,即「彈珠測(cè)試」。
ViewModel層單元測(cè)試
我所理解的ViewModel層,更多的是一些數(shù)據(jù)接口,數(shù)據(jù)格式轉(zhuǎn)換,數(shù)據(jù)校驗(yàn)等等之類的工具性質(zhì)的函數(shù)。由于后端接口給我們的數(shù)據(jù)與真正頁面上展示的形式通常有較大的差異,我們需要在真正將數(shù)據(jù)給到View層之前,經(jīng)過ViewModel層進(jìn)行轉(zhuǎn)化。同樣的,由于用戶在頁面上進(jìn)行的輸入信息有時(shí)也會(huì)不符合軟件定義,錯(cuò)誤的用戶輸入會(huì)造成系統(tǒng)安全隱患,因此也需要在ViewModel層對(duì)用戶輸入的數(shù)據(jù)進(jìn)行校驗(yàn)。
由于ViewModel層的純函數(shù)性質(zhì),通常只需要Jest庫即可進(jìn)行,過程一般比較簡單,在此就不贅述。
總結(jié)
以上是生活随笔為你收集整理的前端如何实现网络速度测试功能_前端组件单元测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sql配置管理器服务是空的_Postgr
- 下一篇: flex 左右布局_面试必考点:前端布局