vue 应用测试(一) --- 介绍

news2024/11/15 21:41:29

vue 应用测试(一) ---介绍

    • 前端测试简介
    • 组件测试
    • Jest 测试框架简介
      • 其他测试框架
    • 第一个测试
      • 避免误报
      • 如何组织测试代码
    • 组件挂载
      • Vue2 组件挂载的方式
      • Vue3 的挂载方式
      • vue-test-utils
      • 挂载选项
    • 如何调试测试用例
    • 参考
    • 小结

前端测试简介

软件测试:检查软件是否按照预期工作的过程。

测试分类:

从是否需要手动测试来分:

  • 手动测试:需要人工操作,比如点击按钮,输入文字等。
  • 自动测试:写代码测试其他代码,不需要人亲自手动测试每一个功能。

前端测试,从测试的范围来分:

  1. 端到端测试

测试整个应用,从用户角度出发,浏览器自动测试整个应用是否按照预期工作。是自动执行的手动测试,加快手动测试的速度。

  • 优点:测试全面,测试结果可靠。
  • 缺点:① 测试速度慢 ② 调试困难 ③ 可能成为 flakey 测试 ④ 编写测试代码的成本高。

flakey 测试:即使程序没有问题,测试也会失败。

  1. 单元测试

对应用的小部分进行的测试。比如测试一个函数,一个组件等。

  • 优点:① 测试速度快 ② 调试方便 ③ 编写测试代码的成本低 ④ 提供文档功能,可通过测试用例了解代码的行为 ⑤ 稳定,有助于重构。
  • 缺点:测试范围小,测试结果不可靠。

重构:不改变代码的功能,但是改变代码的结构,目的是为了提高代码质量。

  1. 快照测试

快照测试会给运行中的应用程序拍一张图片,并将其与以前保存的图片进行比较。如果图像不同,则测试失败。这种测试方法对确保应用程序代码变更后是否仍然可以正确渲染很有帮助。

按照是否测试实现来分类:

  1. 白盒测试

测试代码的实现,比如测试一个函数,需要知道函数的实现细节和依赖关系,然后编写测试代码。往往是开发人员编写的测试代码。

编写白盒测试,为了隔离复杂的依赖,通常会使用各种模拟手段,来模拟依赖的行为,比如模拟网络请求、用户操作和 pinia 等。

不仅测试做了什么,还要测试怎么做到的。

白盒测试用例往往比较脆弱,一旦代码实现发生变化,测试用例很可能就会失败。

  1. 黑盒测试

不关心代码的实现,只关心代码的输入和输出,比如测试一个函数,只需要知道函数的输入和输出,然后编写测试代码。往往是测试人员编写的测试代码。

要少用模拟或者恰当的模拟,因为你不知道内部的依赖关系,也难以模拟,二来越多的模拟测试越不可靠。

测试做了什么,而不是测试怎么做的。

黑盒测试用例往往比较稳定,一旦代码实现发生变化,测试用例不会失败。

各种测试在前端测试中的占比

为何没有集成测试?

前端的集成测试,难以定义、编写和调试,通常认为端到端测试就是集成测试。

什么时候不需要自动化测试?

自动化测试的目的是为了节省时间和精力,长期开发规模较大的项目自动化测试才会带来巨大的收益。如果项目只是一个小项目,或者是一个短期项目,那么自动化测试可能会带来负担,即编写测试代码会比直接编写应用代码更花时间。

实际上,在我的工作中,前端进行自动化测试的团队都很少,大部分都是手动测试。

不必追求 100% 的测试覆盖率

除非一个 bug 导致了严重的后果,比如损失几百万元,否则不必追求 100% 的测试覆盖率。因为测试代码也是需要维护的,测试代码的维护成本也是需要考虑的。

组件测试

组件有很多属性,决定测试哪些属性很重要,能帮助编写高效的测试代码。

如何决定测试哪些属性?

组件的输入和输出(有人叫组件契约或者组件接口)可帮助决定测试哪些属性。

从开发人员使用组件但又不了解组件具体实现的角度来编写测试,好的组件单元测试应该始终可触发一个输入,并断言一个输出。

常见的组件输入:

  1. 用户操作,比如点击按钮,输入文字等;
  2. props;
  3. 组件事件;
  4. vuex store 中的数据;
  5. inject 注入的数据。

常见的输出:

  1. 触发的事件;
  2. 外部调用的方法,即公有方法;
  3. 渲染结果。

Jest 测试框架简介

测试文件:以 .spec.js 或者 .test.js 结尾。

