前端测试最强教程 - 实现 fake http 和 fake db

news2024/11/17 14:47:51

因为想要写出完美的测试,我们就需要模拟各种接口状态,各种动态数据,要求再高点甚至需要模拟鉴权,那这就不是简单的覆盖方法可以实现的。

所以我们需要一些第三方依赖,下面介绍一下实现步骤。

实现步骤

step 1: 新增业务并进行 case design

为了让便于展示测试,我给网站加了一个新功能,在首页会展示网站的标题并且支持修改,这样就需要一个 get 接口,一个 post 接口,并且还需要数据库。

于是我用 koa 搭了一个后端服务,提供两个接口,数据库我不熟,所以我另辟蹊径,在 notion 上新建了一个 page,通过 notionSDK 来获取和更新 page name,这样就成了我的数据库。

别看我说的简单,其实这一套花了我一个下午,有各种意想不到的问题,比如 koa 如何解析 body、 notion 数据结构太复杂、eslint。

tsconfig 配置的问题等等,期间还错把notion key 给 push 了上去,已经给 disable 了。

 具体怎么实现就不细讲了,这不是本系列教程的重点,代码都在github.com/alpacachen/… ,感兴趣可以自己去看一下 server 目录。

总之最后实现的需求大致长这个样子。

对这个需求进行 case design,得到:


G: 网站加载完成

T: 会展示标题 “集成测试框架”

W: 点击修改按钮

T: 会弹出修改弹窗

W: 在输入框中输入 “集成测试框架 2”,点击 “确认修改”

T: 弹窗会关闭,网站标题会更新为“集成测试框架 2”

step 2:完善 app-context,支持xhr

install http-request-mock和lokijs 这两个依赖,重写一下 fake-http-handler.ts这个文件

 

import HttpRequestMock from 'http-request-mock';// 引入 mock 请求的依赖

import { HupuPostDb, TitleDb } from './fake-db';// 引入提前准备好的 fakedb

const mocker = HttpRequestMock.setup()

// mock一下 hupu 接口,数据从写死改为从 db 中读

mocker.mock({

url: '/hupu/api/v2/bbs/walkingStreet/threads?page=1',

method: 'GET',

body: { data: { threadList: HupuPostDb.find() } },

});

// mock 获取标题的请求

mocker.mock({

url: '/api/title',

method: 'GET',

response: () => {

return TitleDb.findOne().title

}

});

//mo 修改标题的请求

mocker.mock({

url: '/api/title',

method: 'POST',

response(req: { body: { title: unknown; }; }) {

// 找到并更新

const prevTitle = TitleDb.findOne().title;

TitleDb.findAndUpdate({ title: prevTitle }, (d) => {

d.title = req.body.title

})

return {};

}

});

http-request-mock这个依赖应该是国人开发,有优秀的中文文档,大家可以看一下,我就不赘述了github.com/huturen/htt…

新建文件 fake-db.ts


import loki from 'lokijs'

import { FakeHupuData } from './fake-data'

const db = new loki('fake-db')

// 创建虎扑热帖集合

const HupuPostDb = db.addCollection('hupu-post')

// 插入默认数据

HupuPostDb.insert(FakeHupuData)


//创建 title 集合

const TitleDb = db.addCollection('title')

// 插入默认数据

TitleDb.insert({ title: '集成测试教程' })

export { HupuPostDb, TitleDb }

接下来我们只需要在 app-context.ts中引入一下 fake-http-handler.ts,这样我们的集成测试就支持了接口和数据的库查询修改。

step 3: 根据 case借助 ai 补充新的测试

接下来我们试试在测试跑一遍中调用接口获取数据,修改数据,再次获取最新数据这个流程。

 

describe('W: 点击标题旁边的 修改按钮', () => {

beforeEach(() => {

fireEvent.click(screen.getByTestId('change-title-but'))

})

it('T: 会弹出弹窗,input 中展示 “集成测试教程”', () => {

expect(screen.getByTestId('title-modal')).toBeTruthy()

expect(within(screen.getByTestId('title-modal')).getByDisplayValue('集成测试教程')).toBeTruthy()

})

describe('W: 修改 title 为 “集成测试教程 2” 关闭弹窗', () => {

beforeEach(async () => {

const input = within(screen.getByTestId('title-modal')).getByDisplayValue('集成测试教程')

fireEvent.change(input, { target: { value: '集成测试教程 2' } })

fireEvent.click(screen.getByText('确定修改'))

await vi.advanceTimersToNextTimerAsync();

})

it('T: 弹窗关闭,顶部栏的文案变为“集成测试教程 2”', () => {

// header

expect(screen.queryByTestId('title-modal')).toBeFalsy()

expect(screen.getByTestId('header').innerHTML).toContain('集成测试教程 2')

})

})

})

