老大让弄jest,之前了解过但没写过,今天趁有机会实操一下,顺便写个笔记后面好复习。
基础开始
啥是前端测试?
自己写代码去测自己代码,自动化去测,不用花费大量时间去自己手测。
测试分类
前端开发最常见的测试主要是以下几种:
• 单元测试:验证独立的单元是否正常工作
• 集成测试:验证多个单元协同工作
• 端到端测试:从用户角度以机器的方式在真实浏览器环境验证应用交互
• 快照测试:验证程序的 UI 变化
今天先搞单元测试,后面其他的再补上。
start
vue-cli创建一个带jest的项目
几个简单示例
export const sum = (x, y) => {
return x + y
}
export const subtract = (x, y) => {
return x - y
}
unit文件夹下
其实测试的API内部函数编译出来大概是这样的
注意在 example.spec.js中jest的方法是可以直接调用的,不用引用
执行 npm run test:unit
结果
其他用法
https://www.jestjs.cn/docs/getting-started
vuetestutils 使用
主要测页面功能
开始测试.vue文件
创建测试文件,文件名一定要和vue文件一样。
测试用例
// test('renders props.msg when passed', () => {
// // const msg = 'hello world'
// const root = document.createElement('div')
// root.id = 'app'
// document.body.appendChild(root)
// new Vue({
// render: h => h(App)
// }).$mount('#app')
// console.log(document.body.innerHTML)
// // 验证渲染结果中是否包含 .hello 元素
// expect(document.body.querySelector('h1').innerHTML).toBe('todos')
// // 验证 props 数据是否渲染正确
// // expect(document.body.innerHTML).toMatch('<h1>hello world</h1>')
// })
执行 npm run test:unit
输出组件的html字符串后就可以检查字符串里是否包含某元素了
结果
mount方法
如果把vue文件内容改了后,会报错,并且标记处错误的位置和原因
案例2
模板 todoApp.vue
<template>
<section class="todoapp">
<header class="header">
<h1>todos</h1>
<input
class="new-todo"
placeholder="What needs to be done?"
autofocus
data-testid="new-todo"
@keyup.enter="handleAdd"
/>
</header>
<!-- This section should be hidden by default and shown when there are todos -->
<section class="main">
<input id="toggle-all" class="toggle-all" type="checkbox" />
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
<!-- These are here just to show the structure of the list items -->
<!-- List items should get the class `editing` when editing and `completed` when marked as completed -->
<li data-testid="todo-item" v-for="todo in todos" :key="todo.id" class="completed">
<div class="view">
<input class="toggle" type="checkbox" checked />
<label data-testid="todo-text">{{ todo.text }}</label>
<button class="destroy"></button>
</div>
<input class="edit" value="Create a TodoMVC template" />
</li>
<!-- <li data-testid="todo-item">
<div class="view">
<input class="toggle" type="checkbox" />
<label>Buy a unicorn</label>
<button class="destroy"></button>
</div>
<input class="edit" value="Rule the web" />
</li> -->
</ul>
</section>
<!-- This footer should be hidden by default and shown when there are todos -->
<footer class="footer">
<!-- This should be `0 items left` by default -->
<span class="todo-count"><strong>0</strong> item left</span>
<!-- Remove this if you don't implement routing -->
<ul class="filters">
<li>
<a class="selected" href="#/">All</a>
</li>
<li>
<a href="#/active">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
</li>
</ul>
<!-- Hidden if no completed items are left ↓ -->
<button class="clear-completed">Clear completed</button>
</footer>
</section>
</template>
<script>
export default {
name: 'TodoApp',
data () {
return {
todos: [
{ id: 1, text: 'eat', done: true },
{ id: 2, text: 'sleep', done: true },
{ id: 3, text: 'play', done: false }
]
}
},
methods: {
handleAdd (e) {
const value = e.target.value.trim()
if (!value.length) {
// 没有数据,什么也不做
return
}
// 有数据,添加到任务列表中
this.todos.push({
id: Math.random(),
text: value,
done: false
})
// 清空文本框
e.target.value = ''
}
}
}
</script>
import Vue from 'vue'
import { mount, shallowMount } from '@vue/test-utils'
import TodoApp from '@/components/TodoApp'
test('任务列表展示正常', async () => {
// 给定一份测试数据
const wrapper = shallowMount(TodoApp)//浅渲染
// 准备测试数据
wrapper.vm.todos = [
{ id: 1, text: 'eat', done: true },
{ id: 2, text: 'sleep', done: true },
{ id: 3, text: 'play', done: false }
]
// 等待视图更新
await Vue.nextTick()
// 测试:期望页面中的 dom 元素和数据是匹配的
// console.log(wrapper.findAll('[data-testid="todo-item"]').length)
// console.log(wrapper.vm.todos.length)
// 从众多li中找到指定的data - testid="todo-item
expect(wrapper.findAll('[data-testid="todo-item"]').length).toBe(wrapper.vm.todos.length)
})
npm run test:unit
案例2
import Vue from 'vue'
import { mount, shallowMount } from '@vue/test-utils'
import TodoApp from '@/components/TodoApp'
test('添加任务正常', async () => {
// 给定一份测试数据
const text = 'hello'
const wrapper = shallowMount(TodoApp)//浅渲染
const input = wrapper.find('[data-testid="new-todo"]')
// 给 input 输入内容
await input.setValue(text) // 内部集成了 nextTick
// 触发回车事件
await input.trigger('keyup.enter') // 等待事件触发,视图数据更新
// 断言:列表中多出了一个内容为 hello 的 todo-item
const list = wrapper.findAll('[data-testid="todo-text"]')
const last = list.at(list.length - 1)
expect(last.text()).toBe(text)
// console.log(input.element.value)
// 添加完后一个清空输入框
expect(input.element.value).toBe('')
// expect(input)
})
vuetest官方文档
https://cn.vuejs.org/v2/cookbook/unit-testing-vue-components.html