单元测试到底测什么,怎么测?我来告诉你

news2024/12/23 3:23:08

前言:
以国内互联网的开发节奏,在前端业务项目中全面覆盖单元测试有时显得不太可行,主要是因为以下这些绊脚石:

UI 交互复杂,路径难以覆盖全面
工期紧,开发对实践 TDD,BDD 所带来的长远效益没有信心
产品经理们时不时打着「敏捷开发」的旗号改需求,使得刚刚辛辛苦苦写完的测试脚本完全作废
在这样的处境下,一味强调单元测试的逻辑覆盖率是没有太大意义的,明确在哪里应用单测的能取得最大的边际效益是更有意义的事情。

以下笔者根据自己的一些在单测的实战经验,列出了三项关于「单元测试应该测什么」的观点并附以一些例子与大家交流:

单元测试并非测试的全部
拿来主义地对待单元测试

单测只是一种局部模块测试,是诸多测试方案中的一种,认识到这一点可以避免我们为了测试而测试,或者为了指标而测试。

同时也应该认识到单测本身的覆盖能力也是有限的,全部用例的 PASS 和 100% 的覆盖率都不能保证被测试模块的所有逻辑路径都有正确的行为。

是否对一个模块使用单元测试往往取决于这个模块的逻辑稳定性和业务类型

例如对于一个底层 npm 包项目,单元测试几乎是他唯一的代码质量保障手段,这时就应该尽可能通过单元测试验证它在各种应用场景下的行为是否符合预期,来最低成本地保证它每次发包和更新的质量。对这类项目,彻底应用 BDD 开发模式也会获得越来越高的开发效率收益。

而对于一个功能复杂的 UI 组件,除了单元测试,还有 E2E 测试,自动化回归测试,QA 手动测试(:blush:)来保障它的代码质量。此时使用单元测试的边际效益可能不是最高的,可以考虑通过别的手段来回归它的逻辑。也可以考虑在初版功能验证上线后通过快照测试(snapshot)来回归验证每一次迭代的逻辑。

边界环境的模拟
让模块穿梭时空

单测的一个很重要的意义是帮助我们在开发阶段模拟出 QA 手动测试(:blush:)甚至线上使用场景下都不易触达的边界场景,如:

模拟个别浏览器下的 JS 版本
模拟某个 URL 状态
模拟某种本地缓存状态
模拟不同时区下的情形
模拟时间过了一个小时(这几乎只有单元测试能够做到)
等等

使用这类模拟对模块进行单元测试的边际效益是极高的,往往比 QA 去作等价的模拟快得多。

比如下面这段脚本,通过 jest 的 timer mock 能力,实现了对 expire 函数的测试:

const expire = (callback) => setTimeout(callback, 60000); // 一分钟以后过期
 
test('到点就调用回调', () => {
  const callback = jest.fn();
  expire(callback);
 
  jest.advanceTimersByTime(59999);
  expect(callback).not.toBeCalled();
 
  jest.advanceTimersByTime(1);
  expect(callback).toBeCalledOnce();
})
复制代码

这段代码通过 jest.advanceTimersByTime 精确模拟了宏任务的运行过程,同步完成了原本需要一分钟才能验证一次的异步流程的测试。

又比如下面的测试脚本用来测试一个名为 catchFromURL 的工具函数,该函数可以从当前的 URL 中获取指定的参数作为返回值返回,同时从 URL 中抹去该参数。

这中需求通过 URL 携带 token 信息的业务场景(如单点登录)中是非常常见的。

test('通过URL获取指定的参数值并抹去之', () => {
  const CURRENT_ORIGIN = document.location.origin;
  const testHref = `${CURRENT_ORIGIN}/list/2/detail?a=123b&b=true#section2`;
  history.replaceState(null, '', testHref);
  expect(catchFromURL('a')).toBe('123b');
  expect(document.location.href).toBe(`${CURRENT_ORIGIN}/list/2/detail?b=true#section2`);
})
复制代码

这段测试代码通过 jsdom 来实现对需要测试的环境的模拟。环境的构造和模拟其实是单元测试中的一个难点,由于 jsdom 本身的一些缺陷(如没有实现 Navigator)使得在测试脚本运行的 node 环境中模拟正确的浏览器环境往往需要用到很多的 Hack 技术,这一点在未来的夜点心中会着重中展开讨论。

点到为止

less is more

测试代码无需关心被测试模块的具体实现,点到为止地测试几种必要的流程场景即可。这一方面可以减少写测试逻辑的时间,一方面可以使得业务逻辑具有更大的实现自由度。

对一个业务模块,测试脚本只需要关心该模块所关联的所有外部性即可:

