实习笔记(二):测试基础概念、日常操作与前辈传授的那些经验
写这篇笔记的时候,我已经在测试岗位上待了几周,逐步从前两周的“手足无措”过渡到“知道自己在干什么”。上一篇我整理了入职初期的整体感受,这篇重点记录我实际接触到的测试基础概念、日常操作流程,以及前辈们在我耳边反复强调、后来事实证明每一条都很有用的经验。
这篇笔记适合正在实习、准备入行测试,或者刚转岗到测试岗位的朋友们。我写的东西不涉及什么高深理论,大部分是最贴近日常工作的东西:测试用例到底怎么设计才不算漏,Bug单怎么写才能不被开发怼回来,回归测试和冒烟测试到底有什么区别,以及遇到环境问题如何自己先排查一轮。如果你也处在“什么都会一点、什么都不精”的阶段,这篇应该能让你少走一些弯路。
1. 测试到底在测什么:重新理解“找Bug”这件事
1.1 我踩过的第一个坑:以为测试就是“点点点”
很多人对测试的印象停留在“打开APP到处乱点,能找到几个崩溃就说明干得不错”。我入职头两天也差不多是这个状态,拿到测试任务就顺着功能路径一个一个点,看到页面正常显示就算过。结果第一次提交完,带我的前辈看了一眼我的用例清单,直接问了一句:“你这些用例是想证明系统能用,还是想证明系统会出错?”
这句话让我愣了很久。后来我才慢慢明白,测试的核心目标不是“证明它能用”,而是“证明它还能在哪些情况下不能用”。顺着正常路径点一遍,只能覆盖最幸福的那条业务路线,一旦用户输入了边界值、走了异常分支、网络中途断开、权限配置不一致,系统可能立刻就崩了。而这些都是测试应该提前发现、提前暴露的问题。
后来我把这个想法记到了笔记第一页:测试是一个“证伪”过程,不是“证实”过程。用例设计的目标,是想方设法制造出能推翻系统“正常”假设的输入和环境,而不是把用户最常用的操作再重复一遍。
1.2 需求文档到底该怎么读
读需求是我实习前几周的另一个困惑点。在学校里接触的最多的是课程设计题目,功能清楚、边界明确,照着做就行。到了真实项目里,一份需求文档可能有几十页,里面还夹杂着各种啰嗦的历史背景、非功能约束、甚至几版修改记录,完全不知道该抓什么。
前辈教我一套方法,我整理完之后基本就是我的固定阅读流程:
第一步,先把需求文档里出现的主语圈出来,也就是这个系统里到底有哪些角色,普通用户、管理员、审核员、运营人员各自能看到什么、能做什么。
第二步,把每个角色对应的核心动作拉成一张操作列表,登录、查询、提交、审批、驳回、导出,每个动作背后都连着业务规则和状态变化。
第三步,重点读“如果”“当”“异常”“不允许”这类词后面的句子。比如“当库存不足时提示补充库存”“如果审核不通过则退回填写页”“用户不能重复提交同一申请”,这几句话几乎就是测试用例的命脉。
我之前很热衷于把需求里所有文字都翻译成用例,结果绝大多数都变成了对需求的复述。前辈说这叫“无效覆盖”,用例量很大,但真正能发现缺陷的没几条。正确的读法,是从需求中找到所有“分支场景”和“限制条件”,而不是把所有“正常流程”变成用例。这也是为什么同一个功能,有些人能设计出三四十条用例,有些人只能写七八条,差距基本都要追溯到读需求这一步。
1.3 也别把质量模型当成八股文
大学课程里几乎都讲过软件质量模型,功能正确性、可靠性、易用性、性能效率、兼容性、安全性,每个维度又拆出一堆子特性。实习之前我觉得这只是考试需要背的东西,进了项目才发现它其实是“查漏补缺的检查清单”。
举个例子,如果你只盯着功能测试,很容易忽略兼容性。我们项目里有一个导出Excel的功能,开发在本地用最新版环境验证一切正常,结果测试时安排在旧版本浏览器上一跑,导出的文件直接打不开。这种问题不写兼容性用例根本发现不了。
再比如易用性。有次测试一个表单页,功能规则全部通过,但我自己填的时候总觉得哪里别扭,提交按钮在页面底部,需要拖动滚动条才能看到。这个不算功能缺陷,但用户实际用起来体验很差。测试报告里我顺手提了一条体验类建议,没想到产品经理很重视,下个迭代就调整了布局。
所以我是这么理解的:质量模型不只是理论框架,它的价值是提醒你从更多角度去看一个功能,避免因为“功能能跑通”而忽略了其他会影响用户使用感受的因素。
2. 测试用例设计:从“想到哪写到哪”到“按套路覆盖”
2.1 用例的最基本结构:谁、做什么、输入什么、期望什么
先说我最早写出来的用例长什么样子。当时拿到需求文档里“用户可以修改个人信息”这句话,我唰唰写了好几条用例:
- 用户点击编辑按钮
- 系统显示编辑页面
- 用户修改手机号
- 系统提示修改成功
写完之后觉得挺完整,但前辈看后指出了问题:修改手机号要不要验证码?手机号格式错误系统怎么提示?空着不改直接保存会怎样?连续两次提交会不会重复触发验证码?你的用例没有一条覆盖这些场景。
这个教训几乎每个测试新人都会遇到。用例的基础结构确实是“前置条件 + 操作步骤 + 输入数据 + 预期结果”,但真正考验能力的是你在设计步骤时,有没有把操作背后的规则和异常往下拆一层。“系统提示修改成功”只是最基础的那条路径,真正的用例设计要回答的是“在什么条件下”“操作了什么功能”“给了什么输入”“系统应该给出什么响应”,每一步都得落在一个明确、具体的状态上。
我习惯把每条用例拆成四个要素来检查:
- 前置条件:系统处于什么状态,数据具备哪些条件
- 操作步骤:从哪个入口进入,具体做了什么
- 测试数据:输入了什么值或选择了哪个选项
- 预期结果:界面上出现什么、数据库里变化了什么、下游系统收到什么
直到今天我都觉得,如果你能把自己的每条用例都写清楚这四个要素,你的用例基本上就合格了。缺了任何一个,执行的人要么不知道从哪里开始,要么不知道结果对不对,要么根本不知道这一条在验证什么。
2.2 覆盖思路:等价类、边界值、场景法是怎么配合用的
设计方法大家都知道,等价类划分、边界值分析、因果图、场景法、判定表,上课时都背过定义。但真正把它们落到用例里,我花了不少时间才找到“组合感”。
等价类划分解决的是“无穷量怎么变成有限量”的问题。拿年龄输入框举例,有效等价类可能是18到60岁,无效等价类可能是小于18、大于60、非数字、空值。每类至少选一个代表值去测试,这是最基础的做法。
边界值分析是补充等价类用不到的“极限场景”。如果规则是18到60岁有效,那17、18、60、61这四个值就是必须测的边界。很多Bug都会出现在边界上,这几乎是测试行业里最容易出成果、也最容易被忽视的地方。
场景法解决的是“多步骤联动”的问题。用户注册、填写资料、上传证件、等待审核、审核通过、收到通知,这是一整条业务链路。每两个环节之间都可能产生状态传递,比如审核驳回后再修改资料重新提交,数据和状态能不能衔接上。只看单个页面是发现不了这种链路问题的。
我的执行顺序是这样的:先根据需求画出核心业务流程图,标出正常路径、分支路径、异常路径,然后对每个路径上的输入项做等价类和边界值分析,最后把所有限制条件组合成判定表。这样整体覆盖会比较完整,不会同一个角度反复测,其他角度完全不碰。前辈说这叫“按套路出牌”,不是靠灵感和运气去测,深以为然。
2.3 一次用例评审,被问得哑口无言之后再补的功课
我们项目上线前会做一轮用例评审,产品、开发、测试坐在一起过用例清单。我作为新人也跟着参加了自己负责模块的评审,刚开始还挺有信心,毕竟用例写了不少,每个功能点基本都覆盖到了。
结果开发看了一会儿,指着我的一条用例问了一个问题:“这里你预期结果是‘提示保存成功并返回列表页’,但万一保存成功之后接口返回的时候网络断了,前端页面会怎么表现?你这条用例预期结果只写了正常情况,异常情况你打算怎么验证?”
我确实没想到这个场景。页面提交到一半断网,这一步往上抛个报错提示还好说,但接口已经在后端执行完了,数据到底有没有写进去?用户是看到失败提示还是成功提示?重新进入页面时数据是否一致?这已经不只是前端显示问题,还涉及前后端状态一致性和接口幂等性。
那次评审给我的收获很大。用例评审不只是“确认一下有没有遗漏”,更多时候是开发用他的技术视角补上我对系统机制理解的空白。从前端页面展示,到后端接口处理,再到数据库状态变化,两边的判断经常是不一样的。测试用例里写的“预期结果”如果不考虑系统在异常情况下的实际行为,执行的时候基本测不出深层问题。
从那以后,我设计用例时会特意多问自己一句:这个操作如果中途失败了,系统会怎样?多问这一句,很多隐藏的Bug就这样被提前暴露出来。
3. 缺陷的生命周期与Bug单实操:从提交到关闭的全过程
3.1 提交Bug单之前,我一定会做的自我检查
实习阶段我提交过不少Bug,也闹过几次笑话。最典型的一次,我提交了一个“登录之后页面空白”的缺陷,开发看到就回了一条:“日志呢?控制台报错了没有?网络请求返回了什么?”我完全答不上来,最后还是前辈带着我重新复现,抓了网络请求,发现是返回数据格式变了一个字段名,导致前端解析失败。从那次以后,我每次提交Bug单之前,都会先做一遍完整的自查。
我总结了一套提交前的检查顺序:
第一步,确认我能稳定复现。只出现过一次的Bug先不要急着提,我会多操作几遍,确认它是不是固定能出现。如果三次里只能复现一次,我会在描述里写清楚出现频率和当时操作环境,不能只写“偶尔出现”。
第二步,把出现Bug前后的操作步骤完整记录下来。从哪个页面进来、点击了什么按钮、上传了什么文件、填写了什么数值,每一步都写。哪怕我怀疑某个步骤无关,也先写下来,让开发自己去判断。
第三步,截图或录屏存下来,并把关键提示信息单独摘出来放在描述最前面。控制台报错、接口返回码、弹窗里的错误文案,这些比截图更重要,是定位问题最直接的线索。
第四步,确认版本和环境信息。当前测试环境是哪个环境、测试的版本号是多少、用了什么浏览器或设备。尤其是前端问题,设备和浏览器版本几乎成了必填项。曾经有一个样式错乱问题,只有在特定浏览器下出现,换一个浏览器就正常,环境不写清楚开发根本无从下手。
做完这些检查,我才会去填Bug单。前辈说过一句话我记到现在:“测试的职责是把问题描述得让开发能被引导着快速定位,而不是丢一句‘这里坏了’就算完事。”我现在每次提Bug,都会下意识拿这句话来衡量自己。
3.2 缺陷生命周期里的几个关键流转环节
缺陷从提交到关闭,整个生命周期大致是:新建 → 待确认 → 已确认(或不复现/设计如此/重复提交)→ 处理中 → 待验证 → 已关闭(或者重新打开)。不同公司的系统叫法可能略有差异,但核心流转逻辑差不多。
我在实操里遇到最多的几个环节是这样的:
新建阶段,测试提交Bug单并分配给对应的开发。这个阶段最重要的是描述质量和级别判断。我刚开始很容易把所有Bug都标成“严重”,后来才知道一个崩溃级的阻断问题和一个文案显示错乱的问题根本不在同一个优先级上。级别标得过高会扰乱整个团队的排期,标得过低又可能拖到很久没人处理。合理的做法是:完全阻断主流程、数据丢失、系统崩溃的,才标严重;布局错乱、部分用户看不到内容,算中等;纯文案显示不统一或体验优化,算轻微。
开发处理阶段,有几种情况很常见。一种是开发看完描述后回复“我这里无法复现”,这种情况就需要测试去补充更详细的前置条件或者录屏,必要时约开发当面一起看。另一种是开发确认问题但觉得不算Bug、是需求本来就这么定的,这种情况一般会转到产品那里确认。还有一种是开发修改完直接说“已修复,可以验证”,订正后的代码上了测试环境,我去验证确认没问题就关闭,如果还有问题就重新打开,继续跟踪。
整个流程走下来,我觉得最考验测试耐心的就是“反复重开”。有时候开发认为修复完成,但实际场景里另一个分支又带出了新问题,或者修复方式不符合需求预期,一个Bug来来回回折腾好几天。一开始我会着急,后来我学会了在重新打开Bug单的时候把验证过程和失败截图贴上去,让开发第一时间知道我验证了什么、产生了什么结果,而不是空泛地留一句“还是有问题”,这样沟通效率高很多。
3.3 一个典型Bug从发现到关闭的完整记录
给你们看一个我印象比较深的Bug流转记录,正好完整走了一遍生命周期:
某个页面上传文件后,接口返回成功,但列表里显示的数据数量对不上,缺失了其中一条。我当时在测试环境连续复现了三次,每次都出现同样的情况,基本排除偶发因素。
我在Bug单里写的内容大致是:前置条件——测试环境下已登录管理员账号,上传包含10条数据的文件,文件格式符合模板要求;复现步骤——进入批量导入页,选择文件并上传,等待接口返回成功后进入列表页,发现列表只展示9条数据;实际结果——列表数据显示9条,接口返回成功提示;预期结果——列表完整展示10条数据;补充信息——测试环境版本号、接口返回码、页面控制台截图、数据请求返回值截图。
开发收到后很快定位到了原因,是导入接口处理数据时,有一条数据因为缺少一个非必填字段走了“校验失败”的逻辑,但校验失败的提示没有拼接到最终返回结果里,导致接口整体返回成功。从测试角度来看,这就是典型的“接口返回成功不代表业务完全成功”问题。修复后我重新上传了同样一份数据,列表正常展示了10条,再补试了上传空文件和重复文件两个场景,确认没问题才把Bug关闭。
这个案例给我最大的启发是:写Bug单时把接口返回值和页面对应状态分开记录,尤其当接口提示成功但页面数据不对的时候,这种信息对开发快速定位帮助极大。
4. 测试环境与数据准备:第一次独立测试就卡在了环境上
4.1 环境部署和联调排错的基本功
我们组的测试环境有一套自己部署的流程,版本更新、配置修改、重启服务这些操作虽然大部分由开发来执行,但测试也需要掌握最基础的连通性排查技能。因为很多Bug根本不是代码逻辑问题,而是环境问题,比如配置没刷、数据库连错、依赖服务没启动。
我第一次独立执行测试,上来就报告了一个“登录之后调接口报500”的Bug,结果开发一查,发现是我连的数据库指向了一个旧环境,里面的用户数据结构和新版本代码不匹配。这个事情非常典型:测试排查时第一反应是“查代码”,但环境层面的问题优先级应该更高。
我现在遇到类似问题,会按这个顺序排查:先看服务本身是否正常启动,再确认当前环境配置指向哪个数据库、哪个缓存服务,接着查看相关依赖服务(如订单系统、用户中心)是否可达,最后才去看接口返回值判断是不是代码逻辑问题。整个排查过程十分钟以内基本能完成,能筛掉至少一半的“假Bug”。
另外我想强调一下网络请求工具的使用。抓接口返回是测试的基本功,不是开发专属技能。打开浏览器的开发者工具,切到网络标签页,找到对应请求,查看返回状态码和响应体,这一步在定位问题的时候几乎是必修课。我现在每次提交疑似接口层面的Bug,都习惯把请求参数和返回数据一并截图,开发几乎都能秒定位。
4.2 测试数据准备:按业务场景倒推,而不是随机造数
实习初期我准备测试数据基本是零散的:页面需要什么就填什么,哪种数据好造先造哪种。后来发现很多场景测不了,比如审核流程需要一条“待审核”状态的数据,我在页面上怎么都造不出来,因为创建成功后默认状态是“已提交”,不会自动变成待审核。
前辈教我换一种思路准备数据:先梳理完整业务链路,确定各个环节需要什么状态的数据,再逆向准备。比如审批流涉及提交、审核、驳回、通过,那我就得准备至少四条不同状态的数据。这四条数据分别从哪里产生,每条需要怎样的前置操作,这个要提前列清楚。
还有一类数据是“边界数据”。测试一个金额字段时,正常数据很容易造,边界数据就需要专门去构造,比如刚好在限额边缘的值、超过限额的值、精度保留到小数点后好几位的情况。这类数据如果测试时没有提前备好,执行到一半就卡住了,很影响测试效率。
我自己的经验是:把测试需要的数据按照“正常数据”“边界数据”“异常数据”“业务状态数据”四个维度提前列出来,对应好造数方法,测试执行会顺畅很多。
4.3 冒烟测试和回归测试的区别,别再混着说了
实习前我总觉得冒烟测试就是“快速测一遍”,回归测试就是“再把上轮用例跑一遍”,细节上理解得模模糊糊。后来在真实迭代中才体会到,这两个概念在节奏和目标上都不一样。
冒烟测试是在一个新版本提测之后,用最快的时间验证主流程能不能跑通,它是一个“准入性”检查。如果登录进不去、主流程走不通,后续的用例执行就没有意义。所以冒烟测试用例一定要选最关键、最核心的那几条,而不是把所有用例全跑一遍。
回归测试是在功能修改完之后,验证原有功能没有被破坏。它讲究的是覆盖面和关联性分析:这次改动涉及哪些模块,哪些历史功能可能受影响,这些范围要先去判断,再有针对性跑起来。比如改了下游接口的返回字段,上游依赖这个字段的页面就可能出问题,这种关联模块没有回归到就等于埋了一个雷。
我实习过程中遇到过几次类似情况:一个看似很小的改动,影响了另外几个模块,当时没有及时回归,上线后用户才发现问题。这也是我为什么越来越重视回归测试的原因——修改某个功能导致另一个功能挂掉,这类问题不靠回归测试,靠人肉记忆是不可能发现的。
5. 前辈们传授的经验:那些写在口头、偏不写进文档的干货
5.1 测试计划的真实作用:把控风险和排期,而不是走流程
实习之前我以为测试计划就是把测试范围、用例数量、执行时间写进一个文档交给领导看。真正跟完一个迭代后才知道,测试计划其实是用来排风险和排人力的。
前辈给我讲过一个很现实的问题:开发提测晚了两天,但上线日期不变,那留给测试的时间就少了,怎么办?这个问题的答案不能是“安排加班”,而应该是重新评估测试范围,把优先级低的用例挪到下一轮、只保核心功能和新功能,或者跟产品商量缩小本次发布范围。这些决策靠的都是测试计划里的风险判断和优先级梳理,临时去翻用例根本来不及。
所以我现在理解,测试计划的核心不是“要测什么”,而是“在有限的时间和资源下,怎么保证最重要的东西先被测出来”。这可以说是一种“优先级管理”的能力,说白了就是会做取舍。
5.2 和开发沟通的三条铁律
实习生最好奇的问题之一,就是测试和开发怎么沟通才不会吵架。我亲眼见过因为一个Bug的描述不清晰,开发和测试在群里来回对了十几条消息,最后居然是在说两个不同环境的问题。这种信息差带来的沟通成本,完全可以通过沟通习惯来降低。
我梳理一下前辈们反复强调、我自己也验证过的三条铁律:
第一条,描述问题必须带上环境、版本、账号这些前置信息,不要让人猜。我们在群里日常协作时,第一句话就会说明“XX测试环境、XX版本、管理员账号”,避免出现“我这边是好的啊”这种因为环境不同而无法对齐的情况。
第二条,先说结论,再展开过程。初级测试很容易从头讲起背景和操作,说了半天还没有点到重点。开发每天时间碎片化严重,一句话没说到问题上,他可能就不想再看了。现在我无论写Bug单还是在群里反馈,第一句永远是结果,比如“批量导入后列表少了一条数据,接口返回200”,然后再补复现步骤。
第三条,不确定是Bug的,先按“疑似问题”沟通,不要直接下结论“你代码错了”。有些情况是数据问题、环境配置问题、需求本身定义就是这样,一上来就断定是开发的责任,很容易把合作氛围搞僵。探明情况再定性,沟通会顺很多。
5.3 前辈的口头禅:“先看日志,别猜问题”
这句话几乎贯穿我整个实习过程。每次我描述一个Bug半天找不到原因的时候,前辈都会先说一句:“看了日志吗?先看日志,别自己猜。”
日志是测试排查问题最直接的证据来源。前端可以看控制台报错,后端可以看服务日志和异常堆栈。比如页面操作无反应,可能是前端没发请求,也可能是后端处理时报了异常,如果不看日志,用肉眼在页面上胡乱试,就是浪费时间。
我第一次独立排查一个问题时,浪费了将近半小时在页面上反复操作,后来前辈帮我翻了后端日志,看到一条空指针异常堆栈,定位到是某个关联数据为空。文件本身没问题,是数据库某条关联记录缺失。从那以后,我的排查习惯就改成:先看页面反应,再抓网络请求,再看后端日志,三步走完再考虑要不要提Bug给开发。
日志这种东西,你越熟练越觉得简单,但新手经常忽略它。我觉得一个测试如果连基本的日志定位能力都没有,工作一半时间都耗在“无法定位”上,别人帮不上忙,自己也很难成长。
5.4 日报周报别写流水账,写清楚“判断和结论”
实习要求写日报周报,一开始我写得很机械,“今天测了登录模块,发现一个Bug,提给了开发”,一句话就完了。后来前辈帮我改了表达方式:要写清楚我今天测了什么范围、发现了什么风险、验证了什么结论、下一步需要什么支持。
这样写的好处是,leader一看就知道你在做什么,也能快速评估你手里的风险和阻塞项。比如“客户管理模块冒烟测试通过,支持进入详细用例执行阶段;但导出功能存在数据量过大时接口超时问题,已提交Bug并和开发确认修复排期,不影响本轮主要功能验收”,这比写十句“今天测了XX”有用得多。
写周报也是复盘的过程,回过头看一眼这一周测试下来,哪些模块风险高、哪些用例设计明显不够、哪些Bug和打扰完全可以前置排查,下个迭代就能做得更好。这些心得比报告本身更有价值。
5.5 测试用例执行之外的自我成长:学会建立“缺陷思维”
前辈们在我实习一段时间后跟我聊过一个比较深的话题:测试这个岗位的长期竞争力,不体现在你发现了多少Bug,而体现在你多快能建立一个完整的“缺陷思维模式”。
所谓缺陷思维,就是看到一个功能时,大脑自动开始追问:这个输入如果是空的呢?这个按钮如果被连点呢?这个状态如果跳过了呢?网络如果断了一下呢?用户如果同时做了两个操作呢?这种思维不是天生来的,是靠大量训练养成的。我实习早期很羡慕前辈一眼就能挑出很多我没注意到的场景,后来发现他们也是踩过无数个坑才练出来的。
实习这段时间,我越来越觉得测试不只是“找茬”,而是一种风险控制工作。通过系统性设计、有效执行、清晰提交缺陷,帮助团队在发布前发现并解决问题,把未知风险变成已知风险,把可能崩溃的用户场景扼杀在上线之前,这本身就是很有成就感的事。
最后再分享一个小习惯:我每天实习结束,会用十分钟把当天遇到的问题、排查的思路、前辈教的方法简单记在笔记里。很多经验第一次听觉得记住了,隔一周就忘了,写下来才是自己的。这个习惯,比我做的任何用例都值钱。