Jest 在查找项目中测试文件时使用默认的 glob 匹配模式。对于 non-glob 模式而言,这意味着 Jest 匹配tests目录中的.js 和.jsx 文件,以及扩展名为 .spec.js 或 .test.js 的所有文件。

globs 是文件匹配模式。Jest 使用 Node glob 模块匹配文件。你可以在如下链接页面的 glob primer 部分中阅读到更多关于 globs 的内容,glob-primer。

其他测试框架

vitest

peeky

第一个测试

已经存在一个使用 vue-cli 创建的项目,希望添加测试。

  1. 安装 vue 测试插件:
vue add @vue/cli-plugin-unit-jest

使用 vue-cli 创建的项目,可以使用 vue add 命令安装插件,会自动配置测试环境。

  1. 编写 HelloWorld.vue 组件:

安装完毕会自动配置测试环境,并创建了一个测试 HelloWorld.vue 的用例,但是项目里没有 HelloWorld.vue,在 tests/unit 就近新建一个。

<script>
  export default {
    name: 'HelloWorld',
    props: {
      msg: {
        type: String,
        default: '',
      },
    },
    data() {
      return {}
    },
  }
</script>

<template>
  <div>{{ msg }}</div>
</template>

然后引入组件:

import HelloWorld from './HelloWorld.vue'
  1. 运行测试

执行 npm run test:unit ,测试环境是否配置成功。

可用性(sanity)测试

搭建测试系统的第一步是编写一个简单的测试来检查系统是否配置正确。这被称为可用性(sanity)测试

在排查复杂问题或者配置环境时,可用性测试应该成为第一个测试用例,因为它能检查环境是否配置正确。

就近放置测试文件

将单元测试放置在尽可能接近被测代码的位置,会更容易被其他开发人员找到。

避免误报

测试中,需要避免误报。测试之所以通过,是因为源代码正常工作,而不是因为编写始终能通过的测试。

常见的误报测试是使用异步代码

test('sets finished to true after 100ms', () => {
  runner.start()
  setTimeout(() => {
    expect(runner.finished).toBe(true) // 100ms 后 finished 为 true
  }, 100)
})

避免误报的最好方法是使用 TDD。

红色阶段是编写一个因正确原因而失败的测试。这里的关键词是“因正确原因”,即确定程序失败的边界条件。

测试驱动开发(TDD)是一种在编写源代码之前先编写测试代码的工作流程,即在编写组件代码之前,需要先编写能够确保组件正常运行的测试代码。

“红、绿、重构” 是一种很流行的 TDD 方法。红代表编写一个不能通过的测试,绿代表让测试通过,在测试通过后,通过重构增强代码可读性。

以这样的方式开发应用程序会有如下好处。首先,你只编写测试功能的源代码,从而保持较少的源代码量;其次,它可以使你在编写代码之前先考虑组件设计。

如何组织测试代码

describe 函数用于组织测试代码,describe 用于定义一组测试用例,每个测试用例都是一个 test 函数。

describe 函数将多个单元测试用例定义为一个测试套件。当你在命令行运行测试时,Jest 会格式化输出,以便你了解哪些测试套件通过,哪些测试套件失败。

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = shallowMount(HelloWorld, {
      propsData: {
        msg
      },
    })

    expect(wrapper.text()).toMatch(msg)
  })
})

当运行测试时,会在控制台格式化输出 describe 和 test 的一个参数,方便查看测试结果。

一个文件可写多个 describe,describe 可嵌套,

推荐的做法是一个文件只写一个 describe。

否则会降低测试代码的可读性和新加的测试用例的不知道放在哪个 describe 里面。

测试代码和源代码挨近,方便他人查看。

不要嵌套使用 describe,会让测试代码难以理解。

test 表示一个测试用例。

两个参数:

第一个参数是一个 字符串 ,在同一个测试套件中,需要唯一,用于标识测试报告中的测试,用来对你的测试做讲要的说明,方便你的阅读测试报告。

第二个参数是包含测试代码的函数。

it 是它的别名 xit 表示跳过这个测试用例,在跳过某些正在或者不想要测试的用例时特别有用。

test.only 表示只运行这个测试用例,其他测试用例都会被跳过。

三步法(3A法则)写测试用例

  1. 准备测试环境(数据、模拟的函数、模拟模块、挂载组件等,是测试的必要条件)(Arrange),让测试就绪,这里是渲染组件。
  2. 采取行动(Action),执行某些操作,比如用户输入、查找渲染结果等,这里是获取组件的文本内容。
  3. 断言(Assert),判断上述行动是否符合预期,这里是断言组件的文本内容和测试数据是否一致,。

以上三步的代码使用空行分隔,这样可以让测试代码更加清晰可读。