这里需要强调一下,这个测试我是直接接在了之前的测试后面,很方便而且直观,只就是为什么我在第一章的时候强调写测试规范的问题,如果测试规范,是非常易于维护和新增的,会大大降低写测试的压力,从此形成良性循环

step: 4 见真章

直接看npm run test npm run coverage得到结果

可以看到除了 server 的代码还是一片绿,并且也没有加几行测试代码 🎉

大家不妨想一想,如果没有集成测试,依靠单测想要达到这种程度的覆盖率需要写多少代码,多少文件?至少需要 header.test.ts和 store.test.ts两个文件,还要 mock 数据,想想就觉得麻烦。

所以重要的事情说三遍,在前端领域

绝大多数单元测试没有任何卵用

绝大多数单元测试没有任何卵用

绝大多数单元测试没有任何卵用

请不要再写单元测试让你自己和你的同事难受了,集成测试才是王道。

结尾

我们集成测试框架基本完成,麻雀虽小,却五脏俱全。

能看到这里的同学想必一定会有些收获,可以尝试拿着这一套思路去套用到你们当前的项目中,年终绩效就不用愁。毕竟一个能写好测试的前端还是不多见的。

当然我这些代码还是有很多值得优化的点,有一些 corner case 发现了但是没有补充测试。比如文件目录可以更加合理,app-context的代码可以组织的更好。

但是作为一个入门教程我认为达到这个程度就够了,切勿直接套用到生产项目中,我提供的是思路,不是代码。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:【文末自行领取】

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JSP 的 request 内置对象

文章目录 前言一、request 内置对象是什么?二、request 对象 1.访问请求参数2.在作用域中管理属性3.获取 cookie4.解决中文乱码5.获取客户端信息6.显示国际化信息总结 前言 我们在学习 JavaScript 的时候有了解过常用对象,这些对象可以在这门脚本语言中全…

java项目之作业管理系统设计与实现源码(springboot)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的作业管理系统设计与实现源码。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 作业管理系统…

怎么选择一款适合自己的蓝牙耳机?2024开放式耳机选购指南

在选择开放式耳机时,可以从以下几个要点着手: 佩戴舒适程度: 耳挂的设计:好的耳挂设计能让耳机稳稳地戴在耳朵上,且不会给耳部造成过多压迫。比如有些耳机配备了可调节的耳挂,能依照不同人的耳型和佩戴习…

WordPress 要求插件开发人员进行双因素身份验证

全球超过40%的网站由 WordPress 提供支持,其庞大的插件和主题生态系统在全球范围内提供了灵活性和定制性。然而,这种受欢迎程度也使其成为网络攻击的主要目标。 WordPress 将为所有插件和主题开发人员引入强制性双因素身份验证 (2FA),以应对…

Vue3动态导入后端路由

动态获取文件 // modules就是一个map,文件路径作为key,文件对象作为value const modulesimport.meta.glob(../views/**/*.vue)获取到的modules对象如下: 添加动态路由 import {createRouter, createWebHashHistory} from vue-routerconst m…

Vue项目开发注意事项

事项一:项目代码放在本地怎么运行起来 1、首先确定项目对应的node和npm版本 node下载地址 Index of /dist/https://nodejs.org/dist/ node 与 npm版本对应关系 Node.js — Node.js Releases 2、node卸载的时候,会自动把对应的npm卸载掉 情况1&…

【源码】询比价管理系统,招投标采购管理系统

前言: 随着互联网和数字技术的不断发展,企业采购管理逐渐走向数字化和智能化。数字化采购平台作为企业采购管理的新模式,能够提高采购效率、降低采购成本、优化供应商合作效率,已成为企业实现效益提升的关键手段。源码获取本文末…

vue3 实现文本内容超过N行折叠并显示“...展开”组件

1. 实现效果 组件内文字样式取决与外侧定义 组件大小发生变化时,文本仍可以省略到指定行数 文本不超过时, 无展开,收起按钮 传入文本发生改变后, 组件展示新的文本 2. 代码 文件名TextEllipsis.vue <template><div ref"compRef" class"wq-text-ellip…

新疆交投路桥桥梁公司:向“新”求“质”,积蓄发展新势能

向“新”求“质”谋发展&#xff0c;“发展新质生产力是推动高质量发展的内在要求和重要着力点&#xff0c;必须继续做好创新这篇大文章&#xff0c;推动新质生产力加快发展”。以新质生产力塑造国企新的核心竞争力成为实现高质量发展的关键内容&#xff0c;既具有重大理论意义…

