采用开源测试框架进行分布式数据库自动化测试

摘要

中兴GoldenDB分布式数据库项目是在单机开源数据库MariaDB基础上构建的分布式数据库集群,旨在解决单机数据库的容量及处理能力无法满足当今数据量越来越大、业务并发度越来越高的问题。GoldenDB分布式数据库具备关系型数据库的ACID特性,用户业务从单机数据库切换至分布式数据库无感知,作为数据库产品最基本最核心的功能就是对数据库表的管理以及对SQL功能的支持,这部分功能对应的用例占据了整个分布式数据库测试用例的70%。而恰巧这部分功能的测试是最有可能实现自动化回归的。如何有效的组织实现SQL功能的自动化回归测试便成了GoldenDB分布式数据库系统测试的一个重要问题。

问题的提出

中兴GoldenDB数据库项目立项之初就意识到SQL功能实现自动化对功能回归的重要意义,因此从项目开始就对SQL部分功能的测试都进行了自动化。SQL功能的测试基本都是通过SQL语句进行的,SQL语句都是可以整理成脚本执行的,因此这部分的自动化比较容易实现。建库建表、预置数据、增删改查等库表操作均可以写进sql脚本,再对脚本按照需要进行编排,配合Shell脚本进行调用,即可完成sql功能的自动化测试。有点麻烦的就是执行结果的校验,这个问题我们是通过重定向上个版本的执行结果到一个结果文件,保存该文件,下个版本回归时,将本版本执行结果文件与上个版本结果文件进行比对来完成结果校验。由于结果文件都是文本格式的,使用的比较工具也比较多,Beyond Compare、Merge都能方便的胜任。

随着GoldenDB项目的不断发展,自动化测试用例越积越多,截至今年7月份统计的数据显示,脚本数量有278个文件,总大小有22M,代码行数超过23万行。回归这些脚本变得越来越繁琐,也越来越耗时。具体体现在:

1、脚本繁多,有些脚本之间有依赖关系,单纯回归执行这些脚本执行时间大约需要2小时。

2、脚本执行完毕结果的比对工作量更大,大约需要1.5人天,使用比较工具只能针对每个结果文件进行比对,具体的差异需要人工识别,且无统计信息。

3、发现问题定位故障比较困难,无法直接输出故障脚本和位置,也需要人工识别。

综上当回归脚本数量越来越多时,这种自动化回归方式效率逐渐变低,急需一种更快捷的自动化回归方式。

解决思路

现有的自动化回归方式在回归脚本比较少,脚本逻辑比较简单的情况下,还是非常有效的,实现也比较容易,面对数量越来越多逻辑复杂度越来越大的大量脚本,急需引入工具解决。具体采用何种工具呢?

我们首先想到的是开发IT阶段使用的RT工具,经过深入研究,发现使用RT工具可以方便的调用和执行sql脚本,但是结果的比对需要另外开发工具进行。也可以使用RT直接开发用例,对结果进行参数化通过代码方式进行结果的校验,但是这样一来增加的代码工作量太大。

接下来,我们想到了mysql以及mariadb这些开源单机数据是如何进行自动化回归的?于是找到了mysqltest这个Mysql/MariaDB开源自动化测试回归工具。Mysqltest的主要测试原理是通过执行一个case,将该case的输出结果,与标准的输出结果作diff。这里的“标准输出结果”指代在可信任的MySQL版本上的 执行结果。如果某个case的执行结果与标准输出结果不同,则说明正在执行的这个MySQL服务有问题,或许是框架,或许是引擎。 当然若干case执行正确并不能确保被测试的框架和引擎是没有问题的,除非能够证明执行的case已经覆盖了所有的分支(这太难了)。这里说到的case,是指一系列的语句,包括SQL语句和一些必要的shell语句。在mysql-test/t/目录下,可以找到很多这样的case,他们的文件名以.test为后缀。

Mysqltest可以很方便的回归升级后的mysql版本功能,那是不是也同样适用于回归我们的分布式数据库GoldenDB呢?

实践情况

1、安装方法

Mysqltest存在于mariadb开源版本中,通过mysql协议对接Mysql/MariaDB数据库进行回归测试的。由于都是标准的mysql接口协议,与GoldenDB的proxy中间件对接简单,安装部署有两种方法:

方法一:独立安装,把mariadb开源版本安装在$HOME下即可,推荐此办法。

方法二:安装在proxy目录下,拷贝mysql-test目录到proxy主目录下,拷贝mariadb原始的bin目录下的文件到proxy的bin目录下,拷贝mariadb原始的share目录下的charsets目录到proxy的share目录下。

2、新增测试用例目录

创建新的测试目录需要修改代码,修改mysql-test-run.pl,在$HOME/mysql-test/suite下创建目录如sql目录,该目录名添加到下面代码的最下一行,并加上“-”。然后再在该目录下创建t和r目录

my @DEFAULT_SUITES= qw(

main-

archive-

binlog-

csv-

federated-

funcs_1-

funcs_2-

handler-

heap-

innodb-

innodb_fts-

innodb_zip-

maria-

multi_source-

optimizer_unfixed_bugs-

parts-

percona-

perfschema-

plugins-

roles-

rpl-

sys_vars-

unit-

vcol-

sql-

);

