Vue.js 測試端到端指南
“當(dāng) Vue 的用戶數(shù)量達(dá)到一定數(shù)量時(shí),它就變成了一個(gè)社區(qū)。突然間,所有這些人都指望我了:貢獻(xiàn)者、用戶、教育工作者、學(xué)生……它變得比我想象的要大?!?– 尤文
這是一位開發(fā)者對(duì) 2014 年發(fā)布的 JS 框架的自白,該框架如今已被超過150 萬用戶使用。如果我們考慮一個(gè)框架有多新,它在網(wǎng)站開發(fā)中就變得很重要。隨著開發(fā)人員慢慢接受 Vue,Vue.js 測試的問題在組織中變得更加有趣。
該框架在一個(gè)不是很流行的地方,所以每個(gè)問題都可以在社區(qū)渠道上找到,并且不是新到還處于試驗(yàn)階段。當(dāng)我們看到使用 Vue 構(gòu)建的大型應(yīng)用程序時(shí),我們知道 Vue.js 測試的相關(guān)性只會(huì)隨著時(shí)間的推移而增加。
所有這些事實(shí)使本指南成為拼圖的重要組成部分,最終將指導(dǎo)您向世界發(fā)布基于 Vue.js 的 Web 應(yīng)用程序。
什么是 Vue.js?
Vue.js 是一個(gè)用于構(gòu)建復(fù)雜或簡單用戶界面的框架。它于 2014 年發(fā)布,如今被近 1% 的網(wǎng)站使用。它是輕量級(jí)的,構(gòu)建在 HTML、CSS 和 JavaScript 等主要 Web 組件之上。
它使用基于組件的模型視圖框架范例,允許將模塊構(gòu)建為松散耦合和連接的組件。這有助于將復(fù)雜的模塊分解為應(yīng)用程序的其他部分也可以重用的小組件。
Vue.js 表達(dá)其基于組件的功能的一個(gè)小例子如下:
在這里,我們通過代碼看到了 HTML 中聲明式渲染的一個(gè)重要概念{{count}}。通過聲明式渲染,我們指出了模板渲染部分,我們可以在其中使用聲明性語法或模板語法直接渲染數(shù)據(jù),這也是 Jinja 2 模板引擎中的雙括號(hào)。這是 Vue 的一個(gè)重要屬性,可以在快速開發(fā)和最小化代碼方面派上用場。
第二個(gè)屬性是反應(yīng)性,自動(dòng)對(duì) JavaScript 代碼中的更改做出反應(yīng)。然后,更改會(huì)反映在 DOM 中,而無需編寫任何額外的代碼。然而,這是對(duì)反應(yīng)性的簡要概括,需要詳細(xì)討論。由于本指南圍繞測試 Vue 組件展開,讓我們改天再討論。
Vue.js 基于組件的系統(tǒng)概述
基于組件的系統(tǒng)的基本思想是將較大的事物劃分為較小的單元,并孤立地關(guān)注每個(gè)單元。這有助于分解一個(gè)更大的問題,并專注于如果立即采用整個(gè)系統(tǒng)可能會(huì)遺漏的細(xì)節(jié)。當(dāng)我們開發(fā)被分成基于組件的樹的簡單 HTML 頁面時(shí),也可以看到這一點(diǎn):
組件樹
在 Vue 中,我們通過將每個(gè)組件保存到其文件中并將其邏輯作為擴(kuò)展來執(zhí)行類似的操作.vue。
為了理解 Vue.js 中組件的最小示例,讓我們創(chuàng)建一個(gè)小網(wǎng)頁,如下所示:
在 Vue 的app.js文件中,我們將創(chuàng)建一個(gè)組件來演示可重用性,如下所示:
在編寫代碼時(shí),將其替換為您要放置的組件的名稱:
我們將放下一個(gè)簡單的模板來替換對(duì)象:
在這里,模板部分采用您希望在屏幕上呈現(xiàn)此組件時(shí)顯示的 HTML 模板。
有了這段小代碼,我們的組件就可以在我們一開始編寫的 HTML 頁面中實(shí)現(xiàn)了。由于此組件由名稱“ vcomp ”引用,因此讓我們將其插入 div 塊中,如下所示:
Vue 在這里要做的是用 中描述的組件模板替換 vcomp 標(biāo)簽app.js。結(jié)果,我們得到一個(gè)小網(wǎng)頁如下:
小網(wǎng)頁
如果我們檢查這個(gè)網(wǎng)頁,我們可以檢查 HTML 代碼是否已被 Vue 中提供的模板替換:
模板
一個(gè)簡單的問題是代碼已經(jīng)變得可重用,但不能根據(jù)我們的選擇進(jìn)行定制。在 Web 開發(fā)中,您可能有許多具有相同代碼的元素。我們上面的例子可以滿足的需求。然而,我們可以有更多的代碼,它們不相同但相似。例如,“Hi, I am Harish”和“Hi, I am Jack”是兩個(gè)相似元素,與“Hi, I am”的相似度為 75%。如果我們能找到一種方法將數(shù)據(jù)放入此模板中,我們就會(huì)擁有一個(gè)很好的組件。
這是通過附加到 Vue 組件的數(shù)據(jù)對(duì)象來完成的。現(xiàn)在,我們修改后的視圖為:
這表示將保持不變的部分。一個(gè)數(shù)據(jù)對(duì)象寫成:
在函數(shù)部分,你可以編寫你想要執(zhí)行的函數(shù)。對(duì)于我們的示例,您需要返回名稱以將其作為:
另外,請(qǐng)注意我們?cè)谀0逯蟹胖玫母郊禹?xiàng){{name}},我們希望在返回時(shí)放置名稱。
我們需要做的最后一件事是決定何時(shí)調(diào)用此函數(shù)以及如何調(diào)用它。雖然有很多方法可以實(shí)現(xiàn)這一點(diǎn),但為了演示,我將把on:click事件附加到一個(gè)按鈕上,單擊該按鈕可以調(diào)用該函數(shù)。
修改后的代碼則變成如下:
這里要注意的兩個(gè)修飾元素是“ methods ”和“ button ”。運(yùn)行這段代碼,你會(huì)得到一個(gè)按鈕,點(diǎn)擊它的名字“嗨,我是”變成“嗨,我是阿什利”。
單元測試:概述
單元測試是測試軟件的支柱之一,另一個(gè)是集成測試和端到端測試。通常,軟件測試從單元測試開始,尤其是當(dāng) TDD 作為一種開發(fā)方法得到促進(jìn)時(shí)。
單元測試將軟件分解成更小的單元,因此更容易關(guān)注更小的部分及其細(xì)節(jié),調(diào)試也變得容易得多。這個(gè)定義可能看起來類似于我們?cè)谏厦娴慕M件定義中討論的內(nèi)容。
實(shí)際上,它們都有相似的根源,但它們所服務(wù)的目標(biāo)卻不同。由于組件在 Vue 應(yīng)用程序中也是較小的單元,因此測試人員執(zhí)行單元測試的工作變得容易得多,并且針對(duì)特定區(qū)域。因此,Vue 組件中的單元測試是 Vue 測試人員之間的熱門話題。
請(qǐng)注意,這不應(yīng)與“測試組件”混淆,因?yàn)閱卧獪y試適用于基于 Vue 的應(yīng)用程序。單元測試仍然意味著測試預(yù)期輸出的功能或類,但只針對(duì)應(yīng)用程序的一小部分。
當(dāng)我們開始只測試 Vue 應(yīng)用程序的組件時(shí),例如它如何掛載或呈現(xiàn),我們稱之為 Vue 中的組件測試。但是,這并不意味著單元測試不涵蓋“僅”組件。在某些情況下,它可能會(huì),而在少數(shù)情況下,它可能不會(huì)。
如何開始在 Vue.js 中進(jìn)行單元測試
在 Vue.js 測試指南的這一部分,我們將在 Vue 中進(jìn)行單元測試,這與 Web 應(yīng)用程序中的單元測試不同。在這里,我們將只關(guān)注如何對(duì)使用 Vue 編寫的應(yīng)用程序的部分進(jìn)行單元測試。
考慮到基于 Vue 的功能是如何工作的,我們的目標(biāo)是對(duì)兩種類型的功能進(jìn)行單元測試。
- 可組合物
- 成分
因此,我們可以將這一節(jié)分為兩個(gè)邏輯部分。
如何在 Vue Composables 中執(zhí)行單元測試
可組合項(xiàng)的概念隨著 Vue 的第 3 版發(fā)布而引入,旨在消除導(dǎo)致復(fù)雜組件和混合的所有 Vue 2 弱點(diǎn)。Vue 可組合是指那些使用 Vue 的組合 API 的函數(shù)。此 API 是針對(duì)隨著時(shí)間的推移變得太大且難以維護(hù)的組件的解決方案。
例如,假設(shè)我們有一個(gè)組件可以通過搜索列出某些產(chǎn)品。稍后,我們需要通過應(yīng)用某些過濾器來在此搜索中提供更多功能。幾天后,我們可能會(huì)添加另一個(gè)搜索功能。做所有這些,我們可能會(huì)制造一個(gè)非常大和復(fù)雜的組件,它會(huì)變得非常難以維護(hù)。
相反,我們可以使用組合 API,它們是從這些組件調(diào)用的可重用函數(shù),并消除了大選項(xiàng)和數(shù)據(jù)。在此示例中,我們可以創(chuàng)建search()、sort()、filter()、advanceFilter()等,并在主組件需要時(shí)調(diào)用。
可組合項(xiàng)可以依賴于以下三個(gè) API 中的任何一個(gè):
- 生命周期
- 注入
- 反應(yīng)性
在這三者中,如果使用反應(yīng)性如下:
- import { createApp } from 'vue'
- createApp({
- data() {
- return {
- counter: 0
- }
- }
- }).mount('#app')
這可以通過直接匹配預(yù)期結(jié)果和實(shí)際結(jié)果來測試,也稱為測試中的斷言。然而,如果使用 lifehooks 和 inject,測試人員需要將這些元素“包裝在主機(jī)組件內(nèi)”,解釋這可能會(huì)使我們偏離實(shí)際的單元測試部分。
如何在 Vue 組件中執(zhí)行單元測試
Vue 組件中的單元測試旨在測試應(yīng)用程序中組件提供的功能。雖然他們應(yīng)該以組件為目標(biāo),但他們應(yīng)該只關(guān)注與這些組件相關(guān)的功能和事件,而不是深入研究代碼的正確性。
在 Vue.js 中執(zhí)行單元測試時(shí)需要注意的重要一點(diǎn)是,不應(yīng)斷言組件實(shí)例的私有狀態(tài),因?yàn)樗赡軙?huì)因任何實(shí)現(xiàn)更改而中斷。單元測試的主要重點(diǎn)應(yīng)該是驗(yàn)證某個(gè)功能或事件或交互的輸出。
Vue.js 組件的單元測試工具
雖然有很多工具和插件可用于對(duì) Vue.js 組件進(jìn)行單元測試,但 Vue 官網(wǎng)僅推薦兩個(gè)工具:
- 齒輪
- 柏
Vitest 是基于節(jié)點(diǎn)的工具,而 Cypress 是基于瀏覽器的工具?;诠?jié)點(diǎn)的工具可能不如基于瀏覽器的工具高效;因此,在這種情況下,Cypress 可能是首選。但是,它會(huì)產(chǎn)生一定的成本。由于 Vitest 是一種無頭工具并且是基于節(jié)點(diǎn)的,因此它可以比 Cypress 更快地執(zhí)行測試。
正如 Vue 所說,“Cypress 可能比 Vitest 慢幾個(gè)數(shù)量級(jí)”, 這可能是一個(gè)值得關(guān)注的問題。因此,測試人員在使用 Vue.js 進(jìn)行單元測試時(shí)必須謹(jǐn)慎工作。
要將 Vitest 添加到您的項(xiàng)目中,您可以直接使用 npm 包管理器將其添加到一個(gè)命令中:
在此之后,我們需要更新 Vite 配置以添加測試選項(xiàng)塊:
完成后,我們可以將測試寫入一個(gè)名稱以*.test.js. 該文件可以放在項(xiàng)目根文件夾中的測試目錄中。您還可以將此文件放在源文件旁邊的測試目錄中。
現(xiàn)在測試用例已經(jīng)寫好了,只需添加測試腳本如下package.json:
現(xiàn)在使用一個(gè)簡單的 npm 命令運(yùn)行這些測試:
安裝庫
掛載庫必須掛載組件,以便可以模擬用戶事件,并且可以使用類似用戶的操作調(diào)用單元測試。這些庫由 Vue 提供,推薦用于 Vue 組件的單元測試。
在這兩者中,@vue/test-utils是一個(gè)低級(jí)庫,@testing-library/vue建立在它之上。因此,從這個(gè)事實(shí)可以明顯看出,@vue/test-utils深入研究 Vue API 的實(shí)現(xiàn)細(xì)節(jié),同時(shí)@testing-library/vue遠(yuǎn)離它,只關(guān)注最終用戶如何使用軟件。對(duì)于測試人員來說,這完全取決于他們根據(jù)情況選擇更喜歡哪一個(gè)。然而,兩者的混合搭配可以產(chǎn)生最好的結(jié)果。
如何在 Vue.js 中運(yùn)行單元測試
Vue.js 中的單元測試可以使用 Vue Test Utils 庫運(yùn)行,這是 Vue.js 的官方單元測試庫。它可以與 Jest、Mocha 和 Karma 等測試運(yùn)行器一起使用,也可以在沒有帶有 jsdom 的測試運(yùn)行器的情況下使用。Vue.js 推薦使用 Jest 進(jìn)行單元測試;因此,我們將在這里遵循相同的模式。
要使用 jest 安裝 Vue 測試工具,請(qǐng)運(yùn)行以下兩個(gè)命令。
安裝cli-plugin-unit-jest運(yùn)行 Jest 測試:
安裝 Vue 測試工具:
現(xiàn)在,我們可以對(duì)我們開始 Vue.js 測試指南的初始代碼做一個(gè)簡單的小測試:
現(xiàn)在,我們首先需要定位此按鈕并返回一個(gè)包裝器以繼續(xù)下一步。這是通過以下代碼實(shí)現(xiàn)的:
現(xiàn)在,找到p這個(gè)按鈕內(nèi)的標(biāo)簽:
然后,我們需要提供一些異步行為來等待點(diǎn)擊發(fā)生,這可以引導(dǎo)我們觸發(fā)我們的代碼:
在這里,正如我們提到的,使用了異步行為,這是 Vue 中一個(gè)很深的話題。希望了解更多信息的人可以參考 Vue.js 文檔中關(guān)于異步行為的官方頁面。運(yùn)行上面的測試暴露了按鈕的功能和包含它的模塊。
在執(zhí)行 Vue.js 測試時(shí),許多組織在為 Windows、macOS、Android 和 iOS 等多個(gè)平臺(tái)構(gòu)建 Web 和移動(dòng)應(yīng)用程序時(shí)面臨嚴(yán)峻挑戰(zhàn)。開發(fā)人員和 QA 團(tuán)隊(duì)面臨著創(chuàng)建內(nèi)部測試基礎(chǔ)架構(gòu)以覆蓋所有瀏覽器、設(shè)備和操作系統(tǒng)的主要挑戰(zhàn),這是一種乏味且昂貴的方法。您仍然需要持續(xù)管理操作系統(tǒng)更新,這是非常不切實(shí)際的。
然而,基于云的測試平臺(tái)使這變得容易。
Vue 中的 Mount 與 ShallowMount
在通過 vue test utils 在 Vue 中執(zhí)行單元測試時(shí),你會(huì)經(jīng)常遇到mount()和shallowMount()在示例中或閱讀其他人的單元測試代碼。測試人員將使用這兩種方法在 Vue 中創(chuàng)建單元測試。
Vue 中的函數(shù)mount()將 Vue 組件作為參數(shù)并返回該組件的包裝器。使用這個(gè)實(shí)例包裝器,測試人員可以與組件交互,因?yàn)樗鼤?huì)捕獲 DOM 并為您呈現(xiàn)它。
該shallowMount()函數(shù)的工作方式也類似,有助于與傳遞的組件進(jìn)行交互。它們之間唯一的區(qū)別是shallowMount()不渲染子組件。而mount()將渲染傳遞的組件及其所有子組件。
因此,它們?cè)诓煌膱鼍昂陀美卸际鞘走x。最重要的是,當(dāng)您需要隔離測試任何組件并需要測試更改對(duì)孩子的影響時(shí),shallowMount就要使用它。否則,如果涉及兒童,那么你應(yīng)該去mount()。這將使您的單元測試用例保持獨(dú)立,并清楚地說明它們的目標(biāo)。
結(jié)論
Vue 是一個(gè)框架,在網(wǎng)站開發(fā)的用戶界面市場中出現(xiàn)了顯著增長。憑借其類似于 React 的基于組件的機(jī)制,Vue 試圖將繁重的模塊分解為更小的組件,這些組件不僅有助于開發(fā),也有助于測試。
本 Vue.js 測試指南討論了網(wǎng)站的測試部分,該網(wǎng)站包含基于 Vue 的元素,特別側(cè)重于單元測試。Vue 有豐富的 API 集合,有助于組件的單元測試,本指南中討論了一個(gè)演示。
對(duì)于 Web 開發(fā)人員和測試人員,我希望本指南能為您的下一個(gè)單元測試項(xiàng)目提供很好的參考。對(duì)于任何反饋和建議,請(qǐng)?jiān)谠u(píng)論部分或通過電子郵件告訴我們。感謝您花寶貴的時(shí)間給這篇文章。