Vue 组件的单元测试

2023-11-12

1、基本的示例

单元测试是软件开发非常基础的一部分。单元测试会封闭执行最小化单元的代码,使得添加新功能和追踪问题更容易。Vue 的单文件组件使得为组件撰写隔离的单元测试这件事更加直接。它会让你更有信心地开发新特性而不破坏现有的实现,并帮助其他开发者理解你的组件的作用。
这是一个判断一些文本是否被渲染的简单的示例:

<template>
  <div>
    <input v-model="username">
    <div
      v-if="error"
      class="error"
    >
      {{ error }}
    </div>
  </div>
</template>
<script>
export default {
  name: 'Hello',
  data () {
    return {
      username: ''
    }
  },
  computed: {
    error () {
      return this.username.trim().length < 7
        ? 'Please enter a longer username'
        : ''
    }
  }
}
</script>
import { shallowMount } from '@vue/test-utils'
import Hello from './Hello.vue'
test('Hello', () => {
  // 渲染这个组件
  const wrapper = shallowMount(Hello)
  // `username` 在除去头尾空格之后不应该少于 7 个字符
  wrapper.setData({ username: ' '.repeat(7) })
  // 确认错误信息被渲染了
  expect(wrapper.find('.error').exists()).toBe(true)
  // 将名字更新至足够长
  wrapper.setData({ username: 'Lachlan' })
  // 断言错误信息不再显示了
  expect(wrapper.find('.error').exists()).toBe(false)
})

上述代码片段展示了如何基于 username 的长度测试一个错误信息是否被渲染。它展示了 Vue 组件单元测试的一般思路:渲染这个组件,然后断言这些标签是否匹配组件的状态。

2、为什么要测试?

组件的单元测试有很多好处:

  • 提供描述组件行为的文档
  • 节省手动测试的时间
  • 减少研发新特性时产生的 bug
  • 改进设计
  • 促进重构自动化测试使得大团队中的开发者可以维护复杂的基础代码

3、实际的例子

单元测试应该:

  • 可以快速运行
  • 易于理解
  • 只测试一个独立单元的工作我们在上一个示例的基础上继续构建,同时引入一个工厂函数 (factory function)使得我们的测试更简洁更易读。这个组件应该:
  • 展示一个“Welcome to the Vue.js cookbook”的问候语
  • 提示用户输入用户名
  • 如果输入的用户名少于七个字符则展示错误信息让我们先看一下组件代码:
<template>
  <div>
    <div class="message">
      {{ message }}
    </div>
    Enter your username: <input v-model="username">
    <div
      v-if="error"
      class="error"
    >
      Please enter a username with at least seven letters.
    </div>
  </div>
</template>
<script>
export default {
  name: 'Foo',
  data () {
    return {
      message: 'Welcome to the Vue.js cookbook',
      username: ''
    }
  },
  computed: {
    error () {
      return this.username.trim().length < 7
    }
  }
}
</script>

我们应该测试的内容有:

  • message 是否被渲染
  • 如果 error 是 true,则
    应该展示
  • 如果 error 是 false,则
    不应该展示我们的第一次测试尝试:
import { shallowMount } from '@vue/test-utils'
import Foo from './Foo.vue'
describe('Foo', () => {
  it('renders a message and responds correctly to user input', () => {
    const wrapper = shallowMount(Foo, {
      data: {
        message: 'Hello World',
        username: ''
      }
    })
    // 确认是否渲染了 `message`
    expect(wrapper.find('.message').text()).toEqual('Hello World')
    // 断言渲染了错误信息
    expect(wrapper.find('.error').exists()).toBeTruthy()
    // 更新 `username` 并断言错误信息不再被渲染
    wrapper.setData({ username: 'Lachlan' })
    expect(wrapper.find('.error').exists()).toBeFalsy()
  })
})

上述代码有一些问题:

  • 单个测试断言了不同的事情
  • 很难阐述组件可以处于哪些不同的状态,以及它该被渲染成什么样子接下来的示例从这几个方面改善了测试:
  • 每个 it 块只做一个断言
  • 让测试描述更简短清晰
  • 只提供测试需要的最小化数据
  • 把重复的逻辑重构到了一个工厂函数中 (创建 wrapper 和设置 username 变量)更新后的测试:
