测试与自动化

  • 软件测试和自动化测试介绍
  • 前端自动化测试框架
  • 使用Jest编写单元测试
  • 统计测试覆盖率
  • 使用Jest测试异步代码
  • 使用Cypress进行e2e测试
  • 测试 Vue 项目

软件测试和自动化测试介绍

了解什么是软件测试,以及自动化方式的测试

什么是软件测试?

定义:

在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。

目的:

促进目标鉴定软件的正确性、完整性、安全性和质量。

本质:

其实是对软件的 ”预期输出“ 与 ”实际输出“ 之间的比较过程

常用测试方法:

  1. 黑盒测试:主要以用户的视角来测试程序的功能,所以也称功能测试

  2. 白盒测试:主要测试程序的代码逻辑,所以也称代码测试

什么是自动化测试?

早先的软件测试工作大都由人来手工完成,其过程极度重复、枯燥、易出错。

而自动化测试则利用程序来模拟人工操作,有效规避了以上问题。

自动化测试的分类:

  1. 单元测试:属于一种白盒测试,即编写代码来对项目中的小部件代码进行测试(比如一个函数)

  2. 集成测试:属于一种白盒测试,即在单元测试基础上,将模块按设计要求组装为子系统或完整系统进行测试

  3. e2e测试:属于一种黑盒测试,即编写自动化脚本模拟用户操作,检测界面间通信、数据传递等是否如预期

  4. 快照测试:属于一种黑盒测试,即事先准备好理想中的参考文件(参考照片),然后再去访问程序并记录当前界面内容(临场拍照),最后比对两者内容是否一致


前端自动化测试框架

了解目前流行的几个用于前端的自动化测试框架

完整的自动化测试框架应包含以下 3 个部分:

  1. 断言库(Assertion Library):用于比对 ”预期输出“ 和 ”实际输出“,并抛出错误
  2. 模拟库(Mock Library):用于模拟数据对象、网络接口等
  3. 测试运行器(Test Runner):用于运行测试代码

一、常用前端单元测试框架:

  1. Jest(完整测试框架)

    • 一个由 Facebook 开源的测试框架,比较新而且目前也比较火
    • 功能全面
    • 零配置
  2. Mocha(核心测试框架)

    • 一个比较成熟的测试框架,社区很大
    • 功能单一但非常灵活,能轻易与其他库结合,比如:Chai(断言库)、Karma(测试运行器)
    • 对异步代码的测试支持的非常好

二、常用的e2e测试框架:

  1. Cypress.io

  2. Puppeteer


使用Jest编写单元测试

使用 Jest 框架来编写单元测试的基本用法

核心内容:

  1. jest 的基本用法

Jest会自动识别和执行项目中所有以.test.js为后缀的测试代码文件。

具体步骤:

  1. 新建项目并安装 jest
npm i jest --save-dev
  1. 编写一些功能代码(先使用 CommonJS 模块,因为用 ESM 需要借助 Babel,后面会举例)

src/util.js

function toUpperCase(str) {return str ? str.toUpperCase() : ""
}module.exports = {toUpperCase
}
  1. 编写用于测试以上代码的 jest 测试代码

jest 提供的常用测试函数:

  • test():创建测试用例,代表一个要测试的场景
  • expect():创建匹配器,并利用 .toBe().toEqual() 等方法进行数据比对

src/util.test.js

// 导入要测试的模块
const { toUpperCase } = require('./util')// 测试用例1:传入参数 'hello',返回 'HELLO'
test('hello to HELLO', () => {expect(toUpperCase('hello')).toBe('HELLO')
})// 测试用例2:传入参数 null,返回 ''
test('null to whitespace', () => {expect(toUpperCase(null)).toBe('')
})
  1. 执行测试
npx jest

运行结果:

如果目标代码使用了 ESM 模块化,那测试代码也需用 ESM。这时需要安装配置 Babel 进行支持:

  1. 安装 babel
npm i babel-jest @babel/core @babel/preset-env --save-dev
  1. 创建 babel.config.js
module.exports = {presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};
  1. 在测试代码中使用 import 导入目标测试代码
import { toUpperCase } from './util'