编程的经验法则之一:代码排版反映思路。

代码越是美观合理,说明写下这段代码的时候,思路越是清晰,这样的代码也更容易被其他人理解,反之亦然。

组件挂载

Vue 组件想要渲染到页面上,需要一个挂载的动作,或者说触发组件渲染到页面上的动作叫挂载。

Vue2 组件挂载的方式

  1. 在组件选项中指定 el。

  2. 使用 Vue 构造器动态挂载。

new Vue(componentOptions).$mount(el)

new Vue.extend(componentOptions).$mount(el)

Vue.extend 接收一个组件选项,然后返回一个构造器。

使用 Vue.extend 手动挂载组件,也是 vue2 中实现弹窗的方式,即新建一个和 body 同级的 div,然后把组件挂载到这个 div,从而让组件的渲染结果脱离组件的嵌套关系。

import Vue from 'vue'
const App = {
  props: {
    count: Number,
  },
  data() {
    return {
      msg: 'hello',
      innerCount: 0
    }
  },
  methods: {
    add() {
      this.innerCount += 1
    },
  },

  template: /*html*/ `
  <div v-if="count % 2 === 0">count:{{count}}. count is even.</div>
  <div v-else>count:{{count}}. count is odd.</div>
  <button @click="add">{{innerCount}}</button>
  `,
}

describe('App', () => {
  it('挂载App', () => {
    const Ctor = new Vue.extend(App)
    const app = new Ctor()
    app.$mount()
  })
})

Vue3 的挂载方式

  1. createApp
const app = createApp(App)
app.mount('#app')

使用 createApp 挂载一个弹窗。

<template>
  <div class="modal-container">
    我是弹窗组件
    <button type="button" @click="close">点击我关闭</button>
  </div>
</template>

<script>
  import {
    ref,
    onMounted,
    reactive,
    watch,
    computed,
    defineComponent
  } from 'vue'
  export default defineComponent({
    name: 'Modal',
    components: {},
    setup(props, {
      emit,
      attrs,
      slots
    }) {
      onMounted(() => {
        console.log('onMounted')
      })

      function close() {
        const modal = document.querySelector('.modal')
        document.body.removeChild(modal)
      }
      return {
        close
      }
    },
  })
</script>

<style>
  .modal {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 400px;
    height: 200px;
    z-index: 1000;
    background-color: #ccc;
  }

  .modal-container {
    position: relative;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 100px;
    height: 100px;
    background-color: red;
  }
</style>

在某个组件内执行 mountModal 挂载显示弹窗。

function mountModal() {
  const div = document.createElement('div')
  div.className = 'modal'
  document.body.appendChild(div)
  const modal = createApp(Modal)
  modal.mount(div)
}

参考问题

  1. 瞬移组件 Teleport
<template>
  <Teleport to="modal-container">
    <p>通过to属性指定挂载的DOM</p>
  </Teleport>
</template>

jest 在 jsdom 环境中运行,jsdom 是一个模拟浏览器环境的库,它提供了一些浏览器环境的全局变量,比如 window、document 等。
所以能直接挂载组件。

vue-test-utils

手动挂载组件,代码量较多,vue-test-utils 提供了一些方便的 API 帮我们做这些事情。

mount 方法,该方法在接收一个组件后,会将其挂载并返回一个包含被挂载组件实例(vm)的包装器对象

知道为什么 mount 不直返回 Vue 实例(vm)而是返回包装器?

mount 返回的包装器不仅包含 Vue 实例,还包括一些辅助方法,你可以使用它们来设置 props检查实例属性以及操作实例

常用的包装器方法:

  1. text 方法:返回包装器的文本内容。
  2. html 方法:返回包装器的 HTML 内容。
  3. find 方法:返回包含指定选择器的第一个 DOM 元素的包装器。
  4. exists 方法:返回一个布尔值,指示包装器是否包含一个或多个匹配的元素。
  5. findAll 方法:返回包含指定选择器的所有 DOM 元素的包装器。
  6. setData 方法:设置组件的 data 属性。
  7. setProps 方法:设置组件的 props 属性。
  8. trigger 方法:触发指定的事件。
  9. vm 属性:返回包装器的 Vue 实例。

mount vs shallowMount

另一个挂载方法, shallowMount ,该方法与 mount 方法类似,但是它不会渲染组件的子组件,而是使用 vuecomponent-stub 代替。

它隔离了组件与其子组件的关系,排除了复杂的依赖关系,使得测试更加专注于当前组件。

mount 会渲染子组件,更加贴近真实环境,但是会增加测试的复杂度。

