在分布式存储产品的测试过程中,测试到底做了些什么事情呢?
测试需要参与到每一个过程中
在设计评审的时候就需要知道验收的标准,这是最重要的开始。因为这个时候如果没有理解用户的需求,验收标准就会跑偏。
用户的需求是测试的基准点。
需要确定测试范围。上线的时间都是固定的,在有限的时间内可能无法覆盖所有的测试,得指定测试范围。
这一方面取决于测试对整个系统的了解程度,另一方面也是考验和开发沟通和交流能力。
测试用例的设计与开发
主要是根据需求编写测试工具或者测试用例代码。一些测试书籍上也介绍了一些常见的方法。这里不多讲。
只有自动化测试才能把人从简单,重复,繁琐的劳动中解放出来。
引入持续集成机制,及时发现代码中存在的问题。
测试对象确定
主要是确定需要测试的版本,以保证最后上线的版本就是测试的版本。
测试实施及反馈
完成测试计划,编写测试报告,在Bug跟踪系统上记录测试中发现的问题。
搜集这些结果给项目经理做质量评估。虽然不全面,但也是重要参考。
统计测试结果,分析。
统计测试覆盖率,跟踪未覆盖到的地方。
这里需要说明的是,测试覆盖率达标了,不意味着测试达标了,只是表示所有的代码都覆盖到了。还需要人工分析测试的完备性。
上线版本及配置文件的最终确认。将所有上线的功能以邮件的形式通知给合作伙伴。
后期线上问题的反馈与追踪,以避免在下个版本中出现同样的问题。
分布式存储产品的开发和测试是个庞大的工程,所涉及到的测试需要分类及分级。为此,引入了测试分级的概念。
测试分级 | 测试资源 | 测试目的 | 测试频率 |
---|---|---|---|
一级:单元测试 | 单机完成 | 不需要依赖其他环境,完成代码函数级别的测试。会采取一些Mock手段去掉对环境的依赖 | 每次提交代码 |
二级:功能测试 | 小集群 | 模拟真实场景,完成功能级别的测试。对其他模块有依赖 | 每次提交代码 |
三级:系统测试 | 小集群 | 模拟真实场景,完成系统级别的测试,是功能的组合。对其他模块有依赖 | 每次提交代码 |
四级:一级性能测试 | 中型集群 | 模拟真实场景,完成性能测试。主要关注Latency,QPS,毛刺率,吞吐量等指标。对其他环境有依赖 | 每次发布 |
五级:二级性能测试 | 中型集群 | 模拟真实场景,完成压力测试,健壮性测试(Failover测试)。主要关注CPU,内存,网络等资源耗尽或者不可用的情况下,系统的表现 | 每次发布 |
六级:数据兼容性及升级测试 | 小集群 | 模拟真实场景,完成存储及上线发布相关测试。 | 每次发布 |
七级:端到端模拟用户场景测试 | 大集群 | 模拟用户的场景,获得测试数据 | 每次发布 |
这个分级的目的主要是为了:
开发需要负责单元测试和功能测试都通过,
才表示代码可测了。才能走到后面的测试流程。
在紧急上线的时候,有所取舍
不同的级别意味着不同的测试时间,一次单元测试和一次性能测试的时间是不一样的。一级和二级是必须要全通过。往上的级别可以有选择性地通过。
分布式存储产品的特点:
所以在设计测试用的时候根据分布式存储产品的特点设计了如下的测试用例:
代码一直在变,会有不同的数据类型出现,如何保证数据兼容性?
一般来说都需要考虑新旧版本写入数据的兼容性。
实践中可以每天模拟用户写入不同大小,不同类型的文件,在每次升级之前预发布,来校验这些数据。以做到数据兼容测试。
开发也会在UT中包含这部分内容。只不过是在不同的级别来测试这一点。
作为分布式存储产品,用户的数据是不能丢的。这点是做存储的底裤。
在实践中会每天扫描新增的数据以检查数据的完整性。
定期还会做全量数据扫描。
每次版本发布的时候,我们需要知道这个版本和上一个版本相比,性能是否有提升。这个也是用户比较能直观感受到的。
性能测试是一个比较复杂的话题,这里不展开。
性能测试和测试的客户端,使用的代码,请求的类型,集群数据的多少都有关系。实践中是选定差不多的测试环境,进行对比,以减少多个测试变量对性能结果带来的影响。
模拟网络,磁盘,CPU等资源消耗完,测试系统的表现能力。对系统设定报警阈值。一旦超过这个能力,系统开始报警。也可以供运维同学参考集群的负载能力。
测试系统在长期运行下,观察内存,网络,CPU资源消耗的情况。常见的问题就是内存泄露,如果每次泄露一点,短时间测试是无法发现问题的。所以一般要求系统能连续运行7天以上。
慢连接攻击测试
大并发模拟攻击测试
其他攻击模拟
也指Failover测试,实践中也是分层的思想
先分模块:
模拟系统各个模块失效的情况。例如进程重启,进程不再启动等。
再分机器:
对于分布式系统来说,机器资源出现状况简直是一定的,例如CPU不够用,内存超了,网卡无法使用,磁盘损坏,机器断电等情况。自动化测试可以通过软件来模拟这些情况。
在实际上线的时候,还是需要做一些模拟故障演练。例如:一台或者多台机器出现断电。
再分集群:
整个集群掉电后重启,数据是否丢失。
不可服务的时间,重启后多久恢复服务。
集群中交换机不可用。这些测试还得依赖于运维工程师的合作。
工欲善其事必先利其器,测试工具的选择也很重要。
在我们实践的过程中没有采用商业软件,大多数也没有现成工具,大多是通过工程实践摸索,开发而来。
工具 | 目的 |
---|---|
集群监控状态收集与自检工具 | 用于测试过程中收集监控数据和自动判断是否异常以帮助测试及早发现问题 |
bug、case的报表分析工具 | 用于通过从bug或case的多个维度来判断当前产品的质量风险点 |
测试结果报表分析工具 | 将测试结果用于比较和分析,方便性能问题的调查 |
性能压力测试工具 | 该功能能够模拟用户的请求压力,请求类型,方便地获取性能数据 |
系统测试框架 | 该工具能够很好地定制测试需求,完成测试任务,发出测试报告,提交测试结果 |
pre-check-in工具 | 该工具能够确保代码在提交前能够自动跑通相关测试集合 |
代码覆盖率报表分析工具 | 代码覆盖率报告分析工具,能够方便给出覆盖率不足的各组件代码 |
静态代码检查工具 | 能够确保代码在提交前能够跑通静态代码检查并提供报表功能 |
协议层、工具层的覆盖率检查工具 | 能够对组件的协议层和工具命令层进行覆盖率检查,来保证测试的覆盖面 |
即使在做了如此多测试的情况下,还是可能会有漏网之鱼。怎么办?
在实践中,我觉得比较行之有效的方法是做好灰度发布。
这里说的灰度发布指的是,发布的时候只发布一部分机器,观察。没有问题,再逐步分批次发布,直至最终全部上线。
做好灰度发布的前提:
1 系统是有兼容性的
也就是说,整个系统应该是能够兼容新旧版本同时存在,且不会相互影响。
如果新版本写入的旧版本不能读,那么需要发布到中间的兼容版本。
机器资源的可视化与监控。例如CPU,内存,网络等是否正常
各层模块的可用性指标可视化与监控。例如成功率,队列长度,健康度等是否正常
关键业务数据指标的可视化与监控。请求的正确率,性能,QPS等业务指标等是否正常
引入大数据工具对每天的访问请求进行分析,得到真正的业务请求。
做好实时监控,以确定系统的稳定性
一个有责任心的工程师会在发布以后去关注功能是否如期工作,那些日志是否正常,线上机器,业务是否都运转正常。
如果上线后有漏网之鱼,应该及时地发现,并在缺陷系统中跟踪,直至修复上线,并且在测试用例中覆盖。以避免重复的错误出现。
如何保障产品发布的质量是一个很大的话题。
总结自己在产品中的方法有:
在具体的测试实践中,还是碰到了很多问题。
由于测试不稳定,导致测试经常失败。大家都失败有时候都熟视无睹了。典型的破窗原理。
单一的环境无法满足几个层级的测试需求,但测试资源有时候是有限的。需要做好规划。
由于产品功能的不断叠加,回归的集合原来越庞大,越来越复杂。回归一次的时间变得越来越长。需要重构测试用例。
由于产品在发布的时候可能会有多个分支在回归,比如正在开发的代码分支,线上需要修复的代码分支。
但回归效率不高,只能排队等待。还是需要提高测试效率。减少回归的时间
测试用例的要求没有开发代码要求高,测试框架中对日志支持不够友好,都造成了调查问题困难。需要改进日志。
我们还是需要做很多工作,让测试更快,更有效地发生。
有几点感受吧:
知道了和做到了之间还差十万八千里。
用韩寒的话说就是:我懂得了许多道理,却依然过不好这一生。
用成语说就是:知易行难。
但靠谱的人总是能在各种不靠谱的环境下,把事情做靠谱。
好的测试工程师就像优秀的守门员,时刻预防着Bug的进攻,守住质量这扇门。
但再好的守门员没有前锋,后卫的团队配合,单枪匹马也无法阻止Bug的进攻。
质量贯穿在每一次评审,代码Review,单元测试,上线观察,灰度发布中等环节中。只有每一个环节都做到位,才会有好的质量。
质量是需要开发,测试,运维一起保障的。
没有质量的代码上线就是运维噩梦的开始。
它可能伴随着半夜报警,连夜修复,通宵紧急发布。
尽可能多的眼睛,就可以让所有的问题浮现。每个人的视角不一样,就像是手术台上的无影灯一样,从各个角度照射下去,Bug就无所遁形。
每个人的思想在碰撞,也许别人的一句提醒或者一个问题,就可以发现自己的视野盲区。