咱們的首次測試html
讓咱們來寫首個測試。咱們首先須要使用shallowMount手動掛載咱們的組件,並將其存儲在咱們將執行斷言的變量中。咱們還能夠經過propsData屬性傳遞道具做爲對象。vue
已安裝的組件是一個對象,它有一些實用方法:程序員
而後,咱們能夠寫第一個斷言:數組
讓咱們來分析一下這裏發生了什麼。首先,咱們使用Jest的expect函數,它將咱們想要測試的值做爲參數。在咱們的例子中,在父級上用findAll方法來獲取具備活動類的全部元素。這將返回一個WrapperArray,包含Wrappers數組的對象。瀏覽器
一個WrapperArray有兩個屬性:父級(包含的Wrappers)和長度(Wrappers的數量)。後者是咱們須要擁有預期數量的stars。app
expect函數還返回一個對象,咱們能夠在其上調用方法來測試傳遞的值。這些方法稱爲匹配器。在這裏,咱們使用toEqual匹配器並將其做爲參數傳遞給指望值。該方法返回一個布爾值(boolean),這是測試經過或失敗的緣由。函數
總而言之,在這裏,咱們指望在父級中找到的具備活動類的元素的總量應等於3(咱們分配給等級道具的值)。工具
在您的終端中,運行您的測試:單元測試
你應該看到它經過。 測試
模擬用戶輸入
Vue Test Utils能夠輕鬆模擬真實用戶最終在實際中所作的事情。在咱們的用例中,用戶能夠點擊stars來切換它們。咱們能夠在測試中使用觸發器方法僞造它,並調度各類事件。
在這裏,咱們首先用findAll獲取第四顆star,它在傳遞的索引(從零開始的編號)中從WrapperArray返回一個Wrapper。而後,咱們模擬它上面的點擊事件- 咱們模仿點擊第四顆star的用戶行爲。
因爲咱們將prop等級設置爲3,所以在咱們點擊以前,第四個star應該處於非活動狀態,所以click事件應該使其處於活動狀態。在咱們的代碼中,這由一個活動類表示,咱們僅在它們被激活時附加在star上。咱們經過調用star上的classes方法來測試它,它將類名做爲字符串數組返回。而後,咱們使用toContain匹配器來確保活動類在這裏。
設置和拆解
因爲咱們觸發了對組件的點擊,咱們已經改變了它的狀態。問題是咱們在全部測試中使用相同的組件。若是咱們改變測試順序並將其移到第一個位置會發生什麼?而後第二次測試將失敗。
在測試時,你不想依賴諸如命令這樣的脆弱的東西。測試套件應該是強大的,而且除非您破壞API,不然理想狀況下現有測試應該不會改變。
咱們但願確保始終有一個可預測的父級來執行斷言。咱們能夠經過設置和拆卸功能實現這一目標。這能夠幫助咱們在運行測試以前初始化,而後進行清理。
在咱們的例子中,有一種方法能夠是在每次測試以前建立咱們的父級並在以後銷燬它。
正如他們的名字所暗示的那樣,beforeEach和afterEach分別在每次測試以前和以後運行。經過這種方式,咱們能夠100%肯定每當咱們運行新測試時,咱們都能使用新的父級。
測試的特殊標識符
將選擇器與樣式和其餘目的(例如測試鉤子)混合毫不是一個好主意。
若是更改標籤名稱或類怎麼辦?
若是您在要測試的元素上沒有特定的標識符,例如計數器,該怎麼辦?
您不想使用無用的類污染您的生產代碼。爲測試提供專用鉤子會更好,例如專用數據屬性,但僅限於測試期間。這樣就不會在最終構建中留下一團糟。
處理此問題的一種方法是建立自定義Vue指令。
Vue.js實例有一個指令方法,它接受兩個參數- 一個名稱,以及在DOM中注入時組件生命週期的鉤子函數。若是您不關心特定的鉤子,也能夠傳遞單個函數。
讓咱們在src /中建立一個名爲directives的新目錄,並添加一個test.js文件。咱們將在咱們的指令中導出咱們想要傳遞的函數。
一個指令鉤子能夠帶幾個參數,在咱們的例子中,咱們只須要前兩個:el和binding。el參數引用指令綁定的元素。binding參數是一個對象,它包含咱們在指令中傳遞的數據。這樣咱們就能夠按照本身的意願操縱元素。
咱們將一個對象傳遞給咱們的指令,所以咱們能夠從data-test-開始生成數據屬性。在處理函數中,咱們綁定的每一個屬性,並在元素上設置一個基於名稱和值的數據屬性。
咱們將一個對象傳遞給咱們的指令,所以咱們能夠從data-test-開始生成數據屬性。在處理函數中,咱們反覆綁定每一個binding屬性,並在元素上設置一個基於名稱和值的數據屬性。
如今咱們須要註冊咱們的指令,以使用它。咱們能夠在全球範圍內進行,但在咱們的狀況下,咱們只會在本地註冊- 就在咱們的Rating.vue組件中。
咱們的指令如今能夠在v-test名稱下訪問。嘗試在計數器上設置如下指令:
如今使用開發人員工具檢查瀏覽器中的HTML。你的面板應該是這樣的:
開始工做了!如今,咱們在開發模式和構建項目時都不須要這個。此數據屬性的惟一目的是可以在測試期間定位元素,所以咱們只想在運行它們時進行設置。爲此,咱們可使用Webpack提供的NODE_ENV環境變量,這是爲咱們的項目提供動力的模塊捆綁器。
當咱們運行測試時,NODE_ENV被設置爲'test'。所以,咱們可使用它來肯定什麼時候設置測試屬性。
在瀏覽器中刷新您的應用並再次檢查計數器:數據屬性已消失。
如今咱們能夠對咱們須要定位的全部元素使用v-test指令。讓咱們從前面開始測試:
咱們用[data-test-id =「star」]替換了.star選擇器,它容許咱們在不破壞測試的狀況下更改類以用於演示目的。這也是單一責任原則和鬆散耦合的好處之一 。
咱們是否還應該爲咱們測試的類使用這些鉤子?
在將此指令設置爲要測試的目標元素以後,您可能想知道是否還應該使用它們來替換咱們主動查找的類。讓咱們看看第一次測試的斷言:
咱們應該對具備活動類的元素使用v-test,並在斷言中替換選擇器嗎?好問題。
單元測試都是關於一次測試一件事。it函數的第一個參數是一個字符串,咱們用它來描述咱們從消費者的角度作的事情。
包裝咱們斷言的測試表示渲染一個類活動等於prop.grade的star列表。這是消費者的指望。當他們將數字傳遞給grade屬性時,他們但願得到相同數量的活躍或選定的star。然而,在咱們組件的邏輯中,活動類正是咱們用來定義這個特徵的東西。咱們根據具體狀況進行分配,所以咱們能夠在視覺上區分活躍的stars。在這裏,這個特定類的存在正是咱們想要測試的。
所以,在決定是否應該使用已有的選擇器或設置v-test指令時,請問本身一個問題:我在測試什麼,而且使用此選擇器對業務邏輯透視圖有意義嗎?
它與功能或端到端測試有何不一樣?
首先,單元測試組件可能看起來很奇怪。爲何要對UI和用戶交互進行單元測試?這不是功能測試嗎?
在測試組件的公共API(也就是從消費者的角度來看)和從用戶角度測試組件之間存在着根本但微妙的差別。首先,讓咱們強調一些重要的東西:咱們正在測試定義良好的JavaScript函數,而不是UI。
當您查看單個文件組件時,很容易忘記組件編譯成JavaScript函數。咱們沒有測試底層的Vue機制,它從這個函數中致使了面向UI的反作用,好比在DOM中注入HTML。這就是Vue本身的測試已經解決的問題。在咱們的例子中,咱們的組件與任何其餘函數沒有區別:它接受輸入並返回輸出。這些緣由和後果是咱們正在測試的,而不是其餘任何東西。
使人困惑的是,咱們的測試與常規單元測試略有不一樣。一般,咱們寫的東西以下:
這裏沒有爭論。輸入和輸出數據,這就是咱們所關心的。對於組件,咱們指望呈現視覺的東西。咱們正在經過虛擬DOM並測試節點的存在。這也是您使用Selenium或Cypress.io等工具進行功能或端到端測試的方法。那有什麼不一樣呢?
經過單元測試,咱們正在測試單獨的行爲。經過功能或端到端測試,咱們正在測試場景。單元測試可確保程序單元的行爲符合預期。它面向組件的消費者- 在軟件中使用該組件的程序員。功能測試從用戶角度確保功能或工做流的行爲符合預期 。