3、新增测试用例

(1) 进入相应功能模块的t目录下

(2) 新增测试用例文件,并以.test为后缀名,例如:testcase_name.test

(3) 在测试用例文件中撰写相应的测试语句,完成后保存

(4) 进入$HOME/ mysql-test目录,执行perl mysql-test-run.pl <testcase_name>命令,并查看生成的结果文件

(5) 若结果文件正常,即可将结果文件保存到此功能模块的r目录下,并改名为test_name.result

4、运行单个测试用例

(1) cd $HOME/ mysql-test

(2) 执行perl mysql -test-run.pl <testcase_name>。可到相应模块目录下的t目录下,查看以.test结尾的文件,这些文件名去掉后缀即为测试用例名称。其中main模块的测试用例在$HOME/ mysql -test/t目录下

例一:perl mysql-test-run.pl profiling

5、运行所有测试用例

(1) cd $HOME/mysql-test

(2) 执行perl mysql-test-run.pl

(3) 不想执行某个模块perl mysql-test-run.pl --skip-ndbcluster

6、运行某个模块的测试用例

(1) cd $HOME/mysql-test

(2) 执行perl mysql-test-run.pl –suite=<module_name> ,$HOME/mysql-test/suite下的目录名即为模块名(main模块不在此目录下)。

例一:perl mysql-test-run.pl -suite=main

例二:perl mysql-test-run.pl -suite=auth_sec

7、注释某个测试用例

(1) 到该测试用例的所在的t目录下

(2) 修改disabled.def文件,在里面增加要注释的测试用例。格式如下:

testcase_name : reason

8、连接远端proxy进行回归测试

./mysql-test-run.pl --extern host=19*.16*.1*.21* --extern port=2*** --extern user=dba --extern password=**** -suite=sql

9、回归测试结果的解读:

采用开源测试框架进行分布式数据库自动化测试

上图展示的是测试用例执行全部成功后的报告信息,从图中可以看出proxy10107用例包中的7个脚本用例全部执行pass,并且分别列出了每个用例脚本的执行时间,单位ms。

采用开源测试框架进行分布式数据库自动化测试

上图展示的是测试用例执行有失败的报告信息,从图中可以看出proxy10105用例包中的3个脚本用例有两个执行pass,一个fail,fail的脚本名称是proxy10105.selectlist_zhuanxiang,其对应的标准结果文件和本次执行结果文件的名称及路径分别为:

--- /home/mysqltest/mysql-test/suite/proxy10105/r/selectlist_zhuanxiang.result 2016-09-06 10:56:23.688118311 +0800

+++ /home/mysqltest/mysql-test/suite/proxy10105/r/selectlist_zhuanxiang.reject 2016-09-06 15:19:45.121441364 +0800。

错误的位置为:@@ -559,12 +559,16 @@,表明标准结果文件的559行开始的12行与本次执行结果文件的559行开始的16行存在差异,接下来打出了具体的差异情况,如图所示,图中最下面两个红色圈圈对应的行前的+号表明是本次执行结果多出的内容,如果前面是-号,则表示是缺少的内容,如果前面什么都不带,则说明该行内容是相同的。

10、mysqltest重点参数说明

--dry-run 只打印要执行的用例名,不执行

--force 当只写一个--force命令时,某一个测试用例出现一个fail,则中断该用例的执行,继续执行下一个用例;若连写两个--force,执行不中断,错误的部分会打印mysqltest:

--do-test=XXX 只执行前缀或全名是XXX的用例

--skip-test=XXX 跳过前缀或全名是XXX的用例执行,执行结果显示为skipped,支持正则表达式

--start-from=XXX 从前缀是XXX用例开始执行

--suite[s]=NAME1,..,NAMEN 执行suites用例集

--enable-disabled 标注成disabled用例也执行

--record TESTNAME 生成XXX.test的XXX.result结果

--extern 连接其他库时,使用每一个参数前必须嵌套该参数,该参数后面只能跟一个连接参数

效果评价

Mysqltest自动化测试框架逻辑原理简单,安装部署方便,优势特别体现在回归结果的判定上,执行效率也很高。目前GoldenDB测试组已经在进行已有自动化脚本往mysqltest框架下的迁移,效率提升明显,具体体现在:

1、之前方式执行一次回归大约需要2个小时的脚本,目前只需要30分钟。

2、之前脚本回归完毕结果的比对确认大约需要1.5人天,目前不需要花费额外的精力,这部分工作mysqltest框架自动完成了,且能清晰准确的定位到具体的问题语句以及标准执行结果和当前版本执行结果。

3、Mysqltest自动化测试框架能够输出固定格式的测试报告,通过解析该报告可以方便的生成CIC需要的报告模板,使得系统测试自动化执行结果能够方便的上报CIC系统,如下图所示。

采用开源测试框架进行分布式数据库自动化测试

推广建议

实践证明mysqltest自动化测试框架可以方便的应用于GoldenDB项目的系统测试回归,大大提高回归执行效率,特别是问题的定位,除此之外,该自动化框架也可应用于如下场景:

1、GoldenDB项目的集成测试阶段。

2、支持mysql协议的如Mysql、MariaDB、NDB等相关系列版本的数据库产品的功能回归测试。

相关推荐