测试这行干久了你会发现一个很有意思的现象很多人背得出“单元测试、集成测试、系统测试、验收测试”这十二个字但真到了项目里这四个阶段该怎么划分、每个阶段该测到什么程度、什么时候该往下走却经常是凭感觉来的。我见过太多项目号称做了完整的测试实际上就是把功能点手动点了一遍连单元测试都没写过集成的时候全靠线上用户当测试员。也有反过来的情况单元测试写得非常漂亮覆盖率刷到90%但系统一上线就崩溃因为接口联调的问题根本没人管过。“测试必须要知道的四个主要阶段”这句话看着像面试题实际上是软件测试工作组织的底层逻辑。四个阶段不是流程文档里拿来充数的名词而是四道不同性质的闸门第一道闸门验证代码本身第二道验证模块之间能否协作第三道验证整个系统是否满足需求第四道验证用户是否真的接受。每一道闸门都在回答一个完全不同的问题漏掉任何一道后面的代价都会成倍放大。这篇文章我按照实际项目里的经验把四个阶段拆开揉碎讲清楚。如果你刚入行可以把它当成一张测试路线图如果你已经带项目了也能对照着看看自己的测试策略有没有盲区。1. 为什么测试必须分成四个阶段1.1 没有阶段规划的测试是怎样的先还原一个真实的混乱场景。某个内部管理系统的迭代开发同学按模块分工A同学写用户管理B同学写权限控制C同学写审批流程。大家各自开发完代码编译能通过自己本地也点了几下觉得没问题了就合到一起准备上线。结果一联调就炸了A模块返回的用户数据格式是驼峰命名B模块解析的时候按的下划线命名拿到数据全是空的C模块调权限接口的时候超时配置设成了1秒审批高峰期经常直接失败。这种问题靠“随手点点”是不可能发现的因为每个模块单看都是正常的问题出在模块之间的约定和协作上。没有阶段划分意味着所有人都把测试当成“最后上线前的一个环节”所有的质量风险都堆在最后那几天爆发然后又没有足够时间修只能带病上线。1.2 四个阶段各回答一个什么问题四个测试阶段真正在回答的是四个递进的问题单元测试回答的是我写的这段代码逻辑对不对。它是白盒层面的验证关注的是函数的输入、输出、分支、异常处理。这一层最贴近代码也最能反映开发人员的编码质量。集成测试回答的是这些模块拼在一起能不能正常协作。它关注的是接口调用是否正确、数据格式是否一致、模块之间的依赖关系是否清晰。这一层的问题单元测试测不出来手工点也很难点到。系统测试回答的是整个系统作为一个整体是否满足需求。它关注的是功能完整性、性能指标、安全性、兼容性、易用性是站在用户视角去检验整个产品。验收测试回答的是做出来的东西用户是否认可并愿意收下。它通常由业务方或最终用户参与目标是确认软件符合合同约定的验收标准可以交付上线。这四个问题复杂度是逐级上升的。越往后越接近真实使用场景发现的问题也越难修因为问题可能藏在很深的调用链里定位成本很高。1.3 阶段划分的核心价值是风险前移我在项目里最深的体会是测试阶段划分的真正价值不是流程好看而是把风险往左推。这里说的“左”指的是时间轴上更早的位置。一个缺陷如果能在单元测试阶段发现改起来可能只需要几分钟因为问题就在眼前那个函数里。如果等系统测试阶段才发现可能要走一遍“复现问题-定位模块-排查调用链-修复-回归”的完整流程几个小时的功夫不一定够。如果上线后被用户发现那就涉及故障通报、数据修复、版本回滚搞不好还要写事故复盘报告。用一个生活化的类比来说四个阶段就像装修房子。单元测试是检查每一块砖有没有烧透集成测试是检查砖和砖之间灰缝是否饱满系统测试是检查整面墙砌得直不直、门窗能不能正常用验收测试是业主拎包入住前说自己满不满意。如果你只管最后验收那一步前面砌墙的时候砖没烧透、灰缝全是空的那返工就是拆墙重来代价完全不一样。所以这四个阶段不是流程文档里拿来充数的名词而是四道不同性质的闸门。每一道闸门都在回答一个完全不同的问题漏掉任何一道后面的代价都会成倍放大。2. 单元测试第一道闸门2.1 单元测试到底在测什么单元测试是四个阶段里最底层、也最容易被忽略的一个。很多团队在赶进度的时候首先砍掉的就是它理由是“开发自己随便点一下不就行了”。但我的看法正好相反单元测试是性价比最高的一层测试因为它离代码最近、反馈最快、定位成本最低。单元测试的重点不是“把函数调通”而是“把函数的各种输入情况都覆盖到”。它要求被测代码是一个个相对独立的单元可以在不启动整个系统的情况下被单独验证。最典型的单元是一个函数、一个方法或者一个类。它的关注点包括正常输入下返回值是否符合预期边界输入下逻辑是否还能正确处理比如空字符串、最大长度、0值、非法格式异常输入下能否抛出预期的异常而不是静默失败分支覆盖判断语句的每个分支是否都被走到了我见过一个很典型的案例。某个订单模块里有一个计算折扣的函数看起来很简单根据用户等级和订单金额计算最终应付金额。开发同学写完函数本地跑了一次输入一个普通订单输出正常就觉得测试完事了。结果线上运行时发现当用户等级参数传入一个空值的时候代码直接抛了空指针异常导致整个下单流程全部失败。这就是典型的单元测试没有覆盖空值输入的教训。2.2 用一个小例子看懂断言和用例设计写单元测试的方法其实不难理解核心就是三句话给定输入、调用函数、断言输出。比如下面这个密码强度校验函数import re def validate_password(password): # 长度至少8位 if len(password) 8: return False # 必须包含字母和数字 if not re.search(r[A-Za-z], password): return False if not re.search(r\d, password): return False return True对应的单元测试可以这样设计def test_validate_password(): # 正常场景长度足够且包含字母数字 assert validate_password(abc12345) True # 长度不足 assert validate_password(a1b2c3) False # 纯字母、没有数字 assert validate_password(abcdefgh) False # 空字符串 assert validate_password() False # 边界恰好8位的纯边界情况 assert validate_password(abcd1234) True这里有一个我非常看重的技巧边界值法。大多数逻辑错误都发生在边界附近所以测试用例一定要特别关注“刚好满足条件”和“刚好差一点”这两种情况。比如长度要求是8那7、8、9三个值都应该测。条件要求“包含字母和数字”那“纯字母”“纯数字”“包含特殊字符但不含数字”都应该构造出来。好的单元测试本质上是在代码层面给函数做了一次全面的“体检清单”。2.3 谁来写单元测试什么时候写关于单元测试团队里永远有一个争论应该由开发来写还是由测试来写。我的实践经验是单元测试必须由写这段代码的开发同学来写。原因很简单单元测试需要对代码内部逻辑有深入理解知道哪些分支是核心路径哪些异常处理是防御性的这些信息只有写代码的人最清楚。测试人员如果来做这件事光是把代码读懂的时间成本就非常高了。至于什么时候写行业里讨论得比较多的是测试驱动开发也就是先写测试再写实现。我的建议是如果没有做过TDD的团队可以不用强求但至少要保证“代码提交之前单元测试必须通过”。也就是做到“边写代码边跑测试”写完一个函数就跑一遍相关测试而不是攒到最后才补。等到功能全部开发完再写单元测试开发同学往往会因为“反正代码都能跑了测试补一下就行”的心态随便写几个用例凑覆盖率失去了真正的意义。2.4 单元测试的常见误区我以为单元测试做久了最常见的误区有三个第一个是只写正常用例不写异常用例。测试全绿了信心满满结果线上一个空指针直接打脸。第二个是过度关注覆盖率数字。覆盖率只是参考不是目标。有些团队把行覆盖率刷到90%以上但关键的分支逻辑完全没测到。真正的关键不是“代码有多少行被执行了”而是“风险最高的逻辑有没有被验证”。第三个是把单元测试写成了集成测试。比如测试一个函数的时候真的去连了数据库、调了外部接口导致测试速度很慢、环境一换就挂。这不是单元测试该干的事应该用桩对象或依赖隔离的方式保证单元测试的快速和稳定。注意单元测试如果运行时间超过几十秒基本就说明被测单元的范围没划对或者依赖没有隔离好。单元测试应该是像呼吸一样轻快的东西跑一次不超过几秒这样才能被高频执行才能真正发挥守门员的作用。3. 集成测试模块之间的磨合期3.1 单元测试全绿为什么一联调就崩我遇到过很多次这种情况每个模块的单元测试都是绿的代码review也做了信心满满地开始联调结果一部署到集成环境就到处都是问题。原因在于单元测试验证的只是“单个零件没问题”但软件系统是一个很多零件组装在一起的整体零件单看没问题不代表组装起来就能正常运转。集成测试要关注的恰恰是单元测试覆盖不到的模块之间交互的问题。比如A模块调用B模块的接口传参名的拼写错了A模块返回的数据格式和B模块的解析逻辑不匹配A模块对B模块的接口做了超时设置但设置时间太短正常响应都等不到两个模块的数据库连接串指向了不同的实例导致数据各写各的。这些问题的共同特点是如果不把模块拼在一起跑光看代码很难发现而一旦跑起来经常是连锁反应一个地方报错后续一片失败。3.2 集成策略自底向上和自顶向下集成测试怎么组织业界有两个经典策略我在不同的项目里都用过。自底向上集成就是从最底层、最基础的模块开始测逐步往上组装。这种策略的优势在于下层模块是稳定的测试过程中一旦出问题可以快速定位到当前正在测试的模块排查范围小。代价是底层模块测的时候上层模块还不存在需要写桩模块来模拟上层调用测试后期才能真正看到完整的系统形态。自顶向下集成反过来从最上层的入口开始逐步往下走。它的优势是能够尽早看到整个系统的主流程跑通业务价值感更强但问题在于上层测试依赖的下层模块可能还没开发完需要写很多驱动模块来模拟底层功能桩代码的工作量非常大。我在实际项目中经常采用的是“核心链路优先的混合策略”先梳理出系统里最核心的一条业务链路把这个链路上的模块优先集成起来跑通然后再以这个核心链路为骨架逐步把外围模块加进来。这比严格按照“底层往上”或“顶层往下”的教科书方式更贴近现实因为大部分项目的核心链路也就是两三个模块的交互先把主干打通风险就降低了一大半。3.3 接口联调最容易踩的几个坑集成测试阶段我踩过太多坑了随手列几个典型的接口返回值格式不一致。前端团队和后端团队约定好了用JSON结果后端在某个字段上返回了字符串前端拿到的是对象解析直接报错。这种问题通过字段类型校验脚本可以提前发现。超时配置不合理。我见过一个系统下游接口的平均响应时间是800毫秒结果上游调用方的超时时间设成了500毫秒导致三成的调用直接失败在大促流量进来的时候尤其明显。超时配置一定是要根据真实的压测数据来定的不能用拍脑袋的经验值。数据库事务边界不对。两个模块各自操作同一份数据一个模块提交了事务另一个模块因为缓存没刷新读出来的还是旧数据。这类问题表面上是数据不一致实际上是事务和缓存策略没有在集成测试里充分验证。环境依赖没有被管理好。有些模块依赖的第三方服务地址是写在配置文件里的但集成环境用的是测试地址生产环境又是另一个地址配置一换行为就变了。集成测试部署的时候配置管理不做好很容易出现“测试环境是绿的生产环境是红的”。3.4 集成测试自动化落地的建议集成测试比单元测试重但不代表不能自动化。我建议集成测试至少覆盖几条最重要的链路用自动化脚本跑起来放在每次发版的流水线里核心业务主流程的端到端接口调用确保“注册-登录-下单-支付-查询”这种链路是通的关键模块之间的接口契约校验定期检查字段名、类型、枚举值是否匹配外部依赖的连通性检查确保数据库、消息队列、缓存等服务状态正常回滚演练验证确保在上线出问题时回滚脚本可以顺利执行我踩过几次坑之后最大的体会是集成测试的自动化脚本不一定要多但一定要覆盖“最容易出问题且影响最大”的那条链路。很多团队疯狂堆接口自动化的用例数量却从来没跑过一条完整的端到端主流程这种投入产出比是非常低的。宁可只有十条用例但每一条都是从用户入口打到数据落库的真实链路也比一百条只验证单个接口的用例强得多。4. 系统测试系统级全面体检4.1 系统测试到底覆盖哪些维度到了系统测试这个阶段被测对象是完整的系统了。它不再关心某个函数的分支对不对也不再关心两个模块之间的传参格式而是关心整个系统在真实场景下的表现是否达标。系统测试的覆盖维度非常广至少包括功能测试所有需求的功能点是否完整实现业务流程是否走通性能测试并发用户下的响应时间、吞吐量、资源使用率安全测试越权访问、SQL注入、XSS攻击、敏感信息泄露兼容性测试不同浏览器、不同操作系统、不同设备上的表现可靠性测试长时间运行是否稳定异常恢复是否正常易用性测试界面操作是否符合直觉核心任务是否容易完成在大部分项目里系统测试最核心的永远是功能测试因为功能不过关谈其他的没有意义。但仅仅做功能测试又是不完整的性能和安全问题往往在功能测试阶段根本暴露不出来。4.2 功能测试的用例设计方法功能测试的用例设计最有用的方法是等价类划分和场景法。等价类划分的思路是把输入域划分成若干个等价类每个等价类中的数据在程序中的处理方式是一样的所以从每个等价类中取一个代表值就够了。比如一个订单金额输入框有效等价类是大于0的数字无效等价类是0、负数、非数字字符。每个等价类至少设计一个用例就能达到不错的覆盖率。场景法更适合业务流程类的测试。比如一个订单提交流程正常场景是“选商品-加购物车-填地址-生成订单-支付-完成”分支场景可能有“购物车为空时提交”“地址栏为空时提交”“支付超时后重新支付”“库存不足时下单失败”。测试的时候把主路径和每个分支路径都走一遍才算覆盖了一个完整的业务流程。我最常对测试新人说的一句话是功能测试不是点得越多越好而是要动脑子设计。你花一个上午无脑点点点可能都不如精心设计三十条用例覆盖的风险场景完整。用例设计的能力才是功能测试真正的技术含量。4.3 性能测试的关键指标和真实场景性能测试是系统测试阶段技术门槛最高的一个专项。因为它不只是“测一测看系统卡不卡”而是要回答几个具体的问题系统能承受多大的并发、响应有多快、资源消耗是否可控、瓶颈在哪里。性能测试的三个核心指标是响应时间、吞吐量、并发用户数。它们之间的关系可以简单理解为并发用户数提高了响应时间会变长响应时间变长了单位时间内完成的请求数吞吐量就会下降。性能测试要做的事情就是找出这三者之间的平衡点找到系统在保证可接受响应时间的前提下最大能支撑多少并发和吞吐。做性能测试的时候我建议一定不要只测“Happy Path”。比如一个电商系统只测“浏览商品”是很轻的请求但真实用户是边浏览边加购边下单还有大量的查询和支付请求。性能测试的脚本设计越接近真实用户行为测试结果才越有参考价值。另一个容易被忽略的操作是性能测试一定要监控服务器端的CPU、内存、磁盘I/O、网络带宽不然你只知道“系统慢”不知道“慢在哪里”更不知道怎么优化。4.4 兼容性、安全性和其他专项测试兼容性测试的思路是做减法确定目标环境矩阵。不用把所有浏览器、所有版本都测一遍而是根据用户画像选出一个核心矩阵。比如一个面向企业内部用户的管理系统如果公司统一用的是某一种标准浏览器那兼容性测试重点验证这个浏览器的不同版本就够了如果是一个面向公众的网站就需要覆盖主流浏览器的最近两到三个大版本。安全测试里最基础也最应该做的是越权测试和注入测试。越权测试就是换个用户身份去访问别人的数据验证系统是否有权限控制注入测试就是UTF-8编码字段里拼接SQL语句或脚本验证系统是否做了参数化处理和输入过滤。很多团队觉得安全测试要请专门的安全团队来做实际上自动化工具就能覆盖掉相当大比例的基础风险关键是要有这条测试意识。兼容性、安全这些专项测试不一定每次迭代都全部执行但每次发版前至少要评估一下“这次改动是否涉及到了需要专项测试的范围”。如果只是改了一个按钮的颜色没有兼容性的必要如果改的是登录鉴权模块安全测试一定不能省。5. 验收测试最后一关是用户说了算5.1 验收测试的两种典型场景验收测试和系统测试最本质的区别在于系统测试是对照需求文档来检验系统验收测试是对照合同或业务预期来确认“用户愿意收下这个系统”。我做过很多项目有一条经验非常深刻系统测试全绿、满足所有需求条款的软件到了验收阶段照样可能被用户拒收。因为用户真正在意的不一定是需求文档里的每一句话而是这个系统能不能顺畅地解决他们的问题。验收测试大体分两种场景。一种是内部项目比如公司内部的运营管理系统验收由内部的业务部门来组织确认功能符合业务预期后就算通过流程相对轻另一种是外部项目比如给某公司开发一套客户管理系统验收由甲方来组织有正式的验收标准文档逐项核对签字确认流程非常重。无论哪种场景验收测试都需要提前确定三样东西验收时间点、验收范围、验收通过标准。这三样如果在项目初期没有明确下来验收阶段几乎必然扯皮。5.2 验收标准该怎么定才不扯皮制定验收标准是验收测试最关键的动作。最忌讳的写法是“系统功能正常”“系统性能良好”这种模糊描述因为“正常”和“良好”每个人都有不同的理解。我在一个报表项目上吃过这个亏验收标准写的是“报表页面可以展示数据”结果用户验收的时候打开页面发现默认查询了一个很大的时间范围响应花了半分钟就说系统不合格开发觉得冤得不行因为“数据确实展示出来了啊”。后来我们总结验收标准一定写成可量化的格式。功能上写明每条验收用例对应的具体步骤和预期结果性能上写清楚在多少个并发用户下核心接口的响应时间不超过几秒、吞吐量不低于多少缺陷上写明哪一级别的缺陷必须全部关闭才能验收通过。我在实践中用过一个比较实用的验收红线清单核心业务流程100%走通不存在阻塞性的功能缺陷所有重大缺陷已关闭一般缺陷有明确修复计划和负责人性能指标在约定负载下达标异常情况下能够优雅降级而不是直接崩溃数据和权限校验正确没有越权和数据泄露问题全部验收测试用例执行完毕结论明确在验收测试开始前跟业务方逐条过一遍这个红线清单确认双方理解一致会省掉后面很多麻烦。5.3 Alpha测试和Beta测试怎么安排验收测试里还有两个经常会提到的概念Alpha测试和Beta测试它们本质上是验收前不同开放程度的验证方式。Alpha测试是在开发方的环境里、由用户在开发人员的陪同下进行测试属于“可控环境下的预验收”。它的好处是发现问题可以第一时间反馈、快速修复但问题是环境毕竟不是用户的真实环境某些问题无法复现。Beta测试是把软件部署到用户的真实环境中让用户在真实的业务场景里使用一段时间属于“真实环境下的试运行”。它的好处是能发现很多实验室环境里永远暴露不出来的问题比如真实数据量下的性能瓶颈、某些特殊设备上的显示问题、和用户其他系统的数据交互问题等。但坏处是问题反馈到修复的周期比较长因为环境不在自己手里复现和定位都要靠用户配合。我在实际工作中建议如果项目周期允许Alpha和Beta测试都要安排。Alpha测试作为正式验收前的一道防线Beta测试作为上线后的观察期。如果只能选一个对用户影响大的系统优先用Beta测试因为真实环境里的验证比实验室验证可靠得多。5.4 验收阶段容易忽略的隐性工作验收测试表面上是测试工作实际上有一堆隐性工作在同时推进如果忽略了验收即使技术层面通过了后面也很难收尾。第一个是验收文档的沉淀。每条验收用例的执行结果、缺陷清单、遗留问题评估都要成体系地记录下来。这些文档不光是给业务方看的更是团队自己后续维护和升级的底稿。第二个是数据迁移和初始化。很多项目在验收的时候要从旧系统把数据迁到新系统数据迁移的准确性、完整性、新旧系统的数据一致性都需要专门的验证而且这些工作通常要在验收开始前就完成。第三个是培训和操作手册。验收测试的用户第一次接触新系统如果不做操作培训很多“缺陷”其实是用户不会操作导致的。提前准备一份简洁的操作手册、做一次现场培训能大幅降低验收阶段的无效沟通成本。这些工作本身不直接产出测试结论但会直接影响验收是否能顺利通过。我在项目里一贯的做法是把验收阶段当成一个“小型的项目交付”来管理测试只是一部分配套的文档、培训、环境准备全部要排进计划。6. 测试常见问题与排查技巧实录6.1 测试环境与测试数据问题测试工作里最让人头疼的往往不是代码本身的Bug而是“环境问题”和“数据问题”。我见过开发在本地跑得好好的部署到测试环境就报错也见过测试人员花了一整天复现一个缺陷结果发现是测试数据被其他同事改掉了。环境问题的高发原因主要是配置漂移。不同环境的数据库地址、外部服务地址、配置中心的值很容易不一致。解决这个问题的有效手段是环境配置的代码化所有环境的基础配置都放在版本管理里环境之间的差异用变量区分发布的时候自动替换。这样至少能把“配置不一致”这类问题从根上掐掉。测试数据问题则要靠数据治理。共用数据库的时候测试执行之前最好能锁定数据范围或者用独立的测试数据集合执行完测试之后要能快速恢复初始状态避免上一个用例的脏数据影响下一个用例。很多团队用数据库镜像或加数据生成脚本的方式来解决效果都不错。6.2 缺陷定位与复现技巧测试人员发现缺陷只是第一步能帮助开发快速定位缺陷才是真正的价值。我总结了一套相对高效的缺陷定位流程先判断问题的范围。通过错误提示、日志信息确定问题大致发生在哪个模块是前端、后端还是数据库层面。前端问题看浏览器控制台后端问题看服务日志数据问题看数据库里的实际值。再尝试最小化复现路径。如果一个复杂的操作流程能触发Bug我会尝试简化操作步骤找到能触发问题的最小路径。很多时候问题只会在某个特定的前置条件下触发把前置条件找出来定位范围就缩小了一大截。然后是记录关键现场信息。时间点、触发步骤、输入数据、响应状态、相关日志片段最好还能截图或录制操作过程。这些信息越完整开发定位问题的速度越快。如果一个Bug偶尔出现但没法稳定复现我的建议是逐步改变输入条件比如用户身份、数据规模、操作顺序、网络状况尽可能缩小触发条件范围。实在复现不了就记录清楚出现频率和已知规律上线后加强监控观察。6.3 测试进度被压缩怎么办测试时间不够用几乎是每个测试人员都会遇到的现实问题。我的态度是进度可以压缩风险控制不能丢。当测试时间被压缩时最不应该做的事情是“把原来设计的测试用例随便点点、走一遍流程”。这么做的结果是测试看起来做了该踩的雷一个都没少踩。正确的做法是做风险分级。把所有待测试的功能按“影响面大小”和“出错可能性”两个维度做一轮评估把高影响、高概率的用例保留完整执行中风险用例做精简执行低风险用例做冒烟验证甚至跳过。同时把“哪些功能没有充分测试”明确地同步给项目干系人而不是自己默默咽了。让管理层知道测试时间压缩的风险在哪个位置后续上线后的运维重点也才有着落。我常跟测试新人说的一句话是测试不是保证软件没有Bug的活动而是用有限资源与无限风险博弈的活动。时间越紧越要把资源用在刀刃上。6.4 我的个人测试习惯清单最后分享一些我做测试这些年的个人习惯不一定适合所有人但不少是踩过坑之后才沉淀下来的。每个迭代开始前先把上一轮遗留的缺陷清单拉出来确认哪些修复了、哪些还没修、哪些需要重新验证带病上线的缺陷一定要单独标记跟踪。开始新功能的测试之前先做一轮完整回归确认上一个迭代没有把东西搞坏。测试用例永远不嫌多但执行顺序要有讲究。我习惯先把核心业务路径跑通再测边界和异常最后测非功能项。核心路径没跑通之前测再多边界用例都意义不大。线上出了事故不急着甩锅先把自己测试层面的漏洞找出来是用例没覆盖到还是环境差异导致还是测试数据没构造对。每一条线上故障都是测试设计下一次迭代的输入项。写测试报告的时候不只写“用例通过率”。我最重视的是“遗留风险描述”哪些功能还有隐患、哪些场景没有覆盖、哪些已知问题正在修复让读报告人对软件的真实质量状态有准确的判断。测试报告的价值不是证明测试做完了而是帮助团队做“能不能发布”这个决策。一些收尾的话做了这么多年测试回头看这四个阶段最大的体会是它们不是流程文档里冷冰冰的节点而是四道层层递进的防线。如果你只记住了这篇文章里的一个观点我希望是这一条越早发现问题的测试才是越有价值的测试。单元测试能力范围内能发现的缺陷不要等到集成测试才发现集成测试能发现的缺陷不要等到系统测试才发现系统测试能发现的缺陷更不要拖到用户上线后才被发现。每一层左移节省下来的不只是修Bug的时间还有整个团队的信任和心态。测试这行方法永远是越做越细的但底层逻辑不变用最小的代价把最重要的风险挡在用户之前。