统计测试覆盖率

了解测试覆盖率的含义和功能

测试覆盖率,也叫代码覆盖率,指的是被测试的目标代码中至少被执行了一次的条目数占所有条目数的百分比。

它是衡量测试的充分性和完整性的重要指标。

覆盖率根据统计条目的类型,细分为:

  • 语句覆盖率:以代码语句为最小单位
  • 路径覆盖率:以逻辑路径为最小单位
  • 函数覆盖率:以函数为最小单位
  • 代码行覆盖率:以代码行为最小单位

统计代码覆盖率的目的:

  • 找出遗漏的测试场景
  • 找出没用到的代码

常用工具

  • Jest - 自带了覆盖率统计工具
  • Karma - 借助第三方库 Istanbul

具体步骤

  1. 在上一章节代码中,执行以下命令生成覆盖率报告
npx jest --coverage

运行结果:
在这里插入图片描述

另外会生成一个包含 html 格式覆盖率报告的 coverage 目录。


使用Jest测试异步代码

测试包含有如网络请求、定时器等异步行为的目标代码

核心内容:

  1. jest 处理异步代码的方式

方式一:回调风格

通过 test() 的回调函数参数 done (它也是个函数,调用它即可告知完成异步任务)

test('some desc', done => {someAsyncTask(data => {try {expect(data).toBe('....')done()} catch(e) {done(e)}})
})

方式二:Promise/async + await 风格

通过在 test() 的回调函数中返回一个 promise 对象

test('some desc', () => {return someAsyncTask().then(data => {expect(data).toBe('...')})
})

或直接用 async/await

test('some desc', async () => {const data = await someAsyncTask()expect(data).toBe('...')
})

具体步骤:

  1. 在上一章节代码基础上,安装 axios 包,并在 src/util.js 中编写一个网络接口调用函数
npm i axios --save

src/util.js

import axios from 'axios'export function getRemoteData() {const url = 'http://www.liulongbin.top:3006/api/getbooks'return axios.get(url).then(res => res.data)
}
  1. src/util.test.js 测试代码中添加新的测试用例:
import { toUpperCase, getRemoteData } from './util'// 测试用例3:获取异步数据
test('get remote data', async () => {// 测试返回 promise 的异步代码,必须要返回 promise 对象// 这样才能让测试正确结束const data = await getRemoteData()expect(data.status).toBe(200)
})

使用Cypress进行e2e测试

安装和使用 Cypress 进行端到端测试

核心内容:

  1. 安装和启动 Cypress
  2. 编写和运行 Cypress 测试代码

具体步骤:

  1. 安装 Cypress
  npm i cypress --save-dev
  1. 打开 Cypress
npx cypress open

Cypress 会搜索到用户电脑上的所有浏览器,供测试时选用:

  1. 创建e2e测试

测试文件名请按 xxx.spec.js 这种命名规则。

  1. 编写测试代码

e2e测试的本质其实就是模拟用户操作,即用户是如何使用网页界面的。所以 e2e 测试代码就是在利用各种 API 操作网页而已。

Cypress 使用了 Mocha + Chai,因此编写测试代码时用的是来自这两个库的函数,如: describeitexpect 等。

/// <reference types="cypress" />describe('测试百度搜索功能', () => {// 每个测试用例都会执行的前置行为beforeEach(() => {// 打开百度首页cy.visit('https://www.baidu.com')})// 一个测试用例it('应该得到搜索结果', () => {// 获取百度首页的关键字输入框,并输入关键字cy.get('#kw').type('前端e2e测试')// 获取百度首页的搜索按钮,并点击cy.get('#su').click()// 对比结果cy.get('.nums_text').should('have.text', '百度为您找到相关结果约3,190,000个')})
})
  1. 点击用例,运行测试

测试 Vue 项目

介绍针对 Vue 开发的应用代码进行自动化测试的工具

核心内容:

  1. 针对 Vue 代码的测试工具介绍
  2. 在 Vue 代码中添加测试工具,并编写测试案例

