基于Vue的Jest單元測(cè)試入門與實(shí)踐
點(diǎn)擊上方藍(lán)字關(guān)注我們
介紹
Vue-Test-Utils 是 Vue.js 官方的單元測(cè)試實(shí)用工具庫,它提供了一系列的 API 來使得我們可以很便捷的去寫 Vue 應(yīng)用中的單元測(cè)試。
主流的單元測(cè)試運(yùn)行器有很多,比如 Jest、Mocha 和 Karma 等,這幾個(gè)在 Vue-Test-Utils 文檔里都有對(duì)應(yīng)的教程,這里我們只介紹 Vue-Test-Utils + Jest 結(jié)合的示例。
?Jest 是一個(gè)由 Facebook 開發(fā)的測(cè)試框架。Vue 對(duì)其進(jìn)行描述:是功能最全的測(cè)試運(yùn)行器。它所需的配置是最少的,默認(rèn)安裝了 JSDOM,內(nèi)置斷言且命令行的用戶體驗(yàn)非常好。不過你需要一個(gè)能夠?qū)挝募M件導(dǎo)入到測(cè)試中的預(yù)處理器。我們已經(jīng)創(chuàng)建了 vue-jest 預(yù)處理器來處理最常見的單文件組件特性,但仍不是 vue-loader 100% 的功能。
?
環(huán)境配置
通過腳手架 vue-cli 來新建項(xiàng)目的時(shí)候,如果選擇了 Unit Testing 單元測(cè)試且選擇的是 Jest 作為測(cè)試運(yùn)行器,那么在項(xiàng)目創(chuàng)建好后,就會(huì)自動(dòng)配置好單元測(cè)試需要的環(huán)境,直接能用 Vue-Test-Utils 和 Jest 的 API 來寫測(cè)試用例了。
但是新建項(xiàng)目之初沒有選擇單元測(cè)試功能,需要后面去添加的話,有兩種方案:
第一種配置:
直接在項(xiàng)目中添加一個(gè) unit-jest 插件,會(huì)自動(dòng)將需要的依賴安裝配置好。
vue?add?@vue/unit-jest
第二種配置:
這種配置會(huì)麻煩一點(diǎn),下面是具體的操作步驟。
安裝依賴
安裝
Jest和Vue Test Utilsnpm?install?--save-dev?jest?@vue/test-utils安裝
babel-jest、vue-jest和7.0.0-bridge.0版本的babel-corenpm?install?--save-dev?babel-jest?vue-jest?babel-core@7.0.0-bridge.0安裝
jest-serializer-vuenpm?install?--save-dev?jest-serializer-vue
配置 Jest
Jest 的配置可以在 package.json 里配置;也可以新建一個(gè)文件 jest.config.js, 放在項(xiàng)目根目錄即可。這里我選擇的是配置在 jest.config.js 中:
module.exports?=?{
????moduleFileExtensions:?[
????????'js',
????????'vue'
????],
????transform:?{
????????'^.+\\.vue$':?'/node_modules/vue-jest' ,
????????'^.+\\.js$':?'/node_modules/babel-jest'
????},
????moduleNameMapper:?{
????????'^@/(.*)$':?'/src/$1'
????},
????snapshotSerializers:?[
????????'jest-serializer-vue'
????],
????testMatch:?['**/__tests__/**/*.spec.js'],
????transformIgnorePatterns:?['/node_modules/' ]
}
各配置項(xiàng)說明:
moduleFileExtensions告訴Jest需要匹配的文件后綴transform匹配到.vue文件的時(shí)候用vue-jest處理, 匹配到.js文件的時(shí)候用babel-jest處理moduleNameMapper處理webpack的別名,比如:將@表示/src目錄snapshotSerializers將保存的快照測(cè)試結(jié)果進(jìn)行序列化,使得其更美觀testMatch匹配哪些文件進(jìn)行測(cè)試transformIgnorePatterns不進(jìn)行匹配的目錄
配置 package.json
寫一個(gè)執(zhí)行測(cè)試的命令腳本:
{
????"script":?{
????????"test":?"jest"
????}
}
第一個(gè)測(cè)試用例
為了保證環(huán)境的一致性,我們從創(chuàng)建項(xiàng)目開始一步一步演示操作步驟。
用 vue-cli 創(chuàng)建一個(gè)項(xiàng)目
當(dāng)前我用到的是 3.10.0 版本的 vue-cli。開始創(chuàng)建項(xiàng)目:
vue?create?first-vue-jest
選擇 Manually select features 進(jìn)行手動(dòng)選擇功能配置:
Vue?CLI?v3.10.0
┌───────────────────────────┐
│??Update?available:?4.0.4??│
└───────────────────────────┘
??Please?pick?a?preset:
??VUE-CLI3?(vue-router,?node-sass,?babel,?eslint)
??default?(babel,?eslint)
??Manually?select?features
勾選 Babel、Unit Testing:
??Check?the?features?needed?for?your?project:
???Babel
???TypeScript
???Progressive?Web?App?(PWA)?Support
???Router
???Vuex
???CSS?Pre-processors
???Linter?/?Formatter
???Unit?Testing
???E2E?Testing
選擇 Jest:
??Pick?a?unit?testing?solution:
??Mocha?+?Chai
??Jest
選擇 In dedicated config files 將各配置信息配置在對(duì)應(yīng)的 config 文件里:
??Where?do?you?prefer?placing?config?for?Babel,?PostCSS,?ESLint,?etc.??(Use?arrow?keys)
??In?dedicated?config?files
??In?package.json
輸入n,不保存預(yù)設(shè):
??Save?this?as?a?preset?for?future?projects??(y/N)?n
項(xiàng)目創(chuàng)建完成后,部分文件的配置信息如下:
babel.config.js:
module.exports?=?{
????presets:?[
????????'@vue/cli-plugin-babel/preset'
????]
}
jest.config.js, 這個(gè)文件的配置默認(rèn)是預(yù)設(shè)插件的,可以按實(shí)際需求改成上面提到的配置 Jest 里的配置一樣。
module.exports?=?{
????preset:?'@vue/cli-plugin-unit-jest'
}
package.json:
{
????"name":?"first-vue-jest",
????"version":?"0.1.0",
????"private":?true,
????"scripts":?{
????????"serve":?"vue-cli-service?serve",
????????"build":?"vue-cli-service?build",
????????"test:unit":?"vue-cli-service?test:unit"
????},
????"dependencies":?{
????????"core-js":?"^3.1.2",
????????"vue":?"^2.6.10"
????},
????"devDependencies":?{
????????"@vue/cli-plugin-babel":?"^4.0.0",
????????"@vue/cli-plugin-unit-jest":?"^4.0.0",
????????"@vue/cli-service":?"^4.0.0",
????????"@vue/test-utils":?"1.0.0-beta.29",
????????"vue-template-compiler":?"^2.6.10"
????}
}
執(zhí)行測(cè)試命令
用上面的步驟創(chuàng)建的項(xiàng)目完成項(xiàng)目后,我們可以在 package.json 的 scripts 項(xiàng)中看到有個(gè) test:unit ,執(zhí)行它:
cd?first-vue-jest
npm?run?test:unit
然后終端里會(huì)看到輸出結(jié)果,PASS 表示測(cè)試用例通過了,這個(gè)是官方提供單元測(cè)試?yán)印O旅嫖覀儊韺扅c(diǎn)自己的東西。

