[Jest] 测试快照

news/2025/3/10 21:17:14/文章来源:https://www.cnblogs.com/Answer1215/p/18694744

在对组件进行测试的时候,往往需要从两个方面进行测试:

  • 交互:确保组件在进行交互时功能正常
  • 渲染:确保组件渲染输出正确(比如不会多一个或者少一个 DOM 元素)

针对渲染方面的测试,我们就可以使用快照来进行测试。

所谓快照,就是给渲染出来的 DOM 元素拍一张“照片”(将最终渲染出来的 DOM 以字符串序列的方式记录下来)

快速上手

首先我们有如下的一个组件

import { useState } from "react";function App() {const [items, setItems] = useState(["苹果", "香蕉", "西瓜"]);const [value, setValue] = useState("");const lis = items.map((it, idx) => <li key={idx}>{it}</li>);function addItem() {if (items) {const newItems = [...items];newItems.push(value);setItems(newItems);setValue("");}}return (<div className="App"><inputtype="text"value={value}onChange={(e) => setValue(e.target.value)}/><button onClick={addItem}>添加</button><ul>{lis}</ul></div>);
}export default App;

这个组件非常的简单,就是一个 todolist 的组件,内部有默认的项目,也可以新增项目。

接下来编写我们的测试代码,代码如下:

import { render } from '@testing-library/react';
import App from './App';test('renders learn react link', () => {const { baseElement } = render(<App />);expect(baseElement).toMatchSnapshot();
});

首先从 render 方法中解构出 baseElement(注意 render 方法来源于 testing library)

接下来调用了 toMatchSnapshot(这个方法是 jest 提供的方法)来生成快照。

image-20230511092759962

通过执行结果也可以看到,生成了一张快照,并且在我们的项目目录中(和你的测试文件是同级的),生成了一个名为 _snapshots_ 的目录,里面就是一张测试快照,测试快照的本质就是渲染出来的 DOM 的结构的字符串序列。

