寫給前端仔的自動(dòng)化測試入門小作文
前言:前端領(lǐng)域的自動(dòng)化測試
一直以來對于前端同學(xué)來說,自動(dòng)化測試都是一個(gè)比較特殊的命題。一方面,大家其實(shí)都知道自動(dòng)化測試的好處,做了什么改動(dòng)只要跑一遍測試用例就知道有沒有改掛了之前的邏輯,進(jìn)行修改時(shí)也更有底氣。而另一方面,前端本身就具有特殊性,活動(dòng)頁從需求評審到正式上線可能在一周內(nèi)就完成了,這種迭代速度還寫測試用例就是折磨自己。
但實(shí)際上,自動(dòng)化測試在前端工程中也是相當(dāng)重要的一部分。即使是快速迭代的活動(dòng)頁面,也會有通用的工具函數(shù)與 SDK,對這一部分的代碼進(jìn)行測試用例的完善是有必要且意義重大的,而對于某些流量巨大且長期存在的頁面,我們甚至需要進(jìn)行多種測試場景的保障。
然而由于這兩種情況的存在,很多前端同學(xué)其實(shí)都對自動(dòng)化測試的認(rèn)知相當(dāng)空白,它有哪些分類?有哪些推薦的實(shí)踐?有哪些框架與方案?而這篇文章的目的就是進(jìn)行一個(gè)基礎(chǔ)的掃盲,至少完成閱讀以后你會知道如何為項(xiàng)目編寫測試用例,以及應(yīng)該編寫哪些場景的測試用例。
單元測試與集成測試
單元測試(Unit Testing)正如其名,其中的測試用例應(yīng)當(dāng)是針對代碼中的各個(gè)單元的,如前端代碼中,每一個(gè)工具方法都可以被作為一個(gè)單元,對應(yīng)一個(gè)獨(dú)立的測試用例。但這么說并不意味著你要寫出非常細(xì)粒度的代碼——這不是沒事折磨自己嗎?我通常使用“功能單元”的方式來確定粒度,比如生產(chǎn)薯?xiàng)l的流水線上,清洗-削皮-切片-包裝就是四個(gè)完全獨(dú)立的功能單元。
你可能會感到疑惑,這四個(gè)功能單元明明存在依賴關(guān)系,為何說是完全獨(dú)立的?這是因?yàn)樵趩卧獪y試時(shí),非常重要的一個(gè)步驟就是對當(dāng)前測試單元的外部依賴進(jìn)行模擬,比如我在測試削皮功能時(shí),會直接給到“已經(jīng)清洗完畢的土豆”,然后檢查“削皮后的土豆”,而不會真的去調(diào)用前后的功能單元。
常見的模擬操作可以分為 Fake、Stub、Mock、Spy 這么幾種,我們在下文會有更詳細(xì)的介紹。
一種常見的情況是工具方法中會基于外部依賴的表現(xiàn)執(zhí)行不同分支的代碼(if/else,try/catch,resolve/reject 等)。這種時(shí)候,我們需要做的就是通過修改外部依賴的表現(xiàn),來檢查工具方法內(nèi)部各個(gè)代碼分支的執(zhí)行情況。比如,在 fetch 成功返回時(shí)應(yīng)當(dāng)調(diào)用 processData 方法,在 fetch 失敗時(shí)應(yīng)當(dāng)調(diào)用 reportError 方法,此時(shí)你就可以篡改掉 fetch 的實(shí)現(xiàn),然后檢查 processData 、reportError 方法是否被調(diào)用(注意,這兩個(gè)方法也需要被模擬(Stub / Spy) ,然后才能檢查它們的調(diào)用情況)。
當(dāng)然,完全模擬所有外部依賴是最理想的情況,在很多時(shí)候一個(gè)工具方法可能具有許多外部依賴,此時(shí)你可以省略掉其中能確定無副作用(如 logger 這樣的純函數(shù)),或者是與核心邏輯無關(guān)的部分。
我們知道,測試用例也可以反過來對代碼產(chǎn)生檢查作用,而在單元測試階段這種作用基本是最明顯的,比如你可以很容易發(fā)現(xiàn)某一處功能單元設(shè)計(jì)得過于耦合,或是某一外部依賴將導(dǎo)致代碼進(jìn)入錯(cuò)誤分支等情況。
目前推薦的單元測試方案主要有這么幾種,Jest、Mocha、Sinon、Jasime 以及 AVA,它們之間各有優(yōu)劣,這里不做比較。但需要注意的是,一套完整的,能夠滿足實(shí)際需求的單元測試方案,通常意味著需要包括這么幾個(gè)功能:
斷言,Jest 提供了注入到全局的 expect 風(fēng)格斷言(expect(1+1).toBe(2)),而 Sinon 提供的則是類似 NodeJs asserts 模塊風(fēng)格的斷言(``sinon.assert.pass(1 + 1 === 2)`),而 Mocha 則不綁定斷言庫,你可以使用 asserts 模塊或者 Chai 來進(jìn)行斷言。另外,斷言又包括了幾種不同的風(fēng)格,我們同樣在下文講解。
用例收集,編寫測試用例時(shí)我們同樣需要基于功能單元區(qū)分,常見的方式就是 describe 收集一個(gè)功能單元,內(nèi)部又使用 it / test 來進(jìn)行功能單元各個(gè)邏輯分支的驗(yàn)證。如:
describe('Utils.Reporter', () => {
it('should report error when xxx', () => {})
it('should show warnings when xxx', () => {})
})
- 模擬功能(Stub 、Fake Timers 等),包括對一個(gè)對象的 Spy,一個(gè)函數(shù)的 Stub,對一個(gè)模塊的 Mock,都屬于模擬的范疇。
- 測試覆蓋率報(bào)告,這一功能常見的方式是通過 istanbul (1.0版本,2.0 更名為 nyc)或 c8 來進(jìn)行實(shí)現(xiàn),其原理包括代碼插樁與使用 V8 引擎內(nèi)置功能兩種,這里不再贅述。另外一個(gè)常見的場景是輸出其他語言格式的覆蓋率報(bào)告(如 JUnit),社區(qū)也通過 Reporters 的機(jī)制為這些測試框架做了支持。
如果你此前并沒有對這些單元測試方案非常熟悉,那我推薦你了解一下 Vitest ,來自 antfu 的作品,特色是快(畢竟基于 Vite)以及對 TypeScript、ES Module 的良好支持,我目前在工作中的單元測試也已經(jīng)全部遷移到 Vitest,同時(shí) Vitest 還自帶了 UI 界面,讓你可以更享受編寫測試并看著它們一個(gè)個(gè)通過的過程。
如果說單元測試是為了測試單個(gè)功能單元,那么集成測試(Integration Testing)很明顯就是為了測試多個(gè)功能單元的協(xié)作。但需要注意的是,多個(gè)功能單元協(xié)作并不意味著對整個(gè)系統(tǒng)(流水線)進(jìn)行完整的功能測試,通常我們還會將幾個(gè)功能單元分散開進(jìn)行組合,成為系統(tǒng)的某一部分,比如清洗-削皮作為預(yù)處理功能,需要確定一籮筐土豆能否正確地變成干凈的去皮土豆,切片-包裝作為核心功能,需要確定去皮土豆能變成冷凍薯?xiàng)l。
而要進(jìn)行集成測試的編寫,其實(shí)我們?nèi)匀恢恍枰褂脝卧獪y試方案即可,因?yàn)楸举|(zhì)上集成測試就是同時(shí)對多個(gè)功能單元進(jìn)行測試,我們驗(yàn)證的范疇也隨之?dāng)U大了而已。
而關(guān)于集成測試的維度拆分則并沒有準(zhǔn)確的界限,你可以像上面那樣將預(yù)處理功能作為一個(gè)系統(tǒng)部分,也可以將整個(gè)流水線作為一個(gè)系統(tǒng)部分(還有供應(yīng)鏈部分、烹飪部分與服務(wù)部分),按照你的實(shí)際業(yè)務(wù)場景就行。
Mock、Fake、Stub
很多時(shí)候測試用例的運(yùn)行時(shí)是受限的,比如我們并不希望真的發(fā)起網(wǎng)絡(luò)請求,或者是和數(shù)據(jù)庫交互,以及 DOM API 的操作等。這個(gè)時(shí)候我們會使用一系列模擬手段,來特定地模擬一個(gè)可交互的對象,并通過修改它的行為來檢查預(yù)期的處理邏輯是否執(zhí)行。
這個(gè)模擬行為通常被直接稱為 Mock,但實(shí)際上,由于模擬的對象類型以及注入的模擬邏輯,更準(zhǔn)確的描述是將這些行為劃分為三大類。首先是最常用的 Stub ,假設(shè)我們在為 UserService 編寫單元測試,其內(nèi)部注入的 PrismaService 負(fù)責(zé)數(shù)據(jù)庫的讀寫,我們可以使用一個(gè) PrismaServiceStub 替換掉實(shí)際的服務(wù),并且在其內(nèi)部提供對應(yīng) PrismaService.user.findUnique 這樣的方法,然后在我們調(diào)用 UserService.queryUser 時(shí),就可以檢查 PrismaServiceStub 上對應(yīng)的方法是否被預(yù)期的入?yún)⒄{(diào)用,而其出參是否被預(yù)期地處理后返回。Spy 也可以認(rèn)為是 Stub 的一種,但它更強(qiáng)調(diào)“是否按照預(yù)期調(diào)用”這個(gè)過程,我們甚至可以僅僅監(jiān)聽一個(gè)對象而無需提供模擬實(shí)現(xiàn)(如 console 這樣的 API)。
而如果我們不希望替換掉 PrismaService,而是希望它真的去進(jìn)行數(shù)據(jù)讀寫,但不是對真實(shí)的數(shù)據(jù)庫,就可以提供一個(gè) Fake 的數(shù)據(jù)庫——比如一個(gè)對象,這樣對數(shù)據(jù)庫的讀寫就變成了對內(nèi)存對象的讀寫,變得更加快捷和穩(wěn)定,這就是 Fake。另外一個(gè)常見的 Fake 場景就是定時(shí)器,常見的單元測試框架都提供了 Fake Timers 的功能支持。
而 Mock 其實(shí)和 Stub 也非常類似,但 Mock 更像是其中“預(yù)期的入?yún)ⅰ?,而并不關(guān)注返回值,我個(gè)人理解通常項(xiàng)目中 fixtures 文件夾下的各種對象和 JSON 就是典型的 Mock 。
當(dāng)然,Mock、Stub、Spy 三者還是非常相似的,我們也并不是必須搞清楚其中的差異,因?yàn)樗鼈兊谋举|(zhì)都是模擬罷了。
斷言:expect、assert、should
我們常見的斷言包括 expect 與 assert 形式,NodeJs 提供了原生的 asserts 模塊讓你來編寫一些簡單的斷言,你可以在實(shí)際代碼中也使用斷言來確保邏輯正確運(yùn)行,而 expect 形式則通常只見于測試用例中。如檢查一個(gè)函數(shù)的調(diào)用和比較兩個(gè)對象,兩種風(fēng)格分別是這樣的:
expect(mockFn).toBeCalledWith("linbudu");
assert.pass(mockFn.calls[0].arg === "linbudu");
expect(obj1).toEqual(obj2);
assert.equal(obj1, obj2);
通常我個(gè)人更喜歡命令式風(fēng)格明顯的 expect 斷言,而除了這兩種風(fēng)格以外,其實(shí)還有一種 should 形式的鏈?zhǔn)斤L(fēng)格斷言,它寫起來是這樣的:
mockFn.should.be.called();
obj1.should.equal(obj2);
值得一提的是在 Chai 這個(gè)斷言庫中對以上三種斷言風(fēng)格都進(jìn)行了支持,如果你有興趣,不妨都試一試。
前端頁面中的組件測試與 E2E 測試
單元測試和集成測試是前后端應(yīng)用中通用的概念,而完成了對基礎(chǔ)功能單元的測試以后,我們需要更進(jìn)一步,關(guān)注領(lǐng)域中特定的功能,比如從前端視角來看一個(gè)組件的 UI 與功能,從后端視角來看一個(gè)接口面對千奇百怪入?yún)⒌捻憫?yīng)。
在當(dāng)今的前端項(xiàng)目中,組件化應(yīng)該是最明顯的一個(gè)趨勢,那么進(jìn)行組件維度的測試也自然是相當(dāng)有必要的。以 React 組件為例,我們可以模擬這個(gè)組件的入?yún)?,并觀察其實(shí)際渲染的 UI 組件是否正確,以及使用快照的方式,來檢查組件的實(shí)際渲染是否一致。
目前使用的組件測試方案通常是和框架綁定的,如 React 下的 @testing-library/react? 和 Enzyme,Vue 下的 @vue/test-utils?,Svelte 下的 @testing-library/svelte,這是因?yàn)楸举|(zhì)上我們是在孤立地渲染這個(gè)組件,并模擬框架行為來驗(yàn)證其表現(xiàn)。
在組件測試方案中,我更推薦 @testing-library/react? (還包括 @testing-library/react-hooks),Enzyme 的 API 要更加復(fù)雜,同時(shí)其目前應(yīng)該已經(jīng)不再維護(hù)(或是維護(hù)力度堪憂)。使用其編寫的測試用例是這樣的:
import * as React from 'react'
function HiddenMessage({children}) {
const [showMessage, setShowMessage] = React.useState(false)
return (
<div>
<label htmlFor="toggle">Show Message</label>
<input
id="toggle"
type="checkbox"
onChange={e => setShowMessage(e.target.checked)}
checked={showMessage}
/>
{showMessage ? children : null}
</div>
)
}
export default HiddenMessage
import * as React from 'react'
import {render, fireEvent, screen} from '@testing-library/react'
import HiddenMessage from '../hidden-message'
test('shows the children when the checkbox is checked', () => {
const testMessage = 'Test Message'
// 將組件模擬渲染出來
render(<HiddenMessage>{testMessage}</HiddenMessage>)
// 基于模糊查詢來驗(yàn)證 DOM 元素的存在
expect(screen.queryByText(testMessage)).toBeNull()
// 同樣基于模糊查詢來觸發(fā)事件
fireEvent.click(screen.getByLabelText(/show/i))
// 驗(yàn)證結(jié)果是否符合預(yù)期
expect(screen.getByText(testMessage)).toBeInTheDocument()
})
單元測試、集成測試、組件測試,看起來我們已經(jīng)非常完美地使用自動(dòng)化測試從不同場景與不同維度進(jìn)行了功能的驗(yàn)證,但實(shí)際上,我們還少了一個(gè)非常重要的維度——用戶視角。在程序最終交付驗(yàn)收時(shí),我們可愛的測試同學(xué)會來把各個(gè)功能和鏈路都檢查一遍,而即使你已經(jīng)寫了巨量的測試用例,還是有可能會被發(fā)現(xiàn)大量的問題,這就是因?yàn)橐暯遣煌W鳛槌绦虻拈_發(fā)者,你清楚地了解程序的控制流走向,也對每一個(gè)分支了然于胸,所以在編寫測試用例時(shí)你其實(shí)更像是上帝視角。
要從用戶的視角出發(fā),實(shí)際上我們只需要屏蔽對程序內(nèi)部的所有感知,而只是去使用這個(gè)程序即可。這樣的測試被稱為端到端測試(End-to-End Testing,E2E),它不再關(guān)注內(nèi)部功能單元的細(xì)節(jié),而是完全從外部還原一個(gè)真實(shí)的用戶視角,如前端應(yīng)用中,用戶登錄-搜索商品-加入購物車-編輯商品-結(jié)算商品的一系列交互,誰管你的登錄背后隱藏了多少權(quán)限分級,商品貨架分級設(shè)計(jì)得多么精細(xì),只要這個(gè)流程無法順利走通,那你的系統(tǒng)就是有問題的。
而既然 E2E 測試是在模擬用戶行為,那么其實(shí)我們所需要做的就是使用用戶的環(huán)境來運(yùn)行系統(tǒng)罷了。如對于前端頁面,其實(shí)就是瀏覽器(更準(zhǔn)確地說是瀏覽器內(nèi)核),而對于后端服務(wù)則是客戶端。
以 Cypress 的功能為例,來看看我們是如何模擬用戶行為的:
在前端領(lǐng)域中編寫 E2E 測試,常見的 E2E 測試框架主要包括 Puppeteer、Cypress、Playwright、Selenium 這么幾種。它們之間各有優(yōu)劣,適用場景也有所不同,我們會在下面進(jìn)行比較。
與其他測試場景的重要不同之一,就是 E2E 測試是可以由測試同學(xué)來編寫的(如支持 Python 和 Java 的 Selenium),在產(chǎn)品進(jìn)行迭代的同時(shí),測試同學(xué)會按照功能點(diǎn)變化對應(yīng)地完善測試用例,同時(shí)確保以往所有功能的測試用例不受影響。
Puppeteer、Cypress、Playwright 的取舍
前端 E2E 測試目前常用的包括 Puppeteer、Cypress、Playwright 這么幾款,這就可能讓你感到選擇困難,到底應(yīng)該選哪個(gè)?萬一選了一個(gè),寫著寫著發(fā)現(xiàn)不符合需求了,咋辦?這一部分我們就來簡單介紹一下它們。
先上結(jié)論:非常簡單的場景使用 Puppeteer(需要搭配 Jest-Puppeteer),PC 應(yīng)用使用 Cypress,移動(dòng)端應(yīng)用使用 Playwright。
接著我們再來一個(gè)個(gè)解釋。首先是 Puppeteer,認(rèn)真地說,它就不應(yīng)該用來做 E2E 測試,因?yàn)槿思艺娴木椭皇且粋€(gè)無頭瀏覽器,你要用它來寫寫爬蟲之類的倒還好,強(qiáng)行霸王硬上弓要人家給你干 E2E,一方面是只支持 Chrome + Chromium 內(nèi)核,另一方面人家不帶斷言庫,你還得帶一個(gè) Jest-Puppeteer 一起。但如果是真的非常非常簡單的場景,你還是可以用 Puppeteer ,加上 NodeJs 的基礎(chǔ)斷言庫,通過自動(dòng)化方式確定一些頁面功能還是沒問題的。
然后是 Cypress ,其場景從人家的 Slogan 其實(shí)也能感覺出來:Fast, easy and reliable testing for anything that runs in a browser,注意 in a browser,其實(shí)人家就是提供了無頭瀏覽器,斷言,GUI,以及 Web 下的各種 API ,然后你就可以完全模擬使用瀏覽器進(jìn)行的一切行為了。同時(shí) Cypress 也通過代碼插樁的方式支持了覆蓋率報(bào)告相關(guān)的能力。需要注意的是,Cypress 只支持瀏覽器維度的配置,如 chrome(也支持chromium)、edge、firefox。
因此,如果你更側(cè)重于檢查應(yīng)用在移動(dòng)端的表現(xiàn),那其實(shí)應(yīng)該使用 Playwright 。為什么?Playwright 支持同時(shí)運(yùn)行多個(gè) project,這些 project 可以被配置為使用瀏覽器內(nèi)核(檢驗(yàn) PC、桌面端場景),也可以被配置為使用內(nèi)置的 devices 預(yù)設(shè),來檢驗(yàn)其在移動(dòng)端的表現(xiàn),這些預(yù)設(shè)包括了視口大小、默認(rèn)瀏覽器內(nèi)核(chromium,webkit,safari 等)等等,參考官網(wǎng)的示例配置:
// playwright.config.ts
import { type PlaywrightTestConfig, devices } from '@playwright/test';
const config: PlaywrightTestConfig = {
projects: [
{
name: 'Desktop Chromium',
use: {
browserName: 'chromium',
viewport: { width: 1280, height: 720 },
},
},
{
name: 'Desktop Safari',
use: {
browserName: 'webkit',
viewport: { width: 1280, height: 720 },
}
},
{
name: 'Desktop Firefox',
use: {
browserName: 'firefox',
viewport: { width: 1280, height: 720 },
}
},
{
name: 'Mobile Chrome',
use: devices['Pixel 5'],
},
{
name: 'Mobile Safari',
use: devices['iPhone 12'],
},
],
};
export default config;
在我所在的團(tuán)隊(duì),目前也正在基于 Playwright 建立 E2E 測試用例,來更方便快捷地保障核心應(yīng)用的頁面功能。
最后,如果你并不是在開發(fā)一個(gè)前端應(yīng)用,而是在開發(fā)一個(gè) UI 組件庫,那你可以使用 StoryBook 提供的測試能力(基于 Jest 與 Playwright),這樣一來你既能夠基于 StoryBook 獲得組件的可視化文檔說明,也可以獲得自動(dòng)生成的 E2E 測試用例:
后端服務(wù)中的 E2E 測試與壓力測試
而對于后端服務(wù)中的測試,由于我暫時(shí)還沒有比較深入地實(shí)踐,這里就只簡單介紹下 Node API 中的 E2E 測試、壓力測試。
上面我們已經(jīng)提到,對于后端服務(wù)來說其實(shí)用戶就是各個(gè)客戶端,而我們也只需要模擬客戶端,向 API 發(fā)起請求,模擬登錄態(tài)信息和各種參數(shù),然后查看最終返回的結(jié)果是否符合預(yù)期即可。在這個(gè)過程中,API 由哪個(gè) Controller 承接,調(diào)用了哪些 Service,走過了哪些 Middleware ,我們都不應(yīng)該也無需關(guān)心。而假裝自己是客戶端的方式就簡單多了,常見的方式是使用 supertest 。另外,通常后端服務(wù)的 E2E 測試也應(yīng)該是盡量模擬完整的交互過程:上傳商品-編輯商品-上架商品-下架商品-...,只不過這個(gè)過程并不像在前端那樣直觀。
另外后端服務(wù)中的 E2E 測試如何 Mock 也有不同的情況,如果希望盡可能模擬用戶,可以使用專用的測試環(huán)境數(shù)據(jù)庫,但這樣測試的執(zhí)行就不完全穩(wěn)定。如果希望從簡,那么可以像單元測試與集成測試中那樣模擬掉外部依賴。另外,部分 NodeJs 框架也直接提供了原生的測試支持,如 @nestjs/testing?,@midwayjs/mock 等等。
另外一個(gè)后端服務(wù)特殊的測試場景則是壓力測試,在某些時(shí)候也可以被等價(jià)于性能測試,從某些方面它其實(shí)也是在模擬用戶,只不過不是模擬一個(gè)用戶的交互行為,而是模擬較大量級的用戶訪問,以此來測試服務(wù)的性能。本質(zhì)上壓力測試并不是在測試 API 的邏輯,而是承載 API 的服務(wù)器性能與負(fù)載均衡相關(guān)邏輯。進(jìn)行壓力測試可以很簡單地使用腳本開多線程并發(fā)請求,也可以使用 Apache Bench、Webbench、wrk(wrk2)測試工具,或者 npm 社區(qū)也有 autocannon 這樣的實(shí)現(xiàn)。
在壓力測試下,我們主要關(guān)注這么幾個(gè)指標(biāo):
- 每秒請求數(shù) RPS,Request Per Second,更常見的稱呼是每秒查詢數(shù) QPS,Query Per Second,它代表了到達(dá)服務(wù)器的請求數(shù)量。
- 并發(fā)用戶數(shù) CL,Concurrency Level,不同于 RPS,并發(fā)數(shù)代表了當(dāng)前仍未完結(jié)的等待處理的請求。舉例來說,假設(shè)某個(gè)神奇 API 的請求處理速度非???,每個(gè)請求的處理時(shí)間無限趨近于 0 ,那么即使其 RPS 可能達(dá)到一百萬,并發(fā)數(shù)卻也非常低(趨近于0)——因?yàn)樗幚淼膶?shí)在是太快了,幾乎不需要同時(shí)處理兩個(gè)請求。
- 每秒事務(wù)數(shù) TPS,Transactions Per Second,TPS 有點(diǎn)類似于 QPS,但它所關(guān)注的事務(wù)其實(shí)是比請求-響應(yīng)過程更具象的過程,舉例來說,訪問 server/index.html ,實(shí)際上還訪問了 server/index.css 與 server/index.js 文件,那么這個(gè)過程實(shí)際上只會記為一次事務(wù),但會記為三次查詢。
- 響應(yīng)時(shí)間 RT,Response Time,一個(gè)請求從進(jìn)入到帶走響應(yīng)的耗時(shí),這個(gè)耗時(shí)包括了等待時(shí)間-處理時(shí)間-IO讀寫時(shí)間-響應(yīng)到達(dá)時(shí)間。
除了這些指標(biāo)以外,我們還會關(guān)注服務(wù)器當(dāng)前的性能指標(biāo),如內(nèi)存與 CPU 占用率,駐留集(RSS,當(dāng)前進(jìn)程獲得分配的物理內(nèi)存,包括堆、棧與執(zhí)行代碼段等),你也可以使用 NodeJs 提供的 --prof? --prof-process 等啟動(dòng)參數(shù),或使用 heapdump 提供的內(nèi)存快照打印功能來幫助分析 Node API 的性能。
尾聲
除了以上介紹的這些自動(dòng)化測試分類,其實(shí)還有著前端頁面的性能測試(如基于 LightHouse、Performance API),主要關(guān)注各種“首次”的指標(biāo),如首屏繪制、可交互時(shí)間、最大內(nèi)容繪制等等,基于 axe-core 的可訪問性測試(Accessibility Testing),關(guān)注網(wǎng)頁的可訪問性,以及一些相對少見的場景,如基于 Needle 的 CSS 測試、基于 Coffee 的命令行應(yīng)用測試,以及混沌工程理念中的混沌測試等,這些概念要么在社區(qū)里已經(jīng)存在大量的高質(zhì)量介紹文章,要么我并沒有深入了解過,在這里就不贅述了。
另外,想要進(jìn)一步地保障頁面的功能穩(wěn)定性,監(jiān)控平臺(白屏,JS Error,404)這一類的存在也是相當(dāng)有意義的,但這一部分功能已經(jīng)存在太多方案,社區(qū)的 Sentry,以及各大廠內(nèi)部自己建設(shè)的平臺等等,這里就不再贅述。
這篇不長也不短的小作文里,我們基本上把前端開發(fā)者會接觸到的自動(dòng)化測試種類都了解了一遍,包括它們的使用場景,實(shí)踐方式,以及可選的庫/框架。在完成全文閱讀后,如果你恰好在開發(fā)“值得投入精力編寫測試”的應(yīng)用,不妨思考下,上面是否恰好有符合你所需求的部分。