實(shí)現(xiàn)一個(gè) ToDoList

看上面的原型圖,有這么幾點(diǎn)明確的需求:
在頭部右側(cè)輸入框輸入要做的事情,敲回車后,內(nèi)容跑到待完成列表里,同時(shí)清空輸入框 輸入框?yàn)榭盏臅r(shí)候敲回車,不做任何變化 待完成列表支持編輯功能,已完成列表不能進(jìn)行編輯 每個(gè)列表項(xiàng)的右側(cè)都有刪除按鈕,用 -號(hào)表示,點(diǎn)擊后刪除該項(xiàng)待完成列表有標(biāo)記為已完成的按鈕,用 √號(hào)表示,點(diǎn)擊后當(dāng)前項(xiàng)移動(dòng)到已完成列表已完成列表有標(biāo)記為未完成的按鈕,用 x號(hào)表示,點(diǎn)擊后當(dāng)前項(xiàng)移動(dòng)到未完成列表列表序號(hào)從1開始遞增 當(dāng)待完成列表為空的時(shí)候,不顯示待完成字樣 當(dāng)已完成列表為空的時(shí)候,不顯示已完成字樣
先把上面的頁面寫好
寫頁面之前先把創(chuàng)建項(xiàng)目的時(shí)候生成的 HelloWorld.vue 和對(duì)應(yīng)的測(cè)試文件 example.spec.js 刪除;同時(shí)修改 App.vue 文件,引入 ToDoList 組件:
<template>
????<div?id="app">
????????<ToDoList>ToDoList>
????div>
template>
<script>
import?ToDoList?from?'./components/ToDoList'
export?default?{
????components:?{
????????ToDoList
????}
}
script>
在 src/compoents 下新建一個(gè)文件 ToDoList.vue,樣式較多就不貼出來了,具體可以去看本項(xiàng)目源碼:
<template>
????<div?class="todolist">
????????<header>
????????????<h5>ToDoListh5>
????????????<input?class="to-do-text"?
????????????????v-model="toDoText"?
????????????????@keyup.enter="enterText"?
????????????????placeholder="輸入計(jì)劃要做的事情"/>
????????header>
????????<h4?v-show="toDoList.length?>?0">待完成h4>
????????<ul?class="wait-to-do">
????????????<li?v-for="(item,?index)?in?toDoList"?:keys="item">
????????????????<p>
????????????????????<i>{{index?+?1}}i>
????????????????????<input?:value="item"?@blur="setValue(index,?$event)"?type="text"?/>
????????????????p>
????????????????<p>
????????????????????<span?class="move"?@click="removeToComplete(item,?index)">√span>
????????????????????<span?class="del"?@click="deleteWait(index)">-span>
????????????????p>
????????????li>
????????ul>
????????<h4?v-show="completedList.length?>?0">已完成h4>
????????<ul?class="has-completed">
????????????<li?v-for="(item,?index)?in?completedList"?:keys="item">
????????????????<p>
????????????????????<i>{{index?+?1}}i>
????????????????????<input?:value="item"?disabled="true"?type="text"?/>
????????????????p>
????????????????<p>
????????????????????<span?class="move"?@click="removeToWait(item,?index)">xspan>
????????????????????<span?class="del"?@click="deleteComplete(index)">-span>
????????????????p>
????????????li>
????????ul>
????div>
template>
国产毛片一区二区三区亖区内套视频
|
动漫黄色视频网站
|
大香蕉一区二区三区
|
波多野结衣一区二区三区漫画
|
色小姐综合网
|