一种不渲染子组件的方 — stubs 模拟子组件。

mount(ParentCom, {
  stubs: {
    Child: true
    Child2: `<span>我是子组件</span>`
  }
})

使用 stubs 对象模拟子组件,可以使用布尔值或者字符串模拟子组件。

这些子组件不会真的渲染,但是它们会存在你的包装器中,你可以使用 find 方法找到它们。

挂载选项

挂载时可以传递一些组件选项,比如 propsData、data、mocks 等,这些选项会覆盖组件的默认选项。

Mounting Options

如何调试测试用例

  1. 使用 vscode 扩展

Jest Runner 可以在 vscode 中运行测试用例,方便调试。

推荐使用

  1. 在 chrome 浏览器调试

开启 jest 调试模式,新加一个脚本:

"test:debug": "node --inspect-brk node_modules/.bin/vue-cli-service test:unit",

没成功,可能哪儿没弄对。你可以试试。

  1. 在 vscode 中调试

参考

vue 官方对测试的建议

Jest 单元测试环境搭建

Vue.js unit test cases with vue-test-utils and Jest

Guide to Unit Testing Vue Components

All Vue Content

Vue NYC - Component Tests with Vue.js - Matt O’Connell—技术演讲

An Introduction to testing in Javascript

小结

  • 介绍了前端测试的分类,单元测试能帮助我们编写高质量的代码。
  • 组件测试的要点:给组件输入,测试输出。
  • Jest 测试框架简介。
  • 3A法则写测试用例。
  • vue 组件渲染的三种方式:shallowMount、mount、Teleport.to 和手动挂载。
  • 不渲染子组件的几种方式:stubs 配置、shallowMount。
  • 调试测试用例的三种方式:vscode 插件、chrome、vscode。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1814268.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(一)

功能模型接口FMI&#xff08;Functional Mock-up Interface&#xff09;是一个开放且与工具解耦的标准。FMI包含了一个C-API&#xff08;接口&#xff09;&#xff0c;一个用于描述接口的XML文件以及可交换的功能模型单元FMU&#xff08;Functional Mock-up Unit&#xff09;&a…

通过nerdctl+buildctl编译发布go程序docker镜像

1 nerdctl安装 下载&#xff1a; wget -c https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-full-1.7.6-linux-amd64.tar.gz 解压&#xff1a; tar -zxf nerdctl-full-1.7.6-linux-amd64.tar.gz -C /usr/local/nerdctl 配置: /usr/local/nerdctl/…

6月报名 | 海克斯康Actran风机类气动噪声分析培训

您好&#xff01;感谢您长期以来对优飞迪科技与海克斯康的关注与支持。我们诚邀您参加海克斯康Actran风机类气动噪声分析培训&#xff0c;特邀海克斯康原厂讲师将以实操为基础&#xff0c;结合真实案例&#xff0c;手把手帮您解锁噪声仿真关键技术。 活动主题&#xff1a; 海…

【架构之路】微服务中常用的几种通信方式

2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f; 强烈推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站:人工智能 引言 微服务架构由于其灵活性、高可扩展性和易维护性&am…

mysql打开远程访问

这里写目录标题 1.使用navicat进入命令控制板,进入use mysql;2.查询用户表3.更新user表中root用户域属性&#xff0c;%表示允许外部访问4.执行以上语句之后再执行&#xff0c;FLUSH PRIVILEGES;5. 执行授权语句 1.使用navicat进入命令控制板,进入use mysql; use mysql;2.查询用…

NOSQL -- MOGODB

Mogodb简介: 是一个开源的, 高性能, 无模式的文档型数据库. NoSql数据库产品当中的一种, 也是最像关系型数据库的非关系型数据库 使用场景: 针对不同的应用场景, 以及其对应的修改对应数据的频率, 我们可以以此选择需要哪一种类型的数据库 Mongo的使用: 启动: 在解压完成之后…

动手学操作系统(六、获取物理内存容量)

动手学操作系统&#xff08;六、获取物理内存容量&#xff09; 在上一节中&#xff0c;我们介绍了保护模式和实模式的区别&#xff0c;保护模式的最大特点是“大”&#xff0c;“大”是指寻址空间大&#xff0c;在进入保护模式之后&#xff0c;我们还将要接触虚拟内存、内存管…

基于pytorch实现的DenseUnet医学图像分割(腹部多脏器)

1、前言 本章将介绍将densenet的主干网络引入unet中 官方实现的代码&#xff1a;kits19-challenge/network at master nitsaick/kits19-challenge (github.com) 本章实现的项目目录如下&#xff1a; 主要代码有train、evaluate、predict脚本 2、代码介绍 数据预处理脚本 数据…

