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