对于函数模块而言,控制它引用的模块、它的输入和它的副作用,验证它的输出和对副作用的影响
对于组件模块而言,控制它依赖的服务、它依赖的子组件、它的 props和它的事件,验证它的渲染结果和 props 中回调的调用情况,而不应该关心它的 state。
下面的脚本通过 enzyme 组件测试工具测试了一个名为 ValidatableInput 的 React 组件。这个组件在失焦(blur)时会触发 onValidate 回调,并传入 inputValue 参数。

test('失焦时触发 onValidate', () => {
    const onValidate = jest.mock();
    const inputValue = '输入的内容';
    const wrapper = shallow(
      <ValidatableInput
        placeholder={''}
        value={inputValue}
        alert={''}
        onChange={onChange}
        onValidate={onValidate}
      />
    );
 
    wrapper.find('.validatable-input').first().simulate('blur');
    expect(onValidate).toBeCalledWith(inputValue);
  });
复制代码

在上述测试用例中我们的测试逻辑完全基于行为开展,只关心失焦的「动作」和执行回调的「反馈」,没有去断言任何关于组件状态的内容。

这样组件可以根据它的需要自由地实现它的内部逻辑,例如添加通过外部的 Provider 来提供 value 和 onChange 成为受控组件的能力。这些实现的变化都不会影响当前这条测试用例的有效性。

上面就是一些对应该用单元测试测什么的看法,把单测用在它最擅长的地方,才能在紧凑的开发节奏中取得事半功倍的效果。

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

 视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方进群即可自行领取。    

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

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

相关文章

11.与JavaScript深入交流-[js一篇通]

文章目录 1.变量的使用1.1基本用法1.2理解 动态类型 2.基本数据类型2.1number 数字类型2.1.1数字进制表示2.1.2特殊的数字值 2.2string 字符串类型2.2.1基本规则2.2.2转义字符2.2.3求长度2.2.4字符串拼接 2.3boolean 布尔类型2.4undefined 未定义数据类型2.5null 空值类型 3.运…

半导体制造中的液体污染控制-液体粒子计数器应用

半导体制造是一个高度复杂的过程&#xff0c;包括许多步骤和阶段&#xff0c;每个步骤和阶段都有可能受到污染。在这种情况下&#xff0c;污染可能导致产量昂贵的损失和时间浪费。为了应对这些挑战&#xff0c;实时监控系统提供了一个强大的解决方案&#xff0c;可以立即检测并…

注意!注意!注意!新规|Temu平台强制欧代英代,警惕产品被拒!

注意&#xff01;注意&#xff01;注意&#xff01;新规&#xff5c;Temu平台强制欧代英代&#xff0c;警惕产品被拒&#xff01; 欧代&#xff0c;英代信息怎么办理呢 TEMU平台上有售卖产品必需要求产品打上英代,欧代信息! 10月15日&#xff0c;Temu正式实施欧代&英代新规…

反射率检测仪如何检测后视镜

后视镜反射率检测是评估后视镜质量的重要步骤&#xff0c;可以反映后视镜的反射效果是否满足设计要求。一般来说&#xff0c;后视镜的反射率越高&#xff0c;驾驶员观察车后的道路状况就越清晰&#xff0c;从而能够更好地判断与后方车辆的距离和速度差。 后视镜反射率检测的原理…

Unity 多图片(带透明通道)合成

取个巧&#xff0c;利用Camera和Render Texture 多个2d图片组合成型 每个Square都单独设置一个层级 相机设置 RenderTexture设置&#xff0c;然后将RenderTexture放在一个RawImage上 以下是生成图片的代码 using UnityEngine.UI; using System.Collections; using System.…

Python爬虫程序中的504错误:原因、常见场景和解决方法

概述 在编写Python爬虫程序时&#xff0c;我们经常会遇到各种错误和异常。其中&#xff0c;504错误是一种常见的网络错误&#xff0c;它表示网关超时。是指客户端与服务器之间的网关通信过程中&#xff0c;服务器在规定的时间内没有返回响应&#xff0c;导致请求超时。此类错误…

关于FreeTypeFont‘ object has no attribute ‘getsize‘问题的解决方案

引言 这个问题是在训练yolov5_obb项目遇到的&#xff0c;大概率又是环境问题。如下图&#xff1a; 解决方法 出现这个问题是Pillow版本太高了&#xff0c;下载低版本的&#xff1a; pip install Pillow9.5 OK&#xff01;

解决proteus仿真stm32,IIC通讯,IIC DEBUG无法显示从机应答信号的问题(问题情况为在8位数据后应答位显示?)

