1. 完整的开发流程是什么?(测试处于什么位置?)
1.1 传统的开发流程
在传统的软件研发周期中,有个比较著名的模式叫“瀑布模式”,在这个模式中,项目周期被清晰的分为“制定计划->需求分析->软件设计->程序编码->软件测试->运行维护”等六个基本活动。并且规定了它们自上而下、相互衔接的固定次序,如同瀑布流水,逐级下落。
如果我们看下面从左到右的顺序,测试阶段就是软件生命周期中的一个特定阶段,并且这个阶段处于比较靠右的一个阶段(如上图软件测试在第五个阶段)。
1.2 缺陷的引入与发现
测试阶段所处位置处于整个软件开发生命周期的末端,这会带来什么问题?首先我们讨论一下在软件开发的过程中,引入缺陷的环节。
- 缺陷何时注入?下图显示了大部分缺陷是在编码阶段出现的,这是可以预料的。这些缺陷包括了开发人员犯的实际的错误,误解了需求,或是不考虑特定代码的后果。
当需要将开发的各个功能模块组合在一起时,未经充分设计的代码也会产生缺陷,被引入到应用程序中,尤其是在涉及多个团队的情况下(以及随着微服务之类的现代体系结构变得更加复杂)。 - 何时发现这些缺陷?很显然,通常在开始测试时就会发现缺陷。但是我们在这里看到的是,即使大多数缺陷是在编码阶段中引入的,但在编码阶段,代码的缺陷几乎没有发现。
- 修复缺陷要花多大的代价?由于大多数缺陷是在编码过程中引入的,但往往直到后续阶段这些缺陷才被发现。在编码阶段结束后发现缺陷,修复缺陷的成本就会急剧增加。
缺陷在系统测试阶段被发现的修复成本,是在编码阶段被发现并进行修复的40倍。也要比在单元测试阶段发现并修复的成本高10倍。
值得注意的是,当只有一台设备部署了有缺陷的代码时,成本尚且可控。但在实际的交付环境中,我们部署的设备数量可能高达几万台,如此一来,当这些潜在的缺陷流入交付环境,修复这些缺陷的成本将难以想象。
在下游阶段进行缺陷修复的成本上升的原因:
- 跟踪问题所需的时间和精力。测试用例越复杂,就越难确定其中哪一部分是真正的麻烦制造者。
- 由于引入了诸如数据库或第三方API之类的从属系统,在开发和测试的环境上再进行问题的复现可能具有偶现性,缺陷复现具有挑战。(在这种情况下,组织在缺陷检测和缺陷修复之间经历数周的延迟是很常见的。)
- 修复缺陷所需的更改的影响。如果是简单的错误,那就没关系了。但是,如果您在很多地方都做过,或者使用了错误的框架,或者所构建的代码的可伸缩性不足以承受预期的负载,或者无法确保代码的安全性……
2. 什么是测试左移?(引出测试左移的重要性和好处)
2.1 问题发现得越早,修复的成本越低
假如在编码阶段发现的缺陷只需要1分钟就能解决,那么单元测试阶段需要4分钟,功能测试阶段需要10分钟,系统测试阶段需要40分钟,而到了上线之后再发现可能就需要640分钟来修复,这可以说是很难让人接受的。
所以为了降低修复缺陷的成本,我们需要提早发现缺陷,防止大量缺陷流入到测试阶段,甚至是线上环境。
- 于是我们希望将黄色曲线(缺陷发现曲线)的峰值出现位置尽量远离红色曲线(修复缺陷成本曲线)的高值位置,也就是将黄色曲线峰值位置向左移,如下图所示。如此一来发现并修复缺陷的成本将在一定程度上有所下降,因为它说明了基于较早测试(左移)的缺陷检测周期所带来的收益。
- 那么这已经到达最低成本了吗?我们是否可以继续尝试将黄色曲线左移?如下图所示,这样我们已经在测试层面尽我们所能地降低成本了。
例如,2017 年,波耐蒙研究所 (Ponemon Institute) 的研究发现,如果在早期开发过程中检测到漏洞,修复成本平均约为 80 美元。但如果在投入生产后才检测到漏洞,修复成本可能高达约 7,600 美元。
2.2 测试左移
于是,软件行业出现了变革,从研发完成后测试才介入的方式,变成从制定计划,需求分析的阶段测试就开始参与进入,从“链条”上看,测试的工作“左移”了。
测试左移也就意味着不是在最后阶段进行测试,而是一直持续测试。测试左移的原则支持测试团队在软件开发周期早期和所有干系人合作,因此他们能清晰地理解需求以及设计测试用例去帮助软件“快速失败”,促使团队更早的修改所有的bug。
参与和理解会使测试人员获取产品完整的知识,彻底想清楚各种场景,根据软件行为设计实时的场景,这些都会帮助团队在编码完成之前识别出一些缺陷。
测试左移:测试左移,本质上是借助工具和测试手段更早地发现问题和预防问题。
- 需求:对需求、架构和设计模型的测试;
- 开发:着重增加对单元、组件和服务层的测试;
- 持续测试:自动化测试。
3. 测试左移的内容?(技术细节)
2.1 需求分析阶段
在需求分析阶段,测试左移的第一步就是确保测试人员参与需求评审。测试人员应当与产品经理、业务分析师紧密合作,确保需求文档中的每一个细节都足够清晰、具体,且具备可测试性。此外,测试人员还应协助定义验收标准(Acceptance Criteria),这有助于确保需求文档中包含的信息足以支持后续测试用例的设计。
同时,测试人员应在此阶段进行初步的风险评估,识别出可能影响产品质量的风险因素,并提出相应的预防措施。例如,如果需求文档中存在不确定性或矛盾的地方,测试人员应及时指出并协助澄清。
具体的测试活动包括:
- 需求澄清:在开始一个项目或开发过程之前,明确并验证所有相关方的需求。
- 需求评审/用户故事评审:通常发生在需求分析阶段结束时,目的是评估需求文档的质量,是否完整、一致、可行、明确、可验证。
-
用户故事启动(Story kickoff):在不同的语境下,也叫需求条目启动、开卡等。对于单个用户故事,在开发人员要开始编码前进行的再次澄清和确认,主要是确认其中的验收标准是否不够完备、是否大家都理解一致了。形式要求尽量轻量级,在开发人员电脑前完成即可,需要业务分析、开发和测试共同参与,时间一般不要超过15分钟。
2.2 软件设计阶段
进入软件设计阶段后,测试左移要求测试人员参与到架构评审和设计讨论中。通过理解系统架构,测试人员可以评估设计方案是否满足非功能性需求(如性能、安全性)。此外,测试人员还可以在此阶段开始思考如何设计测试环境,以及选择合适的测试工具和技术。
这里鼓励采用测试驱动开发 (TDD——Test-Driven Development)的方法论:即开发人员在编写代码之前先编写测试用例,然后编写能够使这些测试用例通过的代码。这种方法有助于确保代码按照预期的功能运作,并且可以作为开发过程中的一种指导。
TDD 强调的是“红绿重构”(Red-Green-Refactor)的循环过程:
- 红色(Red):开发先编写一个测试用例,该测试用例会失败(因为还没有实现相应的功能)。
- 绿色(Green):编写足够的生产代码来通过刚刚编写的测试用例。
- 重构(Refactor):在不影响测试通过的情况下,优化代码结构,使其更简洁、更具可读性和可维护性。
2.3 程序编码阶段
在编码阶段,测试左移意味着不仅要关注单元测试,还要重视代码审查和静态代码分析。
- 单元测试:由开发人员编写,确保每个模块独立正确运行。实际上TDD 本身就是一种编写单元测试的方法,但由于复杂的逻辑、性能的要求等,还是需要编写额外的单元测试来补充 TDD 过程中的测试用例。
- 代码审查:同行之间互相检查代码的过程,有助于发现潜在的问题并在早期修正它们。
- 静态代码分析:使用工具检查代码质量,发现编码规范问题或其他潜在缺陷。
此外,开发过程通过持续集成(Continuous Integration,简称 CI)可以在开发人员频繁地将代码合并到共享的主干分支过程中,自动构建和测试这些合并的代码,每次代码提交后都会自动构建并运行一系列测试(如单元测试、集成测试)。通过持续集成,可以及早发现和修复集成问题,提高软件的质量,并加快开发周期。
2.4 软件测试阶段
测试阶段是传统意义上的集中测试期,此阶段的测试左移着重于提高测试覆盖率,缩短测试周期。它要求测试人员在此阶段执行全面的功能测试、性能测试和安全测试。
- 功能测试确保软件按预期工作。
- 性能测试则用来模拟真实环境下的负载情况,检测系统的响应能力和稳定性。
- 安全测试则是为了确保应用程序没有明显的安全漏洞。
根据测试分层理论,自动化测试可能包括单元测试、接口测试和端到端测试。通常单元测试是开发人员编写,而接口测试和端到端测试可以开发和测试协作完成。其中,通常建议单元测试和接口测试在用户故事开发环节完成,应该属于用户故事开发DoD的一部分。
自动化测试通过编写测试脚本来模拟用户的操作和行为,自动执行测试用例,并记录测试结果。自动化测试可以显著提高测试效率,减少重复性劳动,并且能够实现持续集成中的自动化测试流程。例如,使用Selenium可以自动化Web应用的测试,而JUnit则常用于Java应用程序的单元测试。这些工具允许开发者编写测试脚本,自动化执行测试,及时发现代码变更带来的问题。
回归测试是在修改了部分代码或增加了新功能之后,重新执行以前的测试用例,以确认现有功能没有受到负面影响。通过自动化回归测试,可以确保每次迭代后原有功能不受影响。自动化回归测试通常结合持续集成工具(如Jenkins、GitLab CI)使用,在每次代码提交后自动触发构建和测试流程。这种方式可以快速检测出由于新的代码提交导致的问题,减少手动回归测试所需的时间和成本。
2.5 上线发布阶段
在上线发布阶段,测试左移的重点在于确保新版本能够平稳过渡,减少生产环境中的风险。
通过实施A/B测试,可以在生产环境中对新特性进行小范围测试,收集真实用户反馈,评估新功能的表现。
此外,采用蓝绿部署策略,可以创建两个独立的生产环境,其中一个环境运行现有的稳定版本,另一个环境部署新版本。当新版本准备就绪后,流量可以平滑地从旧环境切换到新环境,如果遇到问题,可以迅速回滚到之前的稳定版本,从而大大减少了部署风险。
同时,利用Prometheus和Grafana等实时监控工具,可以持续监控应用性能,及时发现并响应异常情况,确保系统的稳定运行。这些措施共同保障了软件在上线发布阶段的质量和可靠性。
4. 如何做到测试左移?(软件开发过程中注意的问题)
- 合理的需求分析:参与需求评审、评估需求的质量、分析需求的合理性以及完整性
- 完整的系统设计:代码字段、框架工具的扩展性
- 充分利用静态代码扫描,检查代码问题
- 编写测试用例:用例设计尽可能多覆盖场景
- 测试用例评审:需求再次拆解分析,查缺补漏
- 尽早地测试执行:提早参与测试执行,在集成前就发现一些问题
- 开发自测:提测质量提高
- 适当的探索性测试
- 团队质量意识的培养
5. 测试左移需要注意什么
5.1 测试左移不是QA或测试人员的左移,也不是简单移到需求分析阶段
测试左移常被误认为是QA或者测试人员参与需求分析。其实,测试左移不是人员的简单左移,而是将测试活动左移,在需求、开发等多个环节开展测试相关活动。只要是在原有独立测试阶段之前做的测试工作都可以算作测试左移。
可能大家也会注意到我们会强调QA/测试人员参与需求分析,或者说从需求分析阶段开始介入,其原因主要是因为在绝大多数团队,QA/测试人员还是作为质量保障工作的主力,左移的测试活动暂时还离不开这些主力的参与。
5.2 测试左移不仅是开发自测/提前进行自动化测试,也不仅是TDD
说到测试左移,有人就会提到开发自测、TDD或者开发编写自动化测试。当然,这些都是测试左移实践,但测试左移实践远不止这些。
5.3 测试左移跟持续测试分不开,需要持续在各个环节进行测试活动
测试左移相关测试活动都不是一次性的,而是需要持续频繁地在整个软件开发过程中开展,实现持续地测试,持续地获取快速反馈,实现缺陷的真正预防。
5.4 测试左移实践不能流于形式化
任何实践都不能流于形式化,测试左移实践当然也是如此。对于任何一个左移实践,不能人云亦云,而是要根据实践所能带来的价值,结合自己项目团队的实际情况去开展。同时要不断回顾,进行调整和优化,让实践发挥真正的价值。
5.5 测试左移实践需要跟测试右移/生产环境下的QA活动形成良性闭环
在《测试右移——生成环境下的QA》中介绍生产环境下的QA的时候,提到过需要跟前期各个活动形成良性环路:
生产环境下的QA所设置的监控标准是根据系统的行为特点和在预生产环境下的表现来定义的,生产环境下各项反馈的分析结果反过来又影响着预生产环境的QA过程,而且这两者是相辅相成的,只有形成了良性环路,才能把生产环境下的QA做好。
也可以理解为测试左移活动需要跟生产环境下的QA活动形成良性环路,比如:在Desk Check环节增加日志记录评审(Logging Review),确保日志记录是满足生产环境下的QA的;生成环境下的缺陷分析,反过来也可以帮助优化测试左移活动,更好地做到缺陷预防等。
5.6 测试左移不会增加QA的工作量
说到测试左移,就会推荐QA/测试人员尽早介入,最好能提前到需求阶段,大家自然就会以为原本QA/测试人员就已经够忙了,再左移岂不是更忙不过来了?
其实,不必担心这个。
参考资料
测试知识——测试左移与测试右移的理解与实践 - 青城杂文录 - 博客园
测试左移+测试右移,我们一定要会吗?得物测试leader告诉你_哔哩哔哩_bilibili
软件测试左移技术,零基础快速掌握_哔哩哔哩_bilibili
软件测试流程及规范(参考大华为的规范)_华为软件测试通过率指标计算规则-CSDN博客
华为软件测试工程师分享的自动化测试经验,纯干货!_测试分享-CSDN博客
testing-shift-left - 测试左移 - BY林子
20210613-性能测试左移的实现_哔哩哔哩_bilibili
Shift Left Testing: What, Why & How To Shift Left – BMC Software | Blogs