测试之路 - 精准而优雅
引子
这几年业内一直在做精准测试,大都使用工具 diff 代码改动、分析代码覆盖率这些平台集成的能力。
业务测试中,我们在技术设计和代码实现的基础上也做了一些精减和精准的测试实践,通过深入测试有针对的设计 case,发现隐藏问题,保证质量。
接下来我将通过以下几个场景,介绍一下在 toB 业务中应用精减和精准的思路和实践。
场景一:上传表格的验证
需求点
业务同学需要在运营后台使用表格模板上传多组数据,上传时需要校验表头和字段的格式。
作为 QA,这不就来活了,上传校验 case 贴上来:
问题点
case 中校验内容很多,每个字段的缺失、错误、格式正确性都需要验证。
怎么能更好更快的测试呢?
精准测试
找到对应的上传功能代码:
os: 原来神神秘秘在那敲代码的家伙们,也和我用一样的 for i 和 String 工具类。
通过走查代码发现问题:用 startWith 是几个意思?需求是全匹配啊!
提个 BUG,问题修复(startWith 换成 equals):
发现本次纯数字是用同样的正则和 .length() > 判断,实际测一个上传数字校验即可。
这个正则(^-?\d+$)判断纯数字有问题,大家看出来了吗?
精减结果
1. 正常数据的表格 ,上传成功。 2. 非数字格式和长度大于30的表格,分别上传失败。 3. 剩下的case通过审阅代码的方式验证。 4. 测试通过。结果:
- 审阅代码发现了【startWith】、【正则(^-?\d+$)】两个问题。
- 减少了 case 中 10 条上传异常表格的数据准备和操作,节省了时间。
小结
首先找到代码位置,练习审阅代码,可以通过接口名搜索/diff 代码/开发提供找到代码。
同类重复的测试场景,结合代码对 case 场景归类,可以适当选取重复的内容通过审阅代码进行测试。
注意:当你通过审阅代码测试时,需要特别关注如【正则】、【同类型代码(复制)】和 【get 参数】和【需求文案】,这也是审阅而不实际验证的弊端。
沉淀总结 Code Review 经验,关注【判断条件】、【取值】、【公式】等经常出错的逻辑点,挖掘代码中隐藏的 BUG。
场景二:获取可用规则
需求点
【获取可用规则】是匹配规则的第一部分,要根据处置优先级和启用状态命中匹配到可用规则,如下图所示:
先不展开直接本部分上 case:
问题点
匹配规则是很复杂的场景,规则本身、状态(开关)和优先级(包含同优先级)的场景很多。
完整的规则如何测试?【获取可用规则】部分就上面的两条 case ,够不够全面?
精准测试
首先了解代码获取优先级的逻辑,实际就是一个排序 SQL(优先级字段和自增 ID 字段倒序):
拿到 SQL 返回的集合,取第一条(get0):
通过上面的了解,我们知道状态和优先级是通过 SQL 倒序取第一条实现的,按上述 case 可以覆盖【获取可用规则】的场景:
a. 前置在库里手动插入三个规则;
b. 构造一条可以命中规则的数据;
c. 验证排序规则的结果为对应期望结果。
d. 测试完成。保险一点,写个 SQL 再查一遍:
SQL 结果第一个(即表中 id 为 44 )规则命中,同第 3 步 case 执行的结果一致。
小结
对自己的 case 或者测试的系统没有把握,可以通过结合代码进行测试以确保功能正确性,就不用担心这部分测试不充分啦。
在测试执行过程中,我是通过数据库 insert 的数据,这里有一个前提: case 中已经保证了页面创建的规则在库里保存正确。
当然排序和优先级还有其他的实现方式,比如【加载到内存处理】或者【给优先级的选项增加不同的权重系数】等,期望大家总结沉淀,以后遇到从容应对。
^ _ ^ :仔细的测试同学可能已经发现,这里把【获取规则】和【规则匹配验证】拆开验证,这是拆解理顺复杂逻辑的好方式。
场景三:规则组匹配验证
需求点
【规则组匹配】为匹配规则的第二部分,每一行是一个规则组,规则组里可以选择配置应用 4 条‘子基本规则’(条件为且),‘子基本规则’不命中则该规则组不命中。
再看一下技术设计的部分流程图:
问题点
规则匹配要测试到不同规则组命中的场景,也要测试 A1,A2,A3,A4 子规则本身的正确性。
如果要对规则组进行测试,应该设计 A1+A3,A3+A4,A1+A2+A3,A2+A3+A4,A1+A2+A3+A4…笛卡尔积全量的规则组 case 进行验证
这样穷举出来的 case 最全,但需要的测试时间也更多,有没有更好的解决办法?
精减结果
本场景中即有规则组又有子规则,先测试规则组的命中,然后对‘子规则’单独测试(场景四)
测试规则组时,根据对设计方案的理解,既然是依次排除,那无需穷举 case, 编写 case 时排除不需要测试的场景:
通过审阅代码,确认代码实现是同技术设计一致的,上面的 case 可以覆盖逻辑:
执行测试时先构造命中规则数据,然后构造排除规则的数据(图中标记的数字为库表的记录 id),查询日志进行验证:
结合页面的验证结果,真实排除了规则不匹配的规则组,测试完成。
小结
当遇到功能复杂的业务场景,拆分独立的功能单独测试,往往会让测试思路更清晰,最后再做集成测试,保证功能完整性。
在听完技术评审后,结合技术设计有针对的编写 case,即能避免冗余 case,又能避免覆盖率不够。
在审阅代码后,通过 log 关键字查询日志和验证,确保页面结果和系统逻辑结果一致,防止黑盒测试不充分。
场景四:同类的规则条件
需求点:
【同类的规则条件】为匹配规则的第三部分,单个规则组内所有‘子基本规则’都命中这个规则组才命中,需要测试各‘子基本规则’的匹配逻辑。
问题:
case 初版设计(从最全匹配的 case,逐次减少一个参数,这样保证每个参数都能测试到):
本场景问题同上一场景类似,case 设计应为笛卡尔积的子规则,但执行的场景多,有没有更精减的方式呢?
精减思路:
了解代码中获取匹配数据的逻辑,实际就是一个多 where 条件的 sql:
所以需要保证的是:最细颗粒度条件参数可以传入并查询正确,部分条件参数可查询正确,case 可以精减为:
测试时,通过手写 SQL 查询对应数据:
-- 手动打码SQL SELECT * from dbzz_****.****_volume_count where **_id=99530 and ***_id = 999435 and **_type = 2 and ****_id in (9999623,9999624) and period =14 ORDER BY id desc ;通过对比页面结果和 SQL 查询的结果,两个维度验证数据准确性。
在此分享一个本场景发现的缺陷:标记且注释置灰的位置为问题代码
缺陷: 获取数据时以最细规则(最长匹配)取倒序最近一条(order by id desc limit 1)时没有问题,但以粗粒度的宽泛条件也取倒序最近一条,则数据不全(因为表中每一条记录都是以最细粒度存储)。
发现原因: 之前遇到一个类似的 SQL 逻辑没有使用 sum,所以对此格外关注。
修复: 条件宽泛情况下的数据应是同条件下多条记录的合集,所以应去掉条数限制并改成 sum。
小结
业务中复杂的参数匹配,转化成代码时实际上是个多条件 SQL,思路是只要保证最细条件和部分条件都能传入并查询正确即可。
在审阅代码时,关注 mapper 信息并结合对需求的理解,可以单独写 SQL 验证取值逻辑。
积累业务中同类型中的 BUG 经验,如上面 SUM 的缺陷,在后续的测试中保持关注,提高警惕。
总结
通过分析技术设计和代码实现,可以适当分类精减 case,通过 Code Review 减少复杂的错误验证,转为审阅代码进行测试。
通过审阅代码,从代码层面确认逻辑是否正确,比如关注字段取值、匹配入参、查询条件、判断条件、公式计算等,发现隐藏的缺陷。
以上的内容举例,在测试实践中减少了重复的验证投入,有针对的设计也更有效的发现问题,最后也会让我们的测试结果更有信心。
关于作者
聂飞 测试开发工程师
转转研发中心及业界小伙伴们的技术学习交流平台,定期分享一线的实战经验及业界前沿的技术话题。
关注公众号「转转技术」(综合性)、「大转转FE」(专注于FE)、「转转QA」(专注于QA),更多干货实践,欢迎交流分享~
相关文章:
测试之路 - 精准而优雅
引子 这几年业内一直在做精准测试,大都使用工具 diff 代码改动、分析代码覆盖率这些平台集成的能力。 业务测试中,我们在技术设计和代码实现的基础上也做了一些精减和精准的测试实践,通过深入测试有针对的设计 case,发现隐藏问题…...
Java基础篇常见面试问题总结
文章目录 1. 你是怎样理解 OOP面向对象?2. 重载与重写区别3. 接口与抽象类的区别4. 深拷贝与浅拷贝的理解5. 什么是自动拆装箱? int和 Integer有什么区别6. 和 equals()区别7. String类 能被继承吗为什么用 final修饰8. final、finally、finalize区别 1. 你是怎样理…...
Spring、SpringMVC
一、Spring框架中的单例Bean是线程安全的吗? 【默认单例的情况下】Spring Bean并没有可变的状态(如Service类和DAO类),即只能查不能改,所以没有并发问题,所以某种程度上来说Spring的单例Bean是线程安全的。…...
【传知代码】VRT: 关于视频修复的模型(论文复现)
前言:随着数字媒体技术的普及,制作和传播视频内容变得日益普遍。但是,视频中由于多种因素,例如传输、存储和录制设备等,经常出现质量上的问题,如图像模糊、噪声干扰和低清晰度等。这类问题对用户的体验和观…...
不用投稿邮箱,怎样向各大新闻媒体投稿?
身为单位的信息宣传员,我深知肩上责任重大。每个月,完成单位在媒体上投稿发表文章的考核任务,就如同一场无声的赛跑,既要保证速度,更要注重质量。起初,我遵循“前辈们”的老路,一头扎进了邮箱投稿的海洋。但很快,现实给了我一记重拳——邮箱投稿的竞争犹如千军万马过独木桥,稿件…...
NAT技术总结与双向NAT配置案例
NAT的转换方式: 1.静态转换:固定的一对一IP地址映射。 interface GigabitEthernet0/0/1 ip address 122.1.2.24 nat static global 122.1.2.1 inside 192.168.1.1 #在路由器出接口 公网地址 私网地址。 2.动态转换:Basic NAT nat address-gr…...
mysql的explain
explain可以用于select,delete,insert,update的statement。 当explain用于statement时,mysql将会给出其优化器(optimizer)的执行计划。 通过explain字段生成执行计划表。下面来解析这个执行计划表的每一列…...
SpringBoot+Vue实现图片滑块和文字点击验证码
一、背景 1.1 概述 传统字符型验证码展示-填写字符-比对答案的流程,目前已可被机器暴力破解,应用程序容易被自动化脚本和机器人攻击。 摒弃传统字符型验证码,采用行为验证码采用嵌入式集成方式,接入方便,安全&#…...
每日复盘-20240515
仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 国联证券 (1)|[9:25]|[133765万]|31.12 一…...
【Android】Apk图标的提取、相同目录下相同包名提取的不同图标apk但是提取结果相同的bug解决
一般安卓提取apk图标我们有两种常用方法: 1、如果已经获取到 ApplicationInfo 对象(假设名为 appInfo),那么我们获取方法为: appInfo.loadIcon(packageManager)// 返回一个 Drawable 对象2、 如果还没获取到 Applica…...
高校普法|基于SSM+vue的高校普法系统的设计与实现(源码+数据库+文档)
高校普法系统 目录 基于SSM+vue的高校普法系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3律师功能模块 4学生功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获…...
pytest教程-47-钩子函数-pytest_sessionfinish
领取资料,咨询答疑,请➕wei: June__Go 上一小节我们学习了pytest_sessionstart钩子函数的使用方法,本小节我们讲解一下pytest_sessionfinish钩子函数的使用方法。 pytest_sessionfinish 钩子函数在 Pytest 测试会话结束时调用,…...
如何使用Python下载哔哩哔哩(Bilibili)视频字幕
在本文中,我将向大家展示如何使用Python下载哔哩哔哩(Bilibili)视频的字幕。通过这个方法,你可以轻松地获取你喜欢的视频的字幕文件,方便学习和交流。 准备工作 在开始之前,我们需要安装一些必要的库&…...
IP代理网络协议介绍
在IP代理页面上,存在HTTP/HTTPS/Socks5三种协议。它们都是客户端与服务器之间交互的协议。 HTTP HTTP又称之为超文本传输协议,在因特网使用范围广泛。它是一种请求/响应模型,客户端向服务器发送请求,服务器解析请求后对客户端作出…...
渗透相关面试+流量分析
文章目录 简单自我介绍上一个工作的主要内容Hvv的分组和流程你在hvv/攻防演练中取得了哪些成绩? 二、渗透相关面试题基础端口号以及入侵方式OSI七层协议响应状态码都有哪些?**WAF和IPS的区别**盲注是什么?java内存马类型**内存马有几种类型**…...
Shell之高效文本处理命令
目录 一、排序命令—sort 基本语法 常用选项 二、去重命令—uniq 基本语法 常用选项 三、替换命令—tr 基本语法: 常用选项 四、裁剪命令—cut 基本语法: 常用选项 字符串分片 五、拆分命令—split 基本语法: 六、 文件…...
u3d的ab文件注意事项
//----------------LoadAllAB.cs--------------------- using System.Collections;using UnityEngine;namespace System.IO{public class LoadAllAB : MonoBehaviour{ //读取本地string path "Assets/Actors/lznh/ab/animation/t_bl/";// Use this for initiali…...
Go微服务开源框架kratos的依赖注入关系总结
该文章为学习开源微服务框架kratos的学习笔记!官方文档见:简介 | Kratos Kratos 一套轻量级 Go 微服务框架,包含大量微服务相关框架及工具。 一、Kratos 项目结构简介 通过 Kratos 工具生成的 Go工程化项目模板如下: applicati…...
Linux 第三十二章
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C,linux 🔥座右铭:“不要等到什么都没有了…...
手机号码的正则表达式
手机号码的正则表达式会根据不同的国家/地区有所不同,因为每个国家/地区都有自己特定的手机号码格式。但是,我可以为你提供一个通用的正则表达式模板,并给出一些具体国家/地区的例子。 通用模板 一个基本的手机号码正则表达式模板可能如下所…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...



