在传销案件中数据库取证的分步指南

金字塔计划的特点是分层结构&#xff0c;主要由招募新成员的机制驱动。取证部门调查这些方案时&#xff0c;往往依靠数据库记录来分析这种结构。这些记录详细描述了上级和下级之间的关系&#xff0c;使调查人员能够描绘出组织的动态。在本文中&#xff0c;我们将探讨如何利用数…

如何用好通义灵码企业知识库问答能力?

通义灵码企业版&#xff1a;通义灵码企业标准版快速入门_智能编码助手_AI编程_智能编码助手通义灵码(Lingma)-阿里云帮助中心 通义灵码提供了基于企业知识库的问答检索增强的能力&#xff0c;在开发者使用通义灵码 IDE 插件时&#xff0c;可以结合企业知识库内上传的文档、文件…

23款奔驰E300立标升级23P智能辅助驾驶案例分享

《23 款奔驰 E300 立标升级 23P 智能辅助驾驶案例》 在汽车科技不断进步的今天&#xff0c;越来越多的车主开始追求更加智能、安全的驾驶体验。今天&#xff0c;我们就为大家带来一款 23 款奔驰 E300 立标升级 23P 智能辅助驾驶的精彩案例。 这辆 23 款奔驰 E300 立标原本就散…

业务调度 -- 线路单板中继模式

OTN网络中&#xff0c;线路板可以设置为中继模式&#xff0c;作为中继提高系统传输距离。当前设备支持“双向中继”与“单向中继”两种模式&#xff0c;不同的线路板支持其中的一种模式。单向中继与双向中继模式下支持“光中继”或“电中继”。 单向中继 VS. 双向中继 单向中…

DTOF(direct Time-of-Flight,直接飞行时间)

一、基本概念 1.1 定义 dToF&#xff0c;即直接飞行时间&#xff08;direct Time-of-Flight&#xff09;&#xff0c;是一种通过测量光脉冲发射出去并反射回来的时间差来直接计算距离的技术。 TOF应用场景非常多&#xff0c;电子消费品领域有人脸识别&#xff0c;照相机辅助对…

程序员数学 | 数学归纳法

目录 一、数学归纳法是什么二、使用编程来模拟数学归纳法的证明 人类做重复性的劳动没有效率&#xff0c;而计算机却能更快更准确的完成重复性劳动。所以以重复为特点的迭代法在编程中有着⼴泛的应⽤。实际项目中是否可以用不断更新变量值或者缩小搜索的区间范围的方法&#xf…

AniJS:无需编程的动画解决方案

前言 在网页设计中&#xff0c;动画效果能够显著提升用户体验&#xff0c;但传统的动画实现往往需要复杂的 JavaScript 代码。 AniJS 库的出现&#xff0c;为设计师和开发者带来了一种全新的动画实现方式&#xff0c;它通过简单的 HTML 属性就能创建出令人惊叹的动画效果。 介…

HTML5+JavaScript绘制闪烁的网格错觉

HTML5JavaScript绘制闪烁的网格错觉 闪烁的网格错觉&#xff08;scintillating grid illusion&#xff09;是一种视觉错觉&#xff0c;通过简单的黑白方格网格和少量的精心设计&#xff0c;能够使人眼前出现动态变化的效果。 闪烁的栅格错觉&#xff0c;是一种经典的视觉错觉…

柯桥小语种学习英语口语培训|被点名时,中文喊“到”,那英文喊什么?

"今日体育课&#xff0c;张老师准时点名。阳光下&#xff0c;同学们精神抖擞&#xff0c;一一应答到。课堂氛围活跃&#xff0c;准备充分&#xff0c;期待精彩训练。"被点名时&#xff0c;中文喊“到”&#xff0c;那英文喊什么&#xff1f; “到”用英语怎么说&…

在WPF中实现多语言切换的四种方式

在WPF中有多种方式可以实现多语言&#xff0c;这里提供几种常用的方式。 一、使用XML实现多语言切换 使用XML实现多语言的思路就是使用XML作为绑定的数据源。主要用到XmlDataProvider类. 使用XmlDataProvider.Source属性指定XML文件的路径或通过XmlDataProvider.Document指定…

5G NR 协议规范表(对应3GPP 协议编号)

文章目录 5G NR 协议规范表&#xff08;对应3GPP 协议编号&#xff09;5G 架构相关协议5G 新空口相关协议无线接入网相关协议终端相关协议 5G NR 协议规范表&#xff08;对应3GPP 协议编号&#xff09; 5G 架构相关协议 5G 新空口相关协议 无线接入网相关协议 终端相关协议