
一 为什么要进行测试
前端测试是确保前端应用程序质量和稳定性的重要环节,以下从测试类型、测试框架和工具等方面介绍:
测试类型
- 单元测试:专注于测试单个函数、组件或模块的功能。比如,对一个计算购物车总价的函数进行单元测试,确保输入不同的商品价格和数量组合时,都能正确计算出总价。
- 集成测试:主要验证多个组件或模块之间的交互和集成是否正常。例如,测试一个电商网站中商品列表组件与购物车组件之间的交互,确保添加商品到购物车等操作能正确执行。
- 端到端测试:模拟用户在真实环境中的操作,从应用程序的入口开始,到最终的输出结果,测试整个流程的完整性和正确性。以登录功能为例,端到端测试会模拟用户在浏览器中输入用户名和密码,点击登录按钮,直到成功登录并跳转到相应页面,检查整个过程是否正常。
测试框架和工具
- Jest:是一个流行的 JavaScript 测试框架,具有简洁易用、自动模拟、快照测试和并行执行等特点,适用于各种前端项目,尤其是 React、Vue.js 等框架的项目。
- Mocha:是一个灵活的测试框架,可与各种断言库和测试工具配合使用。它提供了丰富的钩子函数,方便在测试前后执行一些操作,如设置测试环境、清理资源等。
- Chai :是一个常用的断言库,与 Mocha 等测试框架结合使用,提供了多种断言风格,如
expect
、should
和assert
,使测试代码更加易读和灵活。 - Selenium:主要用于端到端测试,它可以控制浏览器进行自动化操作,模拟用户的各种行为,如点击按钮、输入文本、导航页面等,支持多种浏览器和编程语言。
测试流程
- 确定测试策略:根据项目的特点和需求,确定采用哪些测试类型和方法,以及测试的重点和范围。
- 编写测试用例:针对每个测试点,编写详细的测试用例,包括输入数据、预期结果和操作步骤等。
- 执行测试:使用相应的测试框架和工具,运行测试用例,并记录测试结果。
- 分析测试结果:检查测试结果是否符合预期,如果出现失败的测试用例,分析原因并定位问题。
- 修复问题:根据分析结果,对发现的问题进行修复,然后重新执行相关测试,直到所有测试用例都通过。
- 持续集成和自动化测试:将前端测试集成到持续集成流程中,每次代码提交时自动运行测试,确保代码的质量和稳定性。
二 Jest

由facebook推出的测试框架,具有快速,易于配置,社区完善等特点
安装
方式 | 代码 |
---|---|
npm | npm install --save-dev jest |
yarn | yarn add --dev jest |
pnpm | pnpm add --save-dev jest |
简单单元测试
具体流程
1.创建文件并引入jest
bash
mkdir jest-demo && cd
jest-demo pnpm init
pnpm add --save-dev jest
ws .
创建math.js,math.test.js,并修改package.json
JavaScript
//math.js
const sum = (a ,b) => a + b;
module.exports = { sum };
JavaScript
//marh.tset.js
const { sum } = require('./math.js')
describe('Math module', () => {
test('should return sum result when two number plus', () =>{
//given
const num1 = 2
const num2 = 3
//when
const result = sum(num1, num2)
//then
expect(result).toEqual(5)
})
})
json
{
"name": "jest.demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"jest": "^29.7.0"
},
"scripts": {
"test": "jest"
}
}
在控制台输入
pnpm jest
正确

错误