1、错误现象 错误现象如下&#xff0c;在IIC数据传输8位数据后&#xff0c;IIC DEBUG的应答位无法显示应答位 2、错误原因 我们打开信号传输的示波器&#xff0c;直接去查看IIC从机校验位的数据波形&#xff0c;可以看到从机示波器显示的的波形为半高ACK&#xff0c;那错误原…

第19期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

【Proteus仿真】【Arduino单片机】简易电子琴

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用无源蜂鸣器、按键等。 主要功能&#xff1a; 系统运行后&#xff0c;按下K1-K7键发出不同音调。 二、软件设计 /* 作者&#xff1a;嗨小易&a…

通讯网关软件031——利用CommGate X2HTTP实现HTTP访问ODBC数据源

本文介绍利用CommGate X2HTTP实现HTTP访问ODBC数据源。CommGate X2HTTP是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;实现上位机通过HTTP来获取ODBC数据源的数据。 【解决方案】设置网关机…

Jmeter(二十一):jmeter导入和导出接口的处理(超详细)

JMeter测试导入接口 利用Jmeter测试上传文件&#xff0c;首先可根据接口文档或者fiddler抓包分析文件上传的接口&#xff1b;如下图&#xff1a; 以下是我通过fiddler所截取的文件上传的接口 1、填写导入接口的信息 查看文件上传栏下的填写信息&#xff1a; 文件名称&#x…

DM8 Dokcer镜像更新后远程无法jdbc连接问题

背景&#xff1a;原来官网下的dm8docker镜像有效期只有两个星期&#xff0c;问他们商务申请了新的dm8镜像&#xff0c;准备简单升级一下镜像再引入原来的database 先说结论&#xff1a;jdbc驱动要更新 官网dm8驱动链接地址 原来的tag镜像 dm8_single:v8.1.2.128_ent_x86_64…

集简云+管家婆如何无需API开发轻松连接OA、电商、营销、CRM、用户运营、推广、客服等近千款系统

网上管家婆专注于为中小企业提供科学经营管理的一站式解决方案。自2009年创办云端SaaS产品&#xff0c;已服务14年&#xff0c;旨在帮助电商、传统批发零售和实体门店等业务群体提高订单处理效率和商业经营效益。 官网&#xff1a;https://www.wsgjp.com.cn/ 集简云无代码集成…

【ICCV‘23】One-shot Implicit Animatable Avatars with Model-based Priors

文章目录 前置知识 前置知识 1&#xff09;SMPL模型 \quad SMPL这类方法只建模穿很少衣服的人体&#xff08;裸体模型&#xff09;&#xff0c;它只能刻画裸体角色的动画&#xff0c;并不能刻画穿衣服的人体的动画 2&#xff09;data-efficient \quad 这个词推荐用&#xff…

解决SQLServer占用80端口问题

在安装好了SQLServer之后&#xff0c;发现系统默认80端口被占用&#xff0c;导致很多默认用80端口的软件运行不起来。 解决办法 1、运行(快捷键:WINR) services.msc 2、找到SQL Server Reporting Services (MSSQLSERVER) 服务 3、先停止服务&#xff0c;然后再禁用服务

使用MobaXterm向linux窗口化传输文件

使用MobaXterm向linux窗口化传输文件 之前上大学的时候&#xff0c;经常是XSheel配合Xftp使用&#xff0c;Xftp可以窗口化的往linux服务器传输文件&#xff0c;但是有一个问题&#xff0c;就是Xftp是收费的。 后来工作之后师兄给推荐了一个免费的&#xff0c;又好用的类似于Xf…

视频讲解|考虑源荷两侧不确定性的含风电电力系统低碳调度

目录 1 主要内容 2 讲解视频 1 主要内容 本次程序讲解对应程序链接考虑源荷两侧不确定性的含风电电力系统低碳调度&#xff0c;主要实现了基于模糊机会约束的源荷两侧不确定性对含风电电力系统低碳调度的影响&#xff0c;将源荷不确定性采用清晰等价类进行处理。部分讲解重点…

【23真题】邮电之首!扩招15倍!专业课难度骤降!

今天分享的是23年北京邮电大学804的信号与系统试题及解析。 本套试卷难度分析&#xff1a;北邮804在22年只招生6人&#xff0c;23年拟招生87人&#xff0c;扩招近15倍&#xff01;22年北京邮电大学804考研真题&#xff0c;我也发布过&#xff0c;若有需要&#xff0c;戳这里自…

Vant Weapp 的van-cell 与 van-cell-group的边框

场景&#xff1a; 用van-cell循环出来的单元格&#xff0c;最上面有一条边框线&#xff0c;且找不到该元素&#xff1b; <van-cell-group border"{{false}}"> 直接在这写属性 <van-cell> </van-cell> </van-cell-group> 效果图&#xff1…