两个真实软件 Bug 分析:从现象到排查思路
这篇文章记录两个我在实际使用和测试过程中遇到的真实 Bug。
我想把它们整理出来,不只是为了“记住一个问题”,而是训练自己从下面几个角度看 Bug:
- 现象是什么
- 如何稳定复现
- 影响范围在哪里
- 更可能是哪一层出了问题
- 如果我是测试,下一步应该怎么追
这两个 Bug 分别是:
- 腾讯元宝网页端,复制上传 1 张图片后,聊天框里出现十几张相同图片
- 测试实习期间,手机客户端切换账号登录时,App 会先退出回到桌面,再自动重新打开
这两个问题一个偏 Web 端交互 / 前端状态管理,一个偏移动端登录态切换 / App 生命周期管理,刚好很适合放在一起分析。
一、Bug 分析方法:不要只停留在“看到了异常”
很多人记录 Bug 时,只会写:
- 现象:出问题了
- 结果:不符合预期
这样当然可以提单,但如果你想提升自己的分析能力,还不够。
更有价值的方式是把 Bug 拆成 5 个问题:
1. 触发路径是什么
也就是:
- 用户做了什么操作
- 哪一步之后出现异常
2. 异常表现是什么
也就是:
- 页面错了
- 数据重复了
- 状态丢了
- 应用闪退了
3. 预期行为应该是什么
这一点非常重要,因为“Bug”本质上是实际结果和预期结果不一致。
4. 更可能是哪个模块出的问题
比如:
- 前端事件重复触发
- 接口重复请求
- 后端去重失效
- 客户端生命周期处理错误
5. 如果继续排查,要看什么证据
例如:
- 前端控制台日志
- Network 请求
- App 日志
- 埋点
- 崩溃日志
- 服务端请求链路
下面我就按这个思路来拆这两个真实 Bug。
二、Bug 1:腾讯元宝网页端复制上传 1 张图片,却出现十几张相同图片
1. Bug 现象
我在腾讯元宝网页端使用“复制图片并粘贴上传”的方式发送图片。
按预期,我只复制了 1 张图片,聊天框里应该只出现 1 张待发送图片,或者 1 条图片消息。
但实际现象是:
- 我只进行了一次复制 / 粘贴操作
- 聊天框里却出现了十几张相同的图片
也就是说,系统把一次用户操作放大成了多次重复结果。
2. 预期行为
预期应该是:
- 一次粘贴操作,对应一次图片插入
- 聊天框中最多出现 1 张对应图片
- 即使内部存在异步处理,也不应该出现明显重复
3. 可能的复现路径
可以先把复现步骤写成标准测试步骤:
- 打开腾讯元宝网页端聊天页面
- 复制一张图片
- 聚焦到聊天输入框
- 执行粘贴操作,例如
Ctrl + V - 观察聊天框中的待发送图片或消息内容
预期结果:
- 仅出现 1 张图片
实际结果:
- 出现十几张相同图片
4. 这个 Bug 的第一直觉:大概率不是“图片本身有问题”
因为问题不是:
- 图片格式错
- 图片上传失败
- 图片显示损坏
而是:
- 同一张图片被重复插入很多次
这说明问题更像是:
- 同一个事件被处理了多次
- 同一个数据被渲染了多次
- 同一个上传任务被创建了多次
所以从经验上看,这类问题的优先怀疑方向通常是:
- 前端事件监听重复绑定
- 粘贴事件和上传逻辑没有做幂等保护
- 剪贴板中多个数据项被重复解析
- 前端状态更新重复触发渲染
5. 更细一点看,可能是哪几类原因
原因方向 1:paste 事件被重复监听
网页端常见做法是监听输入框的 paste 事件,然后从剪贴板里读取图片数据。
如果代码里发生了下面这种问题:
- 页面重渲染后重复绑定事件
- 每次进入会话都追加一次监听
- 组件卸载时没清理监听器
那一次粘贴就可能触发多次处理逻辑。
这种情况下的典型现象是:
- 一次用户操作
- 多次进入同一段处理函数
- 最终生成多条重复数据
原因方向 2:剪贴板数据被循环处理,但没有正确过滤
浏览器剪贴板里不一定只有“单一图片对象”。
有时一次复制动作里可能包含:
- 图片二进制数据
- HTML 片段
- 文本描述
- 多种 MIME 类型
如果前端在遍历 clipboardData.items 时:
- 没有筛选真正的图片项
- 或者对同一数据重复转换
就可能把“同一张图片”当成多份资源处理。
原因方向 3:前端上传逻辑重复创建任务
也有一种可能不是展示层的问题,而是上传队列的问题。
比如:
- 粘贴后先本地预览一次
- 再自动触发上传
- 上传完成后又补插入一次
- 某个重试逻辑把同一个任务重复加入队列
这时最终表现也可能是:
- 聊天框中出现多张相同图片
- 或者消息区里出现多条相同图片消息
原因方向 4:状态管理重复追加
假设前端使用状态管理维护待发送图片列表:
- 正常应是
list = [imageA]
但如果代码在多个地方都执行了 append(imageA),就会出现:
list = [imageA, imageA, imageA, ...]
这类问题常见于:
- 监听器多次触发
- 异步回调重复执行
- React / Vue 状态更新逻辑写得不严谨
6. 如果我是测试,下一步怎么排
第一步:先判断是“展示重复”还是“请求重复”
这个很关键。
因为:
- 如果只是前端展示重复,Network 里可能只发 1 次上传请求
- 如果请求也重复,说明上传任务本身被创建了多次
所以第一步最值得看的就是浏览器开发者工具里的:
- Network
- Console
第二步:看一次粘贴是否触发多次请求
重点观察:
- 是否一次
Ctrl + V后产生多条上传请求 - 请求参数是否相同
- 时间间隔是否极短
如果是多条相同请求,问题更偏:
- 事件重复触发
- 上传逻辑缺少幂等
第三步:如果请求只有一次,重点怀疑前端渲染或状态
这时应该关注:
- 前端是否对同一结果多次
setState - 是否本地预览和服务端回填都在追加
- 是否列表 key 不正确导致渲染异常
第四步:补做对比实验
为了进一步缩小范围,我会继续做这些对比:
- 复制上传图片 vs 手动选择图片上传
- 粘贴本地截图 vs 粘贴网页图片
- 不同浏览器下是否都能复现
- 无痕模式 / 清缓存后是否仍复现
这些对比可以帮助判断问题更偏:
- 浏览器兼容性
- 剪贴板数据格式
- 页面状态污染
7. 这个 Bug 给我的测试启发
这个问题很典型地说明了一件事:
输入类功能,不只是测“能不能成功”,还要测“是否只执行一次”。
很多测试容易漏掉“重复触发”这类问题,尤其在下面这些场景:
- 粘贴
- 双击
- 连点
- 拖拽上传
- 回车发送
- 自动重试
这类场景都很容易出现:
- 重复提交
- 重复渲染
- 重复请求
所以以后碰到上传、发送、提交、支付、下单这类动作时,我会特别注意:
- 幂等性
- 事件防抖 / 节流
- 前端重复绑定
- 队列去重
三、Bug 2:手机客户端切换账号登录时,先退出回到桌面,再自动重新打开
1. Bug 现象
在测试实习期间,我遇到过这样一个手机客户端问题:
- 用户切换账号登录
- App 会先退出
- 返回到手机桌面
- 随后又自动重新打开 App
从用户视角看,这个体验非常怪:
- 像闪退
- 但又不是彻底闪退
- 因为它会自动重新拉起
2. 预期行为
正常的账号切换登录流程应该是:
- 当前账号退出
- 清理旧账号登录态
- 切换到登录页或重新进入首页
- 整个过程尽量平滑,不应突然回桌面
也就是说,哪怕内部确实做了很多状态重置,用户也不应该感知到:
- App 被“杀掉又重启”
3. 这类问题为什么很值得分析
因为它不是一个简单的页面展示问题,而是明显涉及:
- 登录态切换
- 客户端生命周期
- 页面路由重建
- 进程 / Activity / App 重启机制
这类 Bug 往往比普通表单错误更有分析价值,因为它牵涉系统层和业务层交叉。
4. 第一判断:它不一定真的是“闪退”
用户看到“回到桌面再重新打开”,第一反应往往是:
- App 崩了
但从测试分析角度,不能马上下这个结论。
因为还存在另一种可能:
- 业务代码主动结束当前页面栈或进程
- 然后通过某种方式重新拉起 App
所以这个问题至少有两种大方向:
方向 1:真的崩溃了,然后系统或框架做了自动重启
例如:
- 账号切换后某个页面拿到空对象
- 引发崩溃
- 框架内置崩溃恢复机制把 App 再次拉起
方向 2:程序主动做了“重启应用”式处理
例如:
- 切换账号后为了清空全局状态
- 直接
finishAffinity()或类似操作结束当前页面 - 再通过启动页重新拉起 App
这种实现方式如果没处理好,就会让用户明显看到:
- 先退桌面
- 再重新打开
5. 更可能的原因方向
原因方向 1:账号切换后需要重建全局状态,但实现方式过于粗暴
切换账号时,很多信息都要重置:
- token
- 用户信息
- 首页缓存
- WebView 登录态
- IM / 推送绑定关系
- 本地数据库中的用户相关数据
如果研发为了省事,采用“重启 App”方式强制清理状态,这在实现上确实简单,但用户体验很差。
这类问题的典型表现就是:
- 切换账号时应用明显退出
- 然后重新拉起冷启动流程
原因方向 2:路由栈清理异常
另一个常见原因是页面栈处理不对。
例如:
- 退出登录时清掉所有 Activity
- 但登录成功后又自动跳启动页
- 中间没有平滑过渡
这种情况下,从外部看也很像“先退出回桌面,再重新打开”。
原因方向 3:登录成功后触发了进程级重建
有些 App 在账号切换后会重建:
- 多语言
- 主题
- 用户态配置
- 首页容器
如果重建发生在进程级或应用级,就可能造成明显闪断。
原因方向 4:某个页面在切换账号时访问了失效数据,导致异常退出
比如:
- 当前页面还持有旧用户数据
- 退出后 token 已清空
- 但页面异步回调还在执行
- 最后访问空对象或非法状态
这时就可能出现:
- 先异常退出
- 再因启动保护逻辑自动拉起
6. 如果我是测试,该怎么进一步定位
第一步:先判断是“主动重启”还是“崩溃重启”
这是最重要的一步。
因为这决定了排查方向完全不同。
如果是主动重启,日志里通常会看到:
- 明确的退出登录逻辑
- 清理页面栈逻辑
- 重新拉起启动页逻辑
如果是崩溃重启,日志里更可能出现:
- 崩溃栈
- uncaught exception
- ANR / fatal error
第二步:看客户端日志和生命周期日志
重点关注:
- 退出登录按钮点击后发生了哪些调用
Activity/App生命周期如何变化- 是否调用了清栈 / 重启相关 API
例如 Android 场景下会特别关注:
onPauseonStoponDestroy- 新启动页的
onCreate
如果这些日志连起来看,就能判断:
- 是不是代码主动做了“销毁旧栈再拉起新栈”
第三步:看切换账号过程中是否有异步任务没收干净
切换账号时很容易出问题的地方包括:
- 网络请求还没结束
- WebSocket / 长连接还没断干净
- 推送绑定关系还没切换完
- 本地缓存还没清完
- 首页异步刷新还在执行
这些任务如果和新账号切换过程并发交错,就很容易造成状态异常。
第四步:做场景对比
为了缩小范围,我会继续补这些测试:
- 冷启动后立即切换账号是否复现
- 已登录使用一段时间后切换账号是否复现
- 弱网下切换账号是否更容易复现
- 不同机型、不同系统版本是否都复现
- 从 A 账号切 B 账号复现,从 B 切 A 是否也复现
这样可以判断问题更偏:
- 机型兼容
- 时序问题
- 异步任务清理不彻底
7. 这个 Bug 暴露的本质问题
这个问题很有代表性,因为它暴露出“登录态切换”不是一个简单页面跳转问题。
它背后通常关联的是整套用户态系统:
- 本地缓存
- 登录 token
- 页面栈
- 长连接
- 推送
- 用户数据隔离
所以测试账号切换时,不能只测:
- 能不能登录成功
还要测:
- 登录后页面是否正确
- 退出后状态是否清空
- 切换账号后是否串数据
- 是否出现闪退、重启、白屏、卡死
8. 这个 Bug 给我的测试启发
这个问题让我特别意识到:
登录、退出、切换账号这类场景,本质上是“高风险状态切换场景”。
高风险的原因在于:
- 涉及全局状态重置
- 涉及本地和服务端双向状态同步
- 涉及页面栈和生命周期变化
- 涉及异步任务收尾
所以以后测这类功能,我会特别关注:
- 是否有页面闪断
- 是否回到桌面
- 是否白屏
- 是否自动重启
- 是否串账号数据
- 是否存在旧账号残留信息
四、把这两个 Bug 放在一起看,我学到了什么
虽然这两个 Bug 一个发生在网页端,一个发生在移动端,但它们有一个共同点:
都不是“功能完全不能用”,而是“状态管理和事件处理出了问题”。
第一个 Bug 的核心更像:
- 一次输入事件被多次消费
- 前端状态或上传任务没有做好去重
第二个 Bug 的核心更像:
- 用户状态切换时,全局生命周期没有处理平滑
- 页面栈、登录态、异步任务之间存在冲突
这两类问题都说明:
测试不能只停留在“点一下能不能成功”。
更要关注:
- 事件是否重复触发
- 状态是否重复写入
- 切换过程是否平滑
- 全局状态是否真正收敛
五、如果把这两个 Bug 讲给面试官,怎么说更好
如果面试官问你:
- 你遇到过什么印象深刻的 Bug
- 你怎么分析一个 Bug
- 你怎么从 Bug 里提升自己
你完全可以把这两个例子讲出来。
推荐表达方式不是只说“我遇到过一个重复上传 Bug”,而是按下面结构:
- 先说现象
- 再说预期
- 再说你怎么判断问题可能在哪一层
- 再说如果继续排查你会看什么
- 最后说这个 Bug 给你的测试启发
比如可以这样总结:
我遇到过一个网页端图片粘贴上传 Bug,一次粘贴只传 1 张图,但聊天框出现十几张相同图片。这个问题让我第一时间怀疑不是图片本身,而是粘贴事件被重复消费、上传队列去重失败或者前端状态重复追加。后来我也总结出一个经验:凡是上传、发送、支付、下单这种动作,都要特别关注幂等性和重复触发问题。
再比如移动端那个:
我在实习中还遇到过切换账号登录时 App 先退到桌面再自动重新打开的问题。这个 Bug 让我意识到账号切换不是一个简单登录功能,而是一个高风险全局状态切换场景。后续我在测登录态相关功能时,会特别关注页面栈清理、缓存清理、异步任务收尾和旧账号数据残留。
六、最后的总结
真正有价值的 Bug 复盘,不只是记住“哪里错了”,而是逐渐训练出下面这些能力:
- 看到现象后先分类
- 知道优先怀疑哪一层
- 知道下一步该抓什么证据
- 能把 Bug 转化成后续测试策略
对测试工程师来说,这种能力比单纯记很多八股更重要。
因为你以后不管是在面试里,还是在项目里,真正拉开差距的往往不是“知道多少名词”,而是:
你能不能把一个异常现象,快速拆成清晰的问题,并形成靠谱的分析路径。