测试的GWT套路
GWT | 3A | 说明 |
---|---|---|
Given | Arrange | 准备测试数据,beforeEach,mock模块 |
When | Act | 行动 |
Then | Assert | 断言 借助Matchers来拓展 |
常见断言语句
1 .toBe (value)
2 .toEqual(value) 来判断值是否符合预期(和be区别是可以判断对象之间值是否相等)
3 .toBeFalsy() 判断布尔值
4 .toHaveLength(number) 判断数组长度
单元测试的模块依赖
在实际测试中,写代码和单元测试时经常会遇到一些需要替身的对象
比如: 数据库,网络请求 ,存取文件
使用Mock
用于替代整个模块
使用Stub
模拟特定行为
使用Spy
来监听模块行为
测试详例
sezrchName.js
JavaScript
import * as services from './services';
const searchNames = (term) => {
const matches = services.getName().filter((name) =>{
return name.includes(term)
})
//只想要三分之一的搜索结果
return matches.length > 3 ? matches.slice(0,3) : matches;
}
const functionNotTested = (term) =>{
return ` Hello ${term}`
}
export default searchNames;
searchNames.test.js
JavaScript
import searchNames from "./searchNames";
import { getName } from "./services";
jest.mock("./services", () => ({
getName:jest.fn()
}));
test('should return empty result when not search' ,() => {
//given
const keyword = 'Jone ';
getName.mockImplementation(() => []);
//when
const result = searchNames(keyword);
//then
expect(result).toEqual([]);
});
test('should return target result when found search' ,() => {
//given
const keyword = 'Jone';
getName.mockImplementation(() => ["Jone","Jill","Ringo","John"]);
//when
const result = searchNames(keyword);
//then
expect(result).toEqual(['Jone']);
});
test('should not return more than 3 matches' ,() => {
//given
const keyword = 'John';
getName.mockImplementation(() => [
"Jone",
"Jill",
"Ringo",
"John wick 1",
"John wick 2",
"John wick 3",
"John wick 4",
"John wick 5"
]);
//when
const result = searchNames(keyword);
//then
expect(result).toHaveLength(3);
});
test('should handle null or undefined as input' ,() => {
//given
getName.mockImplementation(() => []);
//then
expect(searchNames(undefined)).toEqual([]);
expect(searchNames(null)).toEqual([]);
});
test('should return search result is case sensitive' ,() => {
//given
getName.mockImplementation(() => ["Jone","Jill","Ringo","John"]);
//then
expect(searchNames('john')).toEqual([]);
});
services.js
JavaScript
export function getName() {
return []
}
注意:此时会报错
Cannot use import statement outside a module
安装依赖(详情见官网)
bash
npm install --save-dev babel-jest @babel/core @babel/preset-env
并在项目根目录添加babel.config.js
JavaScript
module.exports = {
presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};
运行结果

查看多少代码被测试
bash
pnpm test --coverage

根目录下会有一个coverage文件夹里面的html是报告


前端组件化UI测试
测试框架 Test Library
创建项目
bash
npx create-react-app my-react-app
App.js
JavaScript
import './App.css';
import {useState} from "react";
function App() {
const [fullName, setFullName] = useState('')
return (
<div className="App">
<input type="text" placeholder={"Type your name"} value={fullName} onChange={(e) => setFullName(e.target.value)}/>
<p>my name is <span>{fullName}</span></p>
</div>
);
}
export default App;
App.test.js
JavaScript
import { render, screen } from '@testing-library/react';
import App from './App';
import userEvent from "@testing-library/user-event";
test("should show full name when type" , () =>{
//given
const name = "Jone"
//when
render(<App />)
userEvent.type(screen.queryByPlaceholderText("Type your name"),name)
//then
expect(screen.getByText(name)).toBeInTheDocument()
})
测试异步代码
JavaScript
navigator.geolocation.getCurrentPosition() //chrome API 异步获得当前位置
即代码有延迟,结果延迟返回
推荐使用async和await的语法糖

有三个地方可以进行测试 分别是
1.在Form.js提交前将app.js进行mock
2.也可以在API发送axios方法时进行
3.在浏览器的network中直接进行mock ajax请求
差不多就到这里了,其他的内容比如API Mock测试,前端数据管理测试(比如Redux),UI测试....就不一一讲解了,jest作为了解即可,有兴趣可以自己深入了解,有多余的时间可以去学一下Mock
Jest官方文档
前端自动化测试(这是老学长的课件)
推荐的jest相关文章