【2025春第5节课】jest测试

一 为什么要进行测试

前端测试是确保前端应用程序质量和稳定性的重要环节,以下从测试类型、测试框架和工具等方面介绍:

测试类型

  • 单元测试:专注于测试单个函数、组件或模块的功能。比如,对一个计算购物车总价的函数进行单元测试,确保输入不同的商品价格和数量组合时,都能正确计算出总价。
  • 集成测试:主要验证多个组件或模块之间的交互和集成是否正常。例如,测试一个电商网站中商品列表组件与购物车组件之间的交互,确保添加商品到购物车等操作能正确执行。
  • 端到端测试:模拟用户在真实环境中的操作,从应用程序的入口开始,到最终的输出结果,测试整个流程的完整性和正确性。以登录功能为例,端到端测试会模拟用户在浏览器中输入用户名和密码,点击登录按钮,直到成功登录并跳转到相应页面,检查整个过程是否正常。

测试框架和工具

  • Jest:是一个流行的 JavaScript 测试框架,具有简洁易用、自动模拟、快照测试和并行执行等特点,适用于各种前端项目,尤其是 React、Vue.js 等框架的项目。
  • Mocha:是一个灵活的测试框架,可与各种断言库和测试工具配合使用。它提供了丰富的钩子函数,方便在测试前后执行一些操作,如设置测试环境、清理资源等。
  • Chai :是一个常用的断言库,与 Mocha 等测试框架结合使用,提供了多种断言风格,如expectshouldassert,使测试代码更加易读和灵活。
  • Selenium:主要用于端到端测试,它可以控制浏览器进行自动化操作,模拟用户的各种行为,如点击按钮、输入文本、导航页面等,支持多种浏览器和编程语言。

测试流程

  1. 确定测试策略:根据项目的特点和需求,确定采用哪些测试类型和方法,以及测试的重点和范围。
  2. 编写测试用例:针对每个测试点,编写详细的测试用例,包括输入数据、预期结果和操作步骤等。
  3. 执行测试:使用相应的测试框架和工具,运行测试用例,并记录测试结果。
  4. 分析测试结果:检查测试结果是否符合预期,如果出现失败的测试用例,分析原因并定位问题。
  5. 修复问题:根据分析结果,对发现的问题进行修复,然后重新执行相关测试,直到所有测试用例都通过。
  6. 持续集成和自动化测试:将前端测试集成到持续集成流程中,每次代码提交时自动运行测试,确保代码的质量和稳定性。

二 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相关文章

相关推荐
2501_915373881 小时前
Vue 3零基础入门:从环境搭建到第一个组件
前端·javascript·vue.js
沙振宇4 小时前
【Web】使用Vue3开发鸿蒙的HelloWorld!
前端·华为·harmonyos
运维@小兵4 小时前
vue开发用户注册功能
前端·javascript·vue.js
蓝婷儿5 小时前
前端面试每日三题 - Day 30
前端·面试·职场和发展
oMMh5 小时前
使用C# ASP.NET创建一个可以由服务端推送信息至客户端的WEB应用(2)
前端·c#·asp.net
一口一个橘子5 小时前
[ctfshow web入门] web69
前端·web安全·网络安全
读心悦6 小时前
CSS:盒子阴影与渐变完全解析:从基础语法到创意应用
前端·css
湛海不过深蓝7 小时前
【ts】defineProps数组的类型声明
前端·javascript·vue.js
layman05287 小时前
vue 中的数据代理
前端·javascript·vue.js
柒七爱吃麻辣烫7 小时前
前端项目打包部署流程j
前端