import { shallowMount } from '@vue/test-utils'
import Foo from './Foo'
const factory = (values = {}) => {
  return shallowMount(Foo, {
    data () {
      return {
        ...values
      }
    }
  })
}
describe('Foo', () => {
  it('renders a welcome message', () => {
    const wrapper = factory()
    expect(wrapper.find('.message').text()).toEqual("Welcome to the Vue.js cookbook")
  })
  it('renders an error when username is less than 7 characters', () => {
    const wrapper = factory({ username: ''  })
    expect(wrapper.find('.error').exists()).toBeTruthy()
  })
  it('renders an error when username is whitespace', () => {
    const wrapper = factory({ username: ' '.repeat(7)  })
    expect(wrapper.find('.error').exists()).toBeTruthy()
  })
  it('does not render an error when username is 7 characters or more', () => {
    const wrapper = factory({ username: 'Lachlan'  })
    expect(wrapper.find('.error').exists()).toBeFalsy()
  })
})

注意事项:
在一开始,工厂函数将 values 对象合并到了 data 并返回了一个新的 wrapper 实例。这样,我们就不需要在每个测试中重复 const wrapper = shallowMount(Foo)。另一个好处是当你想为更复杂的组件在每个测试中伪造或存根一个方法或计算属性时,你只需要声明一次即可。

4、额外的上下文

上述的测试是非常简单的,但是在实际情况下 Vue 组件常常具有其它你想要测试的行为,诸如:

  • 调用 API
  • 为 Vuex 的 store,commit 或 dispatch 一些 mutation 或 action
  • 测试用户交互我们在 Vue Test Utils 的教程中提供了更完整的示例展示这些测试。
    Vue Test Utils 及庞大的 JavaScript 生态系统提供了大量的工具促进 100% 的测试覆盖率。单元测试只是整个测试金字塔中的一部分。其它类型的测试还包括 e2e (端到端) 测试、快照比对测试等。单元测试是最小巧也是最简单的测试——它们通过隔离单个组件的每一个部分,来在最小工作单元上进行断言。

快照比对测试会保存你的 Vue 组件的标记,然后比较每次新生成的测试运行结果。如果有些东西改变了,开发者就会得到通知,并决定这个改变是刻意为之 (组件更新时) 还是意外发生的 (组件行为不正确)。

端到端测试致力于确保组件的一系列交互是正确的。它们是更高级别的测试,例如可能会测试用户是否注册、登录以及更新他们的用户名。这种测试运行起来会比单元测试和快照比对测试慢一些。

单元测试中开发的时候是最有用的,即能帮助开发者思考如何设计一个组件或重构一个现有组件。通常每次代码发生变化的时候它们都会被运行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue 组件的单元测试 的相关文章