全能型施耐德可编程控制器M241介绍

施耐德M241是一款通信强大、定位控制、丰富扩展于一身的全能型可编程控制器&#xff0c;适用于具有速度控制和位置控制功能的高性能一体型设备。其内置以太网通信端口&#xff0c;可以提供FTP和网络服务器功能&#xff0c;能够更为便捷地整合到控制系统架构中&#xff0c;通过智…

【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用

概述 前三期文章中已经介绍到了 Selenium 与 Playwright 、Pyppeteer 的使用方法&#xff0c;它们的功能都非常强大。而本期要讲的 DrissionPage 更为独特&#xff0c;强大&#xff0c;而且使用更为方便&#xff0c;目前检测少&#xff0c;强烈推荐&#xff01;&#xff01;&a…

Spark Streaming 概述及入门案例

一、介绍 1. 不同的数据处理 从数据处理的方式&#xff1a; 流式数据处理(Streaming)批量数据处理(Batch) 从数据处理的延迟&#xff1a; 实时数据处理(毫秒级别)离线数据处理(小时或天级别) 2. 简介 SparkStreaming 是一个准实时(秒或分钟级别)、微批量的数据处理框架Spa…

了解侧信道攻击基础知识

人们通常认为特洛伊木马、恶意软件和其他形式的黑客攻击等漏洞是的威胁&#xff1b;然而&#xff0c;从 EE 的角度来看&#xff0c;安全性具有全新的含义。  事实上&#xff0c;许多的安全威胁都是基于硬件的&#xff0c;攻击者可以直接从运行我们的安全加密软件的硬件中窃取…

根据mooc 数据库旧代码 实现剥离数据库链接单独成类,并进行测试

数据源详情链接&#xff0c;SQLserver 2019 代码复制粘贴可产生数据 数据库JDBC 查询sqlserver 2019 利用模板实现输入查询-CSDN博客 效果如下 剥离的链接模块 Slinkv2.java package SQLadd;import java.sql.Connection; import java.sql.DriverManager; import java.sql.Re…

CentOS-内网搭建FTP-Server

一、镜像选择 1、 Centos-everting或者DVD 2、7.5 7.6 7.9 均可 二、安装步骤 1、其余步骤和普通安装一致。 2、最重要的一步为“软件选择” 1、勾选FTP、文件以及存储服务器、性能以及开发工具。 三、FTPServer搭建 1、关闭防火墙 systemctl stop firewalld or 通过21和20…

PS教程系统17

橡皮擦工具 主要配合画笔工具来使用 选择画笔工具新建图层试验擦除线条 如果直接在背景图片上进行擦除 会有背景颜色补充 背景橡皮擦 将其白色背景擦除掉shift相关键&#xff0c;进行工作区域切换吸取样点一次采样、两次采样连续、不连续等功能 在进行涂擦的过程一…

为中小制造企业注入数字化转型活力

随着劳动力成本上升,原材料价格上涨,企业生产成本逐年增加&#xff0c;市场竞争越来越激烈&#xff0c;传统的中小制造企业面临着巨大的压力。 通过数字化转型应对环境的变化已成为行业共识&#xff0c;在数字化的进程中&#xff0c;中小企业首要考虑生存问题&#xff0c;不能…

通过ClangFormat进行格式设置时出现错误

1、打开工具->选项 2、文本编辑器->C/C->格式设置->启动ClangFormat支持(去掉勾选)

六种图算法的python实现

六种图算法的python实现 1. Prim 算法 基本原理 Prim算法是一种求解最小生成树的贪心算法。所谓最小生成树&#xff0c;就是对于给定的连通图&#xff0c;找到一棵包含所有顶点的树&#xff0c;且树上所有边的权重之和最小。Prim算法从一个顶点开始&#xff0c;每次选择与当…

[CUDA编程] cuda graph优化心得

CUDA Graph 1. cuda graph的使用场景 cuda graph在一个kernel要多次执行&#xff0c;且每次只更改kernel 参数或者不更改参数时使用效果更加&#xff1b;但是如果将graph替换已有的kernel组合&#xff0c;且没有重复执行&#xff0c;感觉效率不是很高反而低于原始的kernel调用…

使用fvm切换flutter版本

切换flutter版本 下载fvm 1、dart pub global activate fvm dart下载fvm 2、warning中获取下载本地的地址 3、添加用户变量path&#xff1a; 下载地址 终端查看fvm版本 fvm --version 4、指定fvm文件缓存地址 fvm config --cache-path C:\src\fvm&#xff08;自定义地址&…