赞
踩
了解什么是软件测试,以及自动化方式的测试
什么是软件测试?
定义:
在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。
目的:
促进目标鉴定软件的正确性、完整性、安全性和质量。
本质:
其实是对软件的 ”预期输出“ 与 ”实际输出“ 之间的比较过程
常用测试方法:
黑盒测试:主要以用户的视角来测试程序的功能,所以也称功能测试
白盒测试:主要测试程序的代码逻辑,所以也称代码测试
什么是自动化测试?
早先的软件测试工作大都由人来手工完成,其过程极度重复、枯燥、易出错。
而自动化测试则利用程序来模拟人工操作,有效规避了以上问题。
自动化测试的分类:
单元测试:属于一种白盒测试,即编写代码来对项目中的小部件代码进行测试(比如一个函数)
集成测试:属于一种白盒测试,即在单元测试基础上,将模块按设计要求组装为子系统或完整系统进行测试
e2e测试:属于一种黑盒测试,即编写自动化脚本模拟用户操作,检测界面间通信、数据传递等是否如预期
快照测试:属于一种黑盒测试,即事先准备好理想中的参考文件(参考照片),然后再去访问程序并记录当前界面内容(临场拍照),最后比对两者内容是否一致
了解目前流行的几个用于前端的自动化测试框架
完整的自动化测试框架应包含以下 3 个部分:
一、常用前端单元测试框架:
二、常用的e2e测试框架:
使用 Jest 框架来编写单元测试的基本用法
核心内容:
Jest会自动识别和执行项目中所有以.test.js
为后缀的测试代码文件。
具体步骤:
npm i jest --save-dev
src/util.js
function toUpperCase(str) {
return str ? str.toUpperCase() : ""
}
module.exports = {
toUpperCase
}
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('')
})
npx jest
运行结果:
如果目标代码使用了 ESM 模块化,那测试代码也需用 ESM。这时需要安装配置 Babel 进行支持:
npm i babel-jest @babel/core @babel/preset-env --save-dev
babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
node: 'current'
}
}]
],
};
import
导入目标测试代码import { toUpperCase } from './util'
了解测试覆盖率的含义和功能
测试覆盖率,也叫代码覆盖率,指的是被测试的目标代码中至少被执行了一次的条目数占所有条目数的百分比。
它是衡量测试的充分性和完整性的重要指标。
覆盖率根据统计条目的类型,细分为:
语句覆盖率
:以代码语句为最小单位路径覆盖率
:以逻辑路径为最小单位函数覆盖率
:以函数为最小单位代码行覆盖率
:以代码行为最小单位统计代码覆盖率的目的:
常用工具
具体步骤
npx jest --coverage
运行结果:
在这里插入图片描述
另外会生成一个包含 html 格式覆盖率报告的 coverage
目录。
测试包含有如网络请求、定时器等异步行为的目标代码
核心内容:
方式一:回调风格
通过 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('...')
})
具体步骤:
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)
}
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 进行端到端测试
核心内容:
具体步骤:
npm i cypress --save-dev
npx cypress open
Cypress 会搜索到用户电脑上的所有浏览器,供测试时选用:
测试文件名请按 xxx.spec.js
这种命名规则。
e2e测试的本质其实就是模拟用户操作,即用户是如何使用网页界面的。所以 e2e 测试代码就是在利用各种 API 操作网页而已。
Cypress 使用了 Mocha + Chai,因此编写测试代码时用的是来自这两个库的函数,如: describe
、it
、expect
等。
/// <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个')
})
})
介绍针对 Vue 开发的应用代码进行自动化测试的工具
核心内容:
Vue的代码测试涉会及到以下三类:
具体步骤:
一、测试 Vue 组件
# 单元测试
vue add @vue/unit-jest
# 端到端测试
vue add @vue/e2e-cypress
执行后项目中会新增测试专用目录 tests
:
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"/>
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)
})
})
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
没有太大差别。
npm run test:e2e
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。