随机推荐

  • flask+APScheduler定时任务的使用

    APScheduler定时任务使用以及在flask中的调用 APScheduler简介 组成部分 调度器 安装 普通使用安装 结合flask使用安装 使用 添加job add job参数详解 interval 间隔时间 每隔一段时间执行 d
  • Linux下实现编写汇编程序

    本学期的微机原理课程上机使用的是MASM汇编器 上课时使用的是Windows上的DOS 而Linux中的汇编工具是nasm 具体的可以点击链接 http os 51cto com art 201101 243138 htm 这里写代码片 下
  • C++11智能指针的基本原理及使用

    介绍 智能指针是一个类 用来存储指向动态分配对象的指针 负责自动释放动态分配的对象 防止堆内存泄漏 动态分配的资源 交给一个类对象去管理 当类对象声明周期结束时 自动调用析构函数释放资源 分类 auto ptr 已弃用 使用unique p
  • 神经网络算法和遗传算法,数据挖掘神经网络算法

    神经网络算法与进化算是什么关系 应该没有太大的关系吧 我对遗传算法了解一点 遗传算法主要用来优化神经网络第一次运行时所用的连接权值 因为随机的连接权值往往不能对针对的问题有比较好的收敛效果 Matlab神经网络工具箱自动生成的初始权值其实已
  • Tracy 小笔记 Vue - 网络模块封装(axios)

    安装 axios 和 引入 安装 npm install axios save 引用 import axios from axios 网络请求可以测试的几个接口地址 http httpbin org get http 123 207 32
  • Linux中的JDK安装和配置

    Linux中的JDK安装和配置 1 查看是否已安装JDK yum list installed grep java 2 卸载系统Java环境 yum y remove java 1 8 0 openjdk 3 卸载tzdata java y
  • 那年的夏天很笛子

    原文 salance moon spaces live com 在某个阶段 我想应该是时候把至今为止影响自己走上美工 设计 程序之路的历程整理一下了 但是下笔的时候才发现 其实这几乎成了我童年的回忆录 因为程序暂且不算 美工 设计就是我人格
  • Connect函数阻塞

    1 采用select 在学习嵌入式Linux网络编程中 很多同学都发现了一个问题 那就是调用connect函数时 如果服务端关闭 客户 端调用connect 函数时 发现阻塞在那里 而且利用ctrl c信号去停止客户端程序时 需要等待一个较
  • git:一次回滚多个commit

    说明 独立分散的commit共同回滚 git revert n sha 1 git 单次commit对应的sha 1值 sha 1 sha 1 ps n代表不会生成新的commit 如果想直接生成commit请去掉 n 最近连续的coomi
  • hr谈薪资后说请示领导_如何巧妙回答面试中的薪资问题呢?

    好不容易挺过了群面 单面 没想到在HR面被薪资问题打个措手不及 你的期望薪资是多少 说低了总觉得委屈自己 说高了又怕offer不保 好不容易在前面几轮面试积攒的自信 在这个问题上就变成 emm差不多就行吧 然后面试一结束就开始无限后悔 对于
  • 【ML特征工程】第 1 章 :机器学习管道

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • STM32F407 单片机+DMA+环形缓冲区+GPS报文解析

    本文采用DMA 环形缓冲区对GPS报文进行解析 思路是通过DMA中断接收到GPS报文后 存放到环形缓冲区 然后在主程序中解析GPS报文 解析GPS报文的关键是 将环形缓冲区中的字节转换成字符串 然后在字符串中查找GPS报文头标识 例如 GP
  • Block头部解析

    Block解析介绍了Block的各个组成部分 魔法数 块大小 块头部 交易个数 交易 本文将详细介绍块魔法数和块头部的各个组成部分 魔法数 魔法数是比特币客户端解析Block数据时的识别码 比特币正式网络的魔法数是0xD9B4BEF9 不同
  • 地图标识符号大全_资源小结:分省地图查询(9.1版)

    公众号首页回复关键字 分省地图 或通过菜单栏可以快速找到本页 本页内容不断更新 建议收藏起来备查 北京市 北京市最新行政区划图 行政统计表 图集下载 北京市地图集 分区 北京市人文地图 高清版 北京经典旅游线路图 北京城区地图 一亿像素高清
  • vue3和ts使用

    Vue3和TypeScript是两个非常流行的前端技术 它们都有着自己的优点和特点 Vue3是Vue js的最新版本 它带来了很多新的特性和改进 包括更好的性能 更好的开发体验和更好的可维护性 TypeScript是一种静态类型语言 它可以
  • 一文搞懂STM32 PWM配置

    本文主要介绍通过CubeMX对STM32G070CBT6进行配置生成PWM波 内容包括PWM的基本概念 PWM的应用 PWM产生的方法 STM32 PWM波配置详解 1 PWM PWM 英文名Pulse Width Modulation 是
  • 02-不得不了解的js特性

    一 回顾js特性 针对浏览器端js 它有哪些特性 弱类型 解释型 1 弱类型 所谓强类型 就意味着在声明变量的时候 需要确定数据类型 一经确定就不能改变 而弱类型 在声明变量的时候 是无需声明变量的类型 变量的类型有其值来决定 并且是可以随
  • 使用pyecharts出现 'ModuleNotFoundError: No module named 'pyecharts_snapshot' 异常

    使用pyecharts时 出现 ModuleNotFoundError No module named pyecharts snapshot 试了几次都无法解决 突然想到 pyecharts snapshot 会不会也是一个第三方库 毕竟异
  • MySQL 列属性修改操作

    1 mysql中修改字段长度 sql view plain copy ALTER TABLE tb article MODIFY COLUMN NAME VARCHAR 50 这里的tb article为表名 NAME为字段名 50为修改后
  • Vue 组件的单元测试

    1 基本的示例 单元测试是软件开发非常基础的一部分 单元测试会封闭执行最小化单元的代码 使得添加新功能和追踪问题更容易 Vue 的单文件组件使得为组件撰写隔离的单元测试这件事更加直接 它会让你更有信心地开发新特性而不破坏现有的实现 并帮助其