// Jest Snapshot v1, https://goo.gl/fbAQLPexports[`renders learn react link 1`] = `
<body><div><divclass="App"><inputtype="text"value=""/><button>添加</button><ul><li>苹果</li><li>香蕉</li><li>西瓜</li></ul></div></div>
</body>
`;

之后在下一次测试的时候,针对这个组件测试,就会将组件渲染出来的 DOM 结构的序列和之前的快照进行一个比对,看是否一致,如果和之前的快照是一致的,那么测试就通过,如果不一致(这一次渲染新增了DOM节点或者少了DOM 节点),那么就说明这一次渲染和之前的渲染不一致的,测试不通过。

如下图所示:

image-20230511093235552

测试快照虽然很简单,但是有一些注意点:

  • 快照本身并不验证渲染逻辑是否正确,它只是防止意外更改,所以当测试快照不通过的时候,我们就需要检查一下所需的元素、样式是否发生了我们不期望的改变
  • 快照失败的时候,如果确定渲染逻辑没有问题,确确实实是结构需要发生更改,那么我们可以更新快照。可以通过 jest --updateSnapshot 这个命令进行更新。

避免大快照

在上面的示例中,我们的组件比较简单,因此我们针对整个组件做了快照,但是在真实的项目中,往往业务组件会比较复杂,一个大组件里面会嵌套很多的小组件,这个时候如果你直接对整个大组件进行快照,那么就会导致你的快照文件无比的巨大,因为这里快照会将嵌套的组件的 DOM 结构也记录下来。

例如:

import TestUI from "./components/TestUI"
import Items from "./components/Items"function App() {return (<div className="App"><Items/><TestUI/></div>);
}export default App;
function TestUI(){return (<ul data-testid="list"><li>张三</li><li>李四</li><li>王武</li></ul>);
}export default TestUI;
import { useState } from "react";
function Items() {const [items, setItems] = useState(["苹果", "香蕉", "西瓜"]);const [value, setValue] = useState("");const lis = items.map((it, idx) => <li key={idx}>{it}</li>);function addItem() {if (items) {const newItems = [...items];newItems.push(value);setItems(newItems);setValue("");}}return (<div><inputtype="text"value={value}onChange={(e) => setValue(e.target.value)}/><button onClick={addItem}>添加</button><ul>{lis}</ul></div>);
}export default Items;

那么现在针对 App 组件生成快照的时候,就会导致快照文件比较大,因为会连同 TestUI 以及 Items 组件的 DOM 结构一起生成。

这种请求,我们就可以指定只生成某一个部分的快照,这种快照我们称之为小快照。

代码如下:

import { render, screen } from '@testing-library/react';
import App from './App';test('renders learn react link', () => {render(<App />);const content = screen.getByTestId('list');expect(content).toMatchSnapshot();
});

上面的代码,只会针对 TestUI 组件生成快照。

扩展场景

很多人喜欢把快照测试等同于组件的 UI 测试,但是快照有些时候在其他的某一些场景下使用也非常方面。

举个例子:

// getUserById.ts
const getUserById = async (id: string) => {return request.get('user', {params: { id }})
}// getUserById.test.ts
describe('getUserById', () => {it('可以获取 userId == 1 的用户', async () => {const result = await getUserById('1')expect(result).toEqual({// 非常巨大的一个 JSON 返回...})})
});

比如在上面的示例中,http 请求返回的结果是比较大的,这个时候就会有一些冗余的代码,在写 expect 断言的时候就会比较麻烦。

这个时候你就可以使用快照:

// getUserById.ts
const getUserById = async (id: string) => {return request.get('user', {params: { id }})
}// getUserById.test.ts
describe('getUserById', () => {it('可以获取 userId == 1 的用户', async () => {const result = await getUserById('1')expect(result).toMatchSnapshot();})
});

总结

这一小节我们学会了 快照测试。快照测试的思想很简单:

先执行一次测试,把输出结果记录到 .snap 文件,以后每次测试都会把输出结果和 .snap 文件做对比。快照失败有两种可能:

  • 业务代码变更后导致输出结果和以前记录的 .snap 不一致,说明业务代码有问题,要排查 Bug
  • 业务代码有更新导致输出结果和以前记录的 .snap 不一致,新增功能改变了原有的 DOM 结构,要用 npx jest --updateSnapshot 更新当前快照。

不过现实中这两种失败情况并不好区分,更多的情况是你既在重构又要加新需求,这就是为什么快照测试会出现 “假错误”。而如果开发者还滥用快照测试,并生成很多大快照, 那么最终的结果是没有人再相信快照测试。一遇到快照测试不通过,都不愿意探究失败的原因,而是选择更新快照来 “糊弄一下”。

要避免这样的情况,需要做好两点:

  • 生成小快照。只取重要的部分来生成快照,必须保证快照是能让你看懂的
  • 合理使用快照。快照测试不是只为组件测试服务,同样组件测试也不一定要包含快照测试。快照能存放一切可序列化的内容。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[React Jest] 测试 Hook

在进行 React 开发的时候,还有一个非常重要的功能模块,那就是 Hook,自定义 Hook 作为一块公共逻辑的抽离,也会像组件一样被用到多个地方,因此对 Hook 的测试也是非常有必要的。 Hook 没有办法像普通函数一样直接进行测试,因为在 React 中规中,Hook 必须要在组件里面使用…

07_LaTeX之绘图功能

除了排版文字,$\LaTeX{}$ 也支持用代码表示图形。不同的扩展已极大丰富了 $\LaTeX{}$ 的图形功能,`TikZ` 就是其中之一。本章将带你了解一些基本的绘图功能。07_\(\LaTeX{}\) 之绘图功能 目录07_\(\LaTeX{}\) 之绘图功能绘图语言简介\(\textrm{TikZ}\) 绘图语言\(\textrm{Tik…

《计算机网络》笔记——第四章 网络层

目录第4章 网络层网络层提供的两种服务网际协议IP虚拟互连网络分类的IP地址IP地址与硬件地址地址解析协议ARPIP数据报的格式IP层转发分组的流程划分子网和构造超网划分子网无分类编址CIDR(构造超网)最长前缀匹配网际控制报文协议ICMPICMP的应用互联网的路由选择协议 第4章 网络…

《计算机网络》笔记——第三章 数据链路层

计算机网络(第7版)谢希仁目录第3章 数据链路层使用点对点信道的数据链路层三个基本问题(1) 封装成帧(2) 透明传输(3) 差错检测点对点协议PPPPPP协议特点PPP协议的组成PPP协议的帧格式PPP协议的工作状态使用广播信道的数据链路层CSMA/CD协议使用集线器的星形拓扑以太网的信道利…

《计算机网络》笔记——第一章 概述

计算机网络(第7版)谢希仁目录第一章 概述互联网基础结构计算机网络的分类互联网的组成计算机网络的性能计算机网络体系结构TCP/IP的体系结构 第一章 概述 互联网基础结构 互联网服务提供者ISP(Internet Service Provider) 互联网交换点IXP(Internet Exchange Point)计算机…

解析几何笔记

数学 目录数学一、双根式Ex 1Ex 2二、极坐标Ex 1Ex 2三、平移齐次化Ex 1四、同构式Ex 1五、定比点差法Ex 1Ex 2六、极点极线和调和点列 一、双根式 将圆锥曲线和直线联立,展开并做韦达定理是困难的。但是考虑到任意二次方程都可以写成 \(g(x) = a(x_1 - x)(x_2 - x) = 0\) 的形…

线段树总集

引入 一个数列,单点修改(加),区间查询(和)。 上述问题有很多种解法,如树状数组、分块、平衡树等,今天的主题是著名的线段树。 正题 (不确保按难度升序排序,自己看着目录调顺序吧) 线段树基本原理 因为需要区间查询,所以我们希望有一些捷径能将部分的数的和提前算好…

攻防世界reverse难度3

真难做啊攻防世界Reverse3 哎,坐牢,哎,坐牢. 我从来没有觉得ctf有趣过.jpg painful secret-string-400 js虚拟机混淆 我理解错了,一直以为是所有代码翻译一遍. 结果发现是读取字节然后执行代码. 也就是说,它可以直接翻译成ascii码去掉无用的字节码.(还是看wp知道的,看的时候都懵…

线段树总集 1

引入 一个数列,单点修改(加),区间查询(和)。 上述问题有很多种解法,如树状数组、分块、平衡树等,今天的主题是著名的线段树。 正题 (不确保按难度升序排序,自己看着目录调顺序吧) 线段树基本原理 因为需要区间查询,所以我们希望有一些捷径能将部分的数的和提前算好…

央视蛇年春晚Counting Stars中文翻译!

视频链接 : httpe990-5b4b-4262-95d7-7ea2f9425874&modal_id=7464989004501486900&type=general 《Counting Stars》是美国流行摇滚乐队OneRepublic演唱的一首歌曲,由主唱瑞恩泰德创作。这首歌收录于乐队的第三张录音室专辑《Native》中,以其充满活力的旋律和深刻的…

htb Networked walkthrough

nmap扫描只有 22 80 443 端口 443端口访问不了 所以入手点只有80端口了 direarch 扫描网站发现了几个有意思的路径backup 路径下发现了一个压缩tar包下载下来解压看看内容发现是网站源码需要代码审计我审计了半天也没发现什么问题看看wp说是加个gif89a的文件头就可以上传文件 我…

Janus Pro:DeepSeek 开源革新,多模态 AI 的未来

Janus Pro 是 DeepSeek 开发的一个开源多模态人工智能框架,它通过集成视觉和语言处理能力,提供了高性能的多模态任务处理能力。 在线体验: https://deepseek-januspro.com/ 背景 Janus Pro 于2025年1月发布,是一个开源的多模态AI框架,能够同时处理视觉和语言信息。它采用了…