Vue的代码测试涉会及到以下三类:

  • 单元测试(测试函数)- 可使用 Jest 或 Mocha,官方提供了相关插件,可查看官方文档
  • 组件测试(测试Vue组件)- 官方推荐使用 Vue Test Utils 或它的进一步封装库 Vue Testing Library
  • e2e测试(测试界面)- 可使用专为 Vue 封装的 Cypress

具体步骤:

一、测试 Vue 组件

  1. 在现有的 Vue CLI 项目中,通过 vue-cli 提供的命令添加 Vue Testing Library
# 单元测试
vue add @vue/unit-jest# 端到端测试
vue add @vue/e2e-cypress

执行后项目中会新增测试专用目录 tests

  1. 编写一个新组件Counter.vue,并在 App.vue 中调用

Counter.vue

<template><div><h1 class="title">当前计数:<span class="count">{{ count }}</span></h1><div><button class="btn decrease" @click="decreaseHandler">减少</button><button class="btn increase" @click="increaseHandler">增加</button></div></div>
</template><script>export default {props: {init: {type: Number,default: 0}},data() {return {count: this.init}},methods: {increaseHandler() {this.count += 1},decreaseHandler() {this.count -= 1}}}
</script><style>.count {color: red;}
</style>

App.vue中的调用:

<Counter :init="10"/>
  1. 针对 Counter.vue 组件,编写以下几个单元测试

tests/unit/count.spec.js

