作者 | 王涛,巨杉数据库联合创始人、CTO
责编 | 唐小引
封图 | CSDN 下载自 VCG
刚刚过去的这个春节,新型冠状病毒突如其来地横扫大江南北。工厂停工,学校停课。为了响应国家号召,许多软件公司和互联网公司也将在较长一段时间内建议员工采取远程办公的方式,同时也存在骨干工程师无法及时返岗的问题,使得生产力大受影响。
对于软件企业来说,研发与测试是两大核心命脉。研发团队保障着产品新功能新特性的及时发布,而测试团队则如同野马的缰绳,确保产品不会由于迭代速度过快、设计考虑角度不周,而导致软件缺陷的产生。巨杉数据库在经过 9 年的自研和技术创新历程中,在研发体系构建、自动化测试、团队线上线下结合等方面积累了很多经验。从 2011 年团队成立之初开始,我们的整个技术研发体系就以面向流程协作的方式进行构建。其核心思想是,任何员工可以在任何地点,只要遵循正确的流程,就可以与整个团队有机地衔接在一起。在这个非常时刻,为了帮助在远程办公期间内保质保量完成新版本的迭代与测试工作,我们也将自己的一些经验分享给大家,也是本文的内容:如何在无人值守的环境下,完成产品的自动化测试与研发协作。
基础体系
1. 网络基础设施
我们的整个开发环境分为内外网两大网络,其中外部网络可以连接到广域网 Internet,而内部网络则没有广域网连接。外网包括办公室中每个员工的台式机,以及可供员工进行远程连接的 VPN 服务器与防火墙。工程师们无论使用办公室的电脑,还是通过配发的笔记本电脑从远程通过 VPN 接入,均连入公司的外网网段。
公司的外网网段与内网则只能通过虚拟桌面连接,任何员工的办公室电脑或通过 VPN 连入的笔记本电脑,均无法直接访问内网环境中的开发与测试服务器。通过使用 Remote Desktop 等远程连接软件,我们工程师的电脑连接到虚拟桌面服务器后,所有的文档、代码、测试用例的编写均在虚拟桌面服务器中完成。同时,虚拟桌面可以直接通过 SSH 连接内网的开发与测试服务器,可以进行代码的编译、提交、测试等所有操作。
通过这种机制,任何工程师可以在任何时间地点,使用任何笔记本或台式机即可接入自己的虚拟桌面,大家所有的文档、代码、资料均统一存储在个人的虚拟桌面中。例如对于长时间的编译任务来说,就算是编译到一半需要换个工作环境,大家只需要合上笔记本电脑,回到家中打开并连上 VPN,就可以看到自己的远程桌面上编译的结果了。
在我们的内部网络,则主要分为管理集群、开发集群、以及测试集群三大网段。
2. 管理集群
管理集群主要包括 Jira 流程管理、Confluence 内容管理、GitLab 代码管理、以及我们内部自研的资源管理等几大服务。
其中 Jira 流程管理作为研发与测试的主要协作流程,任何测试团队发现的潜在 bug 会在内部 Jira 上提单,并分配给对应模块的开发负责人。研发工程师接收到测试提交的问题单后,会进行问题重现与编码修复。
Jira 流程管理示意
任何代码的修改需要在研发内部进行 Code Review,同时当开发人员编写的代码完全通过测试后,则进行代码 Merge 操作。不论是 Code Review 还是 Merge,我们均基于 GitLab 进行代码的流程管控。
GitLab 代码管理
我们全部的正式设计文档均在 GitLab 中保存,而研发与测试人员自己的一些经验分享则会上传到 Confluence 内容管理系统中,前线实施工程师与所有的后方研发测试人员均可以访问 Confluence 系统中的文档。
Confluence 文档管理
当前我们内网的服务器总数,虚拟机与物理机加起来近千台。因此如何协调管理分配这些计算和测试资源,也是非常复杂的事情。一些测试用例可能需要几十上百台服务器资源,如何在需要时进行分配,在不需要时释放这些资源,就是我们内部自研的自动化资源管理框架所承担的任务。
3. 研发与测试集群
而对于研发集群来说,主要承担的任务就是代码编译与单元测试。在我们的开发环境中,每个工程师均被分配最少三台虚拟机。每次编译完成,在正式提交持续集成测试之前,每个工程师必须完整通过自己的单元测试以及快速标准测试。
在快速标准测试中,我们当前包含大约 2800 个测试用例,完整运行一遍大约需要 20 分钟左右,所有开发人员在将代码提交给持续集成测试框架之前,必须完成快速标准测试,已保障代码最基本的健壮性。
而测试集群则分为三大部分:持续集成、性能测试、以及功能和混沌测试。
其中,持续集成 CI 使用 Jenkins 工具,结合我们自行开发的远程调度框架,运行在大约 300 台虚拟机中,24 小时不间断地反复运行近 2 万个测试用例。
Jenkins 示意
而性能测试则是完全基于物理机,包括多种配置的 x86 服务器、OpenPower 服务器、以及国产化 ARM 服务器。我们当前使用了十余套不同类型的性能测试框架,包括 benchmarksql、tpccrunner、sysbench 以及一系列其他的标准化测试框架。每个重要功能的合入与变更、以及所有的版本发布之前必须完成性能测试,并绘出与之前所有版本的性能对比曲线,已进行性能回归测试。
功能测试与混沌测试使用同一集群。一般来说,功能测试需要一定的手工操作,主要是用来模拟一些外部汇报的问题、以及一些较难使用脚本自动化完成的操作。另外,新功能开发后,测试团队在梳理出测试用例后会首先在功能测试区完成对应测试,再将其固化为持续集成脚本进行自动化测试。
我们每次版本发布前会有 2 周左右的代码冻结窗口。在代码冻结窗口内,除非最高优先级的故障修复才会被允许合并入主干代码库。在这个期间内,测试团队会用最严格的的手段,使用 libfiu 结合混沌测试的机制,在整个集群环境中随意注入故障(例如网络中断、丢包、磁盘数据损坏、磁盘满、控制器错误、服务器挂起、服务器掉电、服务器时间错乱等),并确保数据不会产生错乱或丢失。
4. 远程协作
如果说网络设施是保障无人值守团队有效协作的基础,远程协作工具与流程则是是否能够高效进行协作的核心。
我们当前的团队分散在北京、上海、广州、深圳、成都等几大城市,团队之间的沟通非常频繁,因此早在 2014 年就开始搭建了远程协作通讯机制。
当前我们使用了两套不同的远程会议系统(小鱼易连以及 Maxhub),以避免任何一套失效。其中小鱼易连要作为 Presentation 分享以及多人会议系统,支持超过 20 方同时在线,对于驻扎在各个客户现场的前线实施工程师与后方研发测试通讯非常有帮助。而 Maxhub 则更多作为技术讨论系统,支持远程白板绘图。工程师可以在电视终端上,通过触控笔直接绘图,而远程的团队则可以在他们对应的电视终端上听到语音,并实时看到所绘制的图像。
远程会议和协作平台
除了正式的视频会议与分享之外,由于研发团队内部虚拟桌面网络不直接连接广域网,因此 IM 工具使用的是不需要外网链接的腾讯 RTX;而如果需要与前线实施团队交流时则通过桌面电脑,使用 Skype 作为团队之间的实时沟通工具。
5. 团队组织
众所周知,一个大型项目必须被尽可能切分成小模块,才能够有效保障开发周期与代码质量。几十人同时进行一个功能的开发必然会导致灾难性的结果。
我们的研发体系按照研发 测试进行划分。研发人员则一方面按各自专长,以 SQL 引擎、优化器、数据索引存储、集群管理、以及事务管理等模块,作为领域专家负责对应模块问题的解决;同时也会根据新功能开发任务划分为一个个虚拟团队(或者叫做“部落”),每个虚拟团队以 2-5 人为主。
一般来说,一个典型的虚拟团队包括 2 位开发人员与 1 位测试工程师,极端情况下可以包含 3 位开发人员与 2 位测试工程师。如果一个功能模块需要超过 3 个工程师完成,则意味着该模块需要被进一步分解为更细的子任务。
该测试人员需要在功能的设计之初阶段即参与整个模块的设计讨论,并在前期对功能需求做出深入的了解。与功能设计同时,测试工程师必须尽早完成测试用例的设计,并在开发人员正式编码前通过测试用例评审。
测试用例的开发与代码开发几乎同时开始进行,理想情况下数据库程序代码开发完毕后测试用例代码需要已经准备好,并可以立刻开始进行功能性验证。在进行功能性验证的同时,该测试用例会被作为新的测试单元合并入集成测试框架,确保之后所有新的迭代不会影响该功能的正常运行。
具体来说,在测试流程方面,所有测试与开发人员均需要参与的例会包括:
-
Planning:确定目标产品功能 scope,作出工作量预估与安排,细化任务并作出 sizing;
-
Implementation:所有用例尽可能在测试开始前完成。实践中,开发人员阶段性完成开发任务,测试也可同步,尽早发现问题尽早在需要的情况下重新设计;
-
Retrospection:团队分析项目成功经验及问题和障碍。
每次功能开发完毕并合入主干后,该虚拟团队将会解散,所有成员则会被分配入其他的项目和模块中。在紧急情况下,一些骨干工程师可能会同时参与多个虚拟团队的开发或测试工作。
在团队协作方面,我们目前已经做到了跨地域、跨部门的协同,目前团队已经在六地跨国、跨地区办公,可以保证工作的高效。
自动化测试机制
1. 测试用例规划与管理
在测试的工作中,工具毕竟都只能作为辅助,而真正对产品质量进行保障的还是测试用例的完善程度。对于数据库这类紧耦合的基础软件来说,各种功能并发和顺序在不同的排列组合下可以说是天文数字般的场景,完全不可能做到 100% 全覆盖。因此,测试团队需要做的,是在有限的测试用例和测试时间内,尽可能做到对程序代码的全面覆盖。
测试团队需要针对每个功能进行 story 用例设计和实现,通过用例间的并发以及用例本身的并发,以及可靠性自动化用例构造断电、断网、集群中节点异常、磁盘空间满等各种随机故障来保障不同场景产品的质量。所有自动化用例对应的文本用例均使用 TestLink 统一管理,且用例按特性指定责任人按时维护跟踪。
2. 持续集成 CI
随着数据库系统越来越复杂,我们需要覆盖的测试场景与用例也越来越多。到目前为止,我们总共已经包含了近 2 万个不同的测试用例,单纯的自动化测试用例也已经超过了 1 万个,完整运行所有的自动化测试用例需要 3-4 小时,而覆盖全部自动化与手工测试用例(包括性能测试与混沌测试)则需要近 1 周的时间。
在这么多的测试用例中,不可能每次代码提交都要求运行一遍全部用例,这样只会让开发效率变得低下。因此,测试团队使用了多级测试保障的规范,将全部测试用例分为 5 个级别:
(1)提交构建 基线测试
该级别为最低测试级别,也叫做快速标准测试程序,所有研发人员在提交代码前必须手工运行并通过该测试,以达到最基本的稳定性需求。
该测试用例包直接坐落在程序的代码树中,开发人员可以在编译完成后直接调用脚本,运行该级别的测试程序。
快速标准测试程序大约包含 2800 个左右的简单测试用例,基本上能够覆盖大部分常用的数据库基本功能。开发人员每次提交代码后,测试框架在后台会同样运行一遍该快速标准测试程序,如果发现任何异常则意味着该开发人员没有按照要求运行相关测试用例,会被记以相应的违规警告。
(2)每日构建 集成测试
该级别为标准的回归测试项目,由我们的持续集成框架(CI)反复 24x7 地运行。该测试框架每天夜间 2 点自动根据当天最新提交的代码触发全编译,之后在大约 300 台虚拟机中反复 24x7 地运行近 2 万个测试用例。
这些测试用例远比快速标准测试用例复杂很多,除了最基本的功能操作以外,包含了大量的并发与混合操作业务逻辑,尽可能模拟真实客户现场的用户操作。实际上,我们很多集成测试用例设计就是来自于客户的真实操作环境。
我们的标准回归测试完全运行一次大约需要 4-5 小时。基本上早上工程师上班后能够第一时间看到夜间编译版本的运行结果。
(3)七天稳定性压力测试
回归测试只是保障程序不出现破坏已有功能的问题,但是一般来说很难针对内存泄露、性能下降、随机故障等问题进行检测。我们知道,一些随机问题并不会每次运行程序都出现,而是运行了一段时间后可能在某种特定场景和条件之下才会出现。因此,我们的第三级测试为七天稳定性压力测试。
在该测试下,巨杉数据库集群会在多台服务器中同时运行包括 TPCC、sysbench 以及模拟一些已知客户业务场景的压力测试程序。该测试的目的是尽可能将数据库的增删改查打满,同时在运行的过程中不断检测性能是否存在下降、进程的内存消耗是否不断增加,最后 168 小时后会出具汇总报告。
(4)多场景性能自动对比测试
测试级别 1-3 均为基准测试,测试结果为通过或不通过。但是软件不同版本之间毕竟代码做过修改,如果一个不注意很可能造成整体的性能下降。因此,我们的测试级别 4 为多场景下的性能自动对比测试。
在该测试中,我们会基于测试级别 3 的稳定性压力测试框架,使用最新版本与之前的次新版本在同样的硬件环境下运行同样的逻辑,运行 6 小时对比两者的性能。
一般来说,如果发现最新版本的性能与次新版本存在下降则会作为故障提交给研发分析,如果该性能下降达到 5%以上则会成为重大故障,极端情况下会中断版本的发布直到问题解决。
(5)故障注入与可靠性测试
测试级别 1-4 均为正常环境的测试,也就是所有的软件硬件环境均正确配置且不存在突发故障。但是我们知道,在真实的生产环境中,任何软硬件的故障都有可能发生,而作为数据库软件必须保障在任何故障发生后数据的不错不丢。
在该测试级别中会引入混沌测试与手工测试。测试工程师被要求以任意“有创意”的方式来“折腾”数据库,只要发现最后的数据造成了丢失或不一致,都会被认为是产品 bug 并成为重大故障报告给研发团队。
而混沌测试则更为极端。我们的混沌测试框架能够在操作系统和网络层面自动随机注入故障,例如磁盘 I/O 直接返回一个全空的数据页或错误码,或者网络中随机丢包或者字节跳变,用以验证数据库软件对于异常情况的处理能力。
与手工测试一样,混沌测试中产生的数据丢失或不一致均会以重大故障报告给研发团队,极端情况下可能造成版本发布的推迟。
可以看到,持续集成体系覆盖了从代码的提交、系统集成、长时间运行、版本间升级、以及第三方软硬件故障等场景。其中,除了测试级别 5 需要一定程度的手工运行外,其余所有测试场景均可以做到自动运行、检测结果、生成报告、并发出告警邮件。
3. 研发测试协作
一旦发现问题,测试团队需要第一时间将故障报告给研发团队对应的模块负责人。我们所有的测试用例均用一个负责人(团队),不管任何测试用例失败均会向该测试用例的负责人(团队)自动发送告警邮件,其中包括测试用例号以及对应的日志下载路径。同时,任何测试用例失败后其虚拟机将会被冻结,不会继续运行任何其他的测试用例,直到测试与研发人员在该环境重现问题并解锁该虚拟机。
测试用例负责人看到失败的用例或收到邮件后,会第一时间下载分析日志。如果发现该问题并不是测试用例本身编写错误导致,则会对比上一次正常运行的日志,并结合这段时间内所提交的代码更新进行简单的问题定位。
当故障被限定到某个具体某块后,测试用例负责人会通过 Jira 向研发团队开一个 ticket,根据测试用例重要性的不同标记严重级别。而研发人员在接收到 ticket 后会直接登录到被冻结的虚拟机上查看环境与日志,必要时可以重新运行测试脚本并打断点定位问题。
当研发人员修复问题并进行 code review 后,首先会在开发环境本地运行快速标准测试程序,完成后研发人员会针对问题所影响的测试用例单独运行,确保该修复真正解决了测试用例报告的问题。
本地测试流程通过后,开发人员则可以使用 git 来 commit 并 push 代码进入主干。代码进入主干后会自动触发提交构建程序,在后台虚拟机针对该 push 进行编译并在此运行快速标准测试程序,保障代码的最基本稳定性。
到了每天晚上 2 点,CI 系统会自动触发最新主干代码的全编译,大约 1 小时编译时间后会在 300 台测试虚拟机上运行 4-5 小时,在早上 8 点前完成所有测试用例的运行并产生结果报告。
工具列表
最后,我们简单罗列一下在进行自动化测试中所使用到的工具:
-
代码管理GitLab
-
流程管理Jira
-
文档管理Confluence
-
服务器资源管理自建系统
-
研发内部通讯 IMRTX
-
外部通讯 IMSkype
-
持续集成管理框架Jenkins
-
虚拟桌面Windows 虚拟机 Remote Desktop
-
虚拟机管理OpenStack VMWare
-
性能测试LoadRunner JMeter 独立测试工具
-
测试用例管理Testlink
-
异常注入libfiu
总结
本文主要分享了我们在自动化测试方面的实践。作为自研技术公司,公司成立以来,我们在研发体系、自动化测试、多地工作协调管理以及用户支持服务等方面,搭建了自己的完善体系,积累了丰富的经验。因此,我们在非常时期也将会保证提供给用户一如既往的服务和支持,保证我们的技术研发进度不受影响。
在新型冠状病毒引发的肺炎疫情形势严峻的今天,我们要求所有的员工尽可能在家办公保护好自己,同时也由于预先建设了相对完善的远程协作与自动化测试的机制,最大程度上减少了本次疫情对研发测试进度的影响。
文章分享的我们的研发和测试机制,希望也可以作为软件公司的参考,最终帮助到大家解决远程办公协作、研发测试管理的问题。
作者简介:
王涛,巨杉数据库联合创始人、CTO,曾是北美 IBM DB2 Lab 核心研发成员,负责 DB2 核心引擎研发,还曾参与世界第一款分布式数据库 DPF 的研发。有着超过十五年的数据库核心架构设计、研发和创新经验。作为巨杉数据库的总架构师和技术产品负责人,自 2011 年以来,在王涛的领导下,SequoiaDB 的技术团队从零开始自研分布式数据库,目前在在金融行业交易业务、数据中台等场景得到广泛应用。
,