代码静态检查实践
为什么需要代码静态检查?
代码静态检查,即静态代码分析,是指不运行被测代码,仅通过分析或检查源程序的语法、结构、过程、接口等检查程序的正确性,并找出代码中隐藏的错误和缺陷。
代码静态检查规则的建立往往需要大量的时间沉淀和技术积累,挑选合适的静态代码分析工具,自动化执行代码检查和分析,可以极大地提高代码静态检查的可靠性,节省测试成本。
静态检查工具的优势
主要包括以下三个方面:
- 帮助软件开发人员自动执行静态代码分析,快速定位代码的隐藏错误和缺陷;
- 帮助软件设计人员更专注于分析和解决代码设计缺陷;
- 显著减少在代码逐行检查上花费的时间,提高软件可靠性的同时可以降低软件测试成本。
SonarQube 是一款目前比较流行的代码静态检查工具。
静态代码检查近五年的发展状况
自2013年以来,国内的大型互联网公司已开始积极地搭建持续交付环境,并如火如荼地开展持续交付的实践。持续交付流程除了启用代码静态检查工具外,还发生了如下变化:
- 从某些团队开展静态检查到所有团队都开展静态检查;
- 持续交付系统从缺少静态检查到强制静态检查;
- 从借用其他公司的检查规则到形成自己的检查规则。
设定科学的检查流程
静态检查相关的流程可设定如下:
- 鼓励开发人员在开发环境下载执行静态检查;
- 不管采用的是主干开发还是特性分支开发的分支策略,都进可能地在代码合入主干之前,通过静态检查;
- 没有通过静态检查的产品包,不允许发布到线上或用户验证环境。
这三个环节的检查,需要特别注意两点:
1.公司或团队通常会有一个公共检查规则的最小集合(简称Rules),不管哪个步骤的检查,至少得保证通过这个最小集合的检查。
2.不管是开发环境还是持续交付系统,都需要及时、方便地获取到这个统一的Rules.
跳过检查的几类方式
代码检查时可能会有以下问题发生:
- 代码规则可能不适合程序语言的多个版本;
- 第三方代码生成器自动产生的代码存在问题,该怎么略过静态检查;
- 静态检查受客观情况的限制,存在误报的情况;
- 某些规则对部分情况检查得过于苛刻;
- 其他尚未归类的不适合做静态检查的问题。
针对以上问题的处理策略,可分为三类:
- 把某些文件设置为完全不做静态检查;
- 把某些文件内部的某些类后方法设置为不做某些规则的检查;
- 调整规则的严重级别,让规则适应语言的多个版本。
如何提高静态检查的效率?
- 提升静态检查平台的处理能力;
- 在代码合入主干前采用增量形式的静态检查。
什么是破坏性测试?
破坏性测试就是通过有效的测试手段,使软件应用程序出现崩溃或失败的情况,然后测试在这样的情况下,软件运行会产生什么结果,而这些结果又是否符合预期。
使用的测试手段必须是有效的,有两点原因:
第一, 破坏性测试的手段和过程,并不是无的放矢,它们是被严格设计和执行的。
第二, 破坏性测试,会产生切实的破坏作用,需要权衡破坏的量和度。
破坏性测试的流程与用例设计
破坏性测试与普通测试流程,唯一不同的是,绝大部分普通测试可以在测试失败后,继续进行其他的测试;而破坏性测试,则有可能无法恢复到待测状态,只能停止后续的测试。
设计破坏性测试的测试用例时,通常会考虑两个维度:
第一个维度是,一个破坏点的具体测试,即设计一个或一组操作,能够导致应用或系统崩溃或异常。此时,需要注意两个问题:
- 出现问题后的系统或软件是否有能力按预期捕获和处理异常;
- 确认被破坏的系统是否有能力按照预期设计进行必要的修复,以确保能够继续处理后续内容。
第二个维度是,整个系统的破坏性测试,通常会采用压力测试、暴力测试、阻断链路去除外部依赖等方法,试图找到需要进行破坏性测试的具体的点。
破坏性测试的执行策略
绝大部分破坏性测试都会在单元测试、功能测试阶段执行。而执行测试的环境也往往是局部的测试子环境。
但真实环境要比测试子环境更复杂多变,在测试子环境进行的破坏性测试真的有效吗?所以,最近几年,技术圈衍生出一个很流行的理论:混沌工程。
混沌工程
随着分布式系统架构的不断进步,传统的破坏性测试也越发捉襟见肘,最主要的问题有两个:
第一, 它被设计得太严格,以至于失真了。而真正有破坏力的故障,都是随机的、并行的、胡乱的。
第二, 它覆盖不了生产环境,只能做到类似抽样检验的能力,且很难重复和持续。
所以,混沌工程的理论就应运而生了。
混沌工程是在分布式系统上建立的实验,其目的是建立对系统承受混乱冲击能力的信心。
分布式系统的弱点:
- 当服务不可用时,不可用或不完整的回退能力;
- 不合理的设置超时时间引起的重试风暴;
- 依赖服务接收过多的流量,从而导致中断;
- 由单个故障点引起的级联故障。
要避免这些弱点在生产过程中影响客户,需要一种方法来探知和管理这些系统固有的混乱,经实践证明,通过一些受控实验,能够观察这些弱点在系统中的行为。这种实验方法,被叫作混沌工程。
实验方法,即科学实验都必须遵循的4个步骤:
- 将正常系统的一些正常行为的可测量数据定义为“稳定态”;
- 建立一个对照组,并假设对照组合实验组都保持“稳定态”;
- 引入真实世界的变量,如服务器崩溃、断网、磁盘损坏等;
- 尝试寻找对照组合实验组之间的差异,找出系统弱点。
混沌工程的几个高级原则:
- 使用改变现实世界的事件,就是要在真实的场景中进行实验,而不要想象和构造一些假想和假设的场景;
- 在生产环境运行,为了发现真实场景的弱点,所以更建议在生产环境运行这些实验;
- 自动化连续实现,人工的手工操作时劳动密集型的、不可持续的,因此要把混沌工程自动化构建到系统中;
- 最小爆破半径,与第二条配合,要尽量减少对用户的负面影响,即使不可避免,也要尽力减少范围和程度。
Netflix 公司的先驱实践
Netflix 为了保证其系统在AWS上的健壮性,创造了Chaos Monkey, 是混沌工程的先驱者。
利用Mock与回放技术助力自动化回归
持续交付中的测试难点
“第一座大山”:测试数据的准备和清理。
“第二座大山”:分布式系统地依赖。
“第三座大山”:测试用例的高度仿真。
如何翻越这三座大山,可以利用Mock和回放技术这两大利器。
两大利器之一 Mock
如果某个对象在测试过程中依赖于另一个复杂对象,而这个复杂对象又很难被从测试过程中剥离出来,那么就可以利用Mock去模拟并代替这个复杂对象。
Mock为测试和持续交付带来的价值,可以总结为以下三点:
- 使测试用例更独立、更解耦。
- 提升测试用例的执行速度。
- 提高测试用例准备的效率。
如何在测试中使用Mock技术?
第一, 基于对象和类的Mock
推荐使用的框架是Mockito或者EasyMock。
第二, 基于微服务的Mock
推荐的框架是Weir Mock和Mock Server.
两大利器之二“回放”技术
要做到和实际用户操作一致,最好的方法就是记录实际用户在生产环境的操作,然后在测试环境中回放。
首先,如何把用户的请求记录下来?
携程实践
第一种方案是,在统一的SLB上做统一的拦截和复制转发处理。这个方案的好处是,管理统一,实现难度也不算大。缺点是, SLB是生产主路径上的处理服务,一不小心,可能影响本身的路由服务,形成故障。
第二种方案是,在集群中扩容一台服务器,在该服务器上启动一个软交换,由该软交换负责复制和转发用户请求,而真正的用户请求,仍旧由该服务器进行处理。
然后,看看回放的多样性。
- 按照正常的时间间隔,按照记录进行顺序回放;
- 压缩回放时间,形成一定的压力,进行回放,达到压力测试的目的;
- 根据业务特性自研回放工具。