import Counter from '@/components/Counter.vue'
import { mount } from '@vue/test-utils'describe('Counter.vue', () => {it('不传 init 属性时显示的初始计数是 0', () => {// 渲染组件const wrapper = mount(Counter)// 获取组件内的数据expect(wrapper.vm.count).toBe(0)})it('传入 init 属性值为 10 时显示的初始计数是 10', () => {const wrapper = mount(Counter, {// 为组件传入属性propsData: {init: 10}})expect(wrapper.vm.count).toBe(10)})it('点击 3 下增加按钮及 1 下减少按钮,当前计数增加 2', () => {const wrapper = mount(Counter)// 获取组件内的元素const btnIncrease = wrapper.find('.increase')const btnDecrease = wrapper.find('.decrease')// 模拟用户点击btnIncrease.trigger('click')btnIncrease.trigger('click')btnIncrease.trigger('click')btnDecrease.trigger('click')// 比对数据expect(wrapper.vm.count).toBe(2)})
})
  1. 运行单元测试
npm run test:unit

在以上单元测试中进行数据比对时,都从组件的实例(vm 对象)上获取数据来进行比对,但有时我们想测试的是界面是否已渲染成我们期望的内容,这时应该这样写:

it('点击 3 下增加按钮及 1 下减少按钮,当前计数增加 2', async () => {const wrapper = mount(Counter)// 获取组件内的元素const btnIncrease = wrapper.find('.increase')const btnDecrease = wrapper.find('.decrease')// (修改点1)模拟用户点击(使用 await)await btnIncrease.trigger('click')await btnIncrease.trigger('click')await btnIncrease.trigger('click')await btnDecrease.trigger('click')// (修改点2)获取界面上的内容来进行数据比较expect(wrapper.get('.count').text()).toBe('2')
})

说明:此处使用 await 是因为 click 事件是异步的,这样才能在异步行为发生后正确获取重新渲染后的界面内容。

二、e2e 测试

在 vue 中进行 e2e 测试其实和直接使用 Cypress 没有太大差别。

  1. 通过以下命令启动 Cypress
npm run test:e2e
  1. 和之前一样,编写和运行 Cypress 测试脚本即可

【测试与自动化】介绍-框架-Jest-覆盖率-异步代码-e2e-Vue测试相关推荐

  1. 测试框架 Jest 实例教程

    Jest 是由 Facebook 开源出来的一个测试框架,它集成了断言库.mock.快照测试.覆盖率报告等功能.它非常适合用来测试 React 代码,但不仅仅如此,所有的 js 代码都可以使用 Jes ...

  2. 微软开源的Web测试和自动化神器 Playwright

    Playwright 是微软开源的一个用于 Web 测试和自动化的框架, 提供了可靠的端到端测试, 功能非常强大, 可以在测试, 爬虫,自动化场景中使用. 跨浏览器 Playwright 支持所有现代 ...

  3. Jest测试框架入门之匹配器与测试异步代码

    一.匹配器 1.对于一般的数字与字符串类型使用 toBe test('adds 1 + 2 to equal 3', () => {expect(1 + 2).toBe(3); });test( ...

  4. 前端自动化测试框架Jest介绍和使用

    在实际项目的自动化测试过程中,如果只有这两个方法,很显然,是远远不够的,这时候,就需要我们对之前的方法进行扩充,同时还有很多自动化的机制需要集成进去.这时候 Jest 闪亮登场! Jest 框架介绍 ...

  5. 前端测试框架—jest基本使用

    前端测试框架-jest基本使用 前言 jest 常见匹配器 基本类型 boolean Number String Array,Set 异常 取反 命令行工具使用 异步代码测试方法 钩子函数 分组(钩子 ...

  6. 顶级测试框架Jest指南:跑通一个完美的程序,就是教出一群像样的学生

    facebook三大项目:yarn jest metro,有横扫宇宙之势. 而jest项目的宗旨为:减少测试一个项目所花费的时间成本和认知成本. --其实,它在让你当一个好老师. jest文档非常简略 ...

  7. 前端测试框架Jest系列教程 -- Expect(验证)

    写在前面 在编写测试时,我们通常需要检查值是否满足某些条件,Jest中提供的expect允许你访问很多"Matchers",这些"匹配器"允许您验证不同的东西. ...

  8. 前端测试框架Jest——语法篇

    使用匹配器 使用不同匹配器可以测试输入输出的值是否符合预期.下面介绍一些常见的匹配器. 普通匹配器 最简单的测试值的方法就是看是否精确匹配.首先是toBe() test('two plus two i ...

  9. 自动化测试(一)基本介绍——测试框架的分类 单元测试工具 E2E测试工具

    自动化测试(一)基本介绍--测试框架的分类 & 单元测试工具 & E2E测试工具 5-3 自动化测试 课程介绍 在前端界,浏览器兼容性是让工程师们头疼的问题,对于经验丰富的人来说,很清 ...

最新文章

  1. [国际A类会议] 2018最最最顶级的人工智能国际峰会汇总!CCF推荐!
  2. {TypeError}argument for rectangle() given by name (‘thickness‘) and position
  3. GridFS读文件代码示例
  4. 7-47 打印选课学生名单 (25 分)(两种做法)(思路加详解+map+vector做法+最后一个点超时解决)+兄弟们冲丫丫
  5. java if else重构_Java编程细节-重构-为什么 if-else 不是好代码
  6. s鼠标在计算机哪部分里,罗技 G700s鼠标游戏软件详解
  7. 科学计算与MATLAB语言之基础知识
  8. AutoCAD Eagle的常规操作和PCB制板及拼板说明
  9. Hadoop技术内幕-Hadoop远程过程调用
  10. MySQL事物和事物回滚
  11. wishbone bus
  12. 如何制作实时库存报表
  13. Maven配置中央仓库
  14. 水表读数图解_水表读数怎么正确看 水表怎么读?
  15. iOS 数据库-SQLite3 CoreData FMDB
  16. 学计算机学文学理,大学期末特惨专业排行榜!
  17. 计算思维(1)-质因数
  18. 区块链,开启数字时代的金钥匙
  19. 单片机按键启停c语言,ZigBee-CC2530单片机 - 按键控制跑马灯的启停
  20. css外层DIV半透明内层div不透明-弹出层效果的实现

热门文章

  1. SpringSecurity退出登录logout报错404
  2. windows server 2016 开启多用户登陆
  3. 【读书笔记】【More Effective C++】异常(Exceptions)
  4. linux创建分区大小命令,Linux使用fdisk创建分区详解
  5. c语言中测长度的函数,c读入文本后,用strlen函数测不出正确长度
  6. IP地址,子网掩码,默认网关,DNS服务器详解
  7. 关于HMM(隐马尔可夫模型)
  8. ThinkRock简介
  9. 如何用python编程能实现输入诗句的上句显示下句_Python爬虫之诗歌接龙
  10. 硕士研究生毕业论文检测加强通过率的四大方法