介绍
MySQL Test Run 简称MTR,是MySQL官方提供的自动化测试框架,执行脚本在发布路径的mysql-test目录下。
主要测试步骤,是通过执行一个case(*.test)中的语句(包括sql语句和其他管理语句),将case的输出记录保存在结果文件(*.result)中,或者是将语句执行结果与标准的输出结果作diff,如果出现偏差就会报错。
MySQL自动化框架包括一组测试用例和用于运行它们的程序:perl 脚本(mysql-test-run.pl)和 c++ 二进制(mysqltest)。
- perl 脚本:负责控制流程,包括启停、识别执行哪些用例、创建文件夹、收集结果等操作。
- mysqltest:负责执行测试用例,包括读文件,解析特定语法,执行用例。
安装
- 安装依赖包
本次安装环境是CentOS 8.5
yum -y install perl* -y
- 下载安装包并解压
本文采用的MySQL版本是8.0.28,可根据需要自行选择版本。
cd /home/wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-test-8.0.28-linux-glibc2.12-x86_64.tar.xztar -xvf mysql-test-8.0.28-linux-glibc2.12-x86_64.tar.xzmv mysql-8.0.28-linux-glibc2.12-x86_64 mysql_mtr_8.0.28cd /home/mysql_mtr_8.0.28/cp -r /path-to-db/* /home/mysql_mtr_8.0.28/ #将mysql安装包目录下的文件与mtr目录合并cd /home/mysql_mtr_8.0.28/mysql-test #进入mtr目录
也可通过下载源码包进行编译安装,本次暂不做介绍 。
主要目录介绍
include
包含.inc文件,用于测试开始时判断是否满足测试条件,在测试用例中通过source命令引入,就像C/C++的头文件,在mtr的体系中,我们可以将许多可重复利用的测试语句,提取到*.inc文件中,放到对应的include目录中,以便在*.test中直接调用。
suite
包含所有测试suite,每一个suite为一个测试用例集,一般地,我们将若干个测试功能点同属于一个功能模块的testcase放在一个大目录下,这个包含了t和r目录的大目录被称为一个testsuite。其中a.test文件会放在t目录,而a.result放在r目录。
测试示例
我们通过一个最简单的例子来说明这个框架是怎么使用的。
创建测试用例
在 mysql-test/t 目录下创建一个文件名为 mytest.test的测试用例:
# vi mytest.test--disable_warningsDROP TABLE IF EXISTS t1;SET @@sql_mode='NO_ENGINE_SUBSTITUTION';--enable_warningsSET SQL_WARNINGS=1;CREATE TABLE t1 (a INT);INSERT INTO t1 VALUES (1);INSERT INTO t1 VALUES (2);DROP TABLE t1;
执行并查看结果
# ./mtr --record mytest.testLogging: ./mtr mytest.testMySQL Version 8.0.28Checking supported features... - SSL connections supportedCollecting tests...Checking leftover processes...Removing old var directory...Creating var directory '/usr/local/mysql/mysql-test/var'...Installing system database...Using parallel: 1==============================================================================TEST RESULT TIME (ms) or COMMENT--------------------------------------------------------------------------worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 13000..13009worker[1] mysql-test-run: WARNING: running this script as _root_ will cause some tests to be skipped[100%] main.mytest [ pass ] 12--------------------------------------------------------------------------The servers were restarted 0 timesSpent 0.012 of 4 seconds executing testcasesCompleted: All 1 tests were successful.
看到successful说明执行成功。
执行说明
1. mysql-test/mtr这个文件,是一个perl脚本。同目录下还有 mysql-test-run 和mysql-test-run.pl,这三个文件是一模一样的; 2. 执行case时会自动启动一个mysql服务,默认端口为13000。如果这个case涉及到需要启动多个服务(比如主从),则端口从13000递增; 3. ./mtr的参数只需要指明测试case的前缀即可,当你执行./mtr mytest会自动到t/目录下搜索 mytest.test文件来执行,也可以输入完整的测试例名称如./mtr mytest.test。 如果要执行某个功能模块的所有测试用例,可以在suite目录下创建一个大目录如spTest然后再分别创建t和r目录,执行该目录的测试例可以写成:./mtr spTest.mytest; 4. mytest.test最后一行是删除这个创建的表。因为每个case都要求不要受别的case影响,也不要影响别的case,因此自己在case中创建的表要删除; 5.第一次执行建议加上参数--record,执行完会在对应的r目录下生成mytest.result;mtr会将mytest.test的执行结果与r/mytest.result作diff。 若完全相同,则表示测试结果正常(如果需要和往期测试结果做对比,需要在r目录下先提供一份xx.result文件); 6.MTR提供了一套测试用例,如果不带任何参数直接执行./mtr,会运行t目录下的的所有case,包括上面刚新增的用例。
mtr 其他常用参数介绍
--force
默认情况下,只要遇到一个用例出错,测试程序就会退出,加入该参数后,mtr会忽略错误并继续执行下一个case直到所有case执行结束再退出(但如果脚本存在太多错误还是会退出);
--record
是否记录results结果,首次执行建议带上,让其自动生成.results文件再修改成我们预期的结果文件;
若一个执行输出结果和testname.result文件不同,会生成一个testname.reject文件,该文件在下次执行成功之后被删除;检查reject文件的内容,如果里面是期望的输出,则将内容拷贝到.result文件中,作为以后判断运行结果是否通过的依据;
--big-test
执行标记为big的测试用例,因为用例较大、耗时较长,标记为big的用例默认不会执行,输入两遍big-test则只执行标记为big的测试用例;
--suite=[dirname]
批量执行指定测试目录下的所有测试例,有时候我们要执行一套xx.test文件,这样可以在执行的时候指定套件名称。
- 连接远程的数据库进行mtr执行:
#./mtr --extern host=192.168.6.1 --extern port=3306 --extern user=root --extern password='123456' --record --force example.1
--extern:一般情况下mtr是启动自己的MySQL服务来进行测试,如果在启动时指定参数—extern,则可以使用指定的MySQL服务进行测试;host | port :远程服务器地址 | 端口;user | password: 对应数据库的用户名 | 密码;
测试用例编写的规范
- 尽可能避免每行超过80个字符 ;
- 用#开头,作为注释;
- 缩进使用空格,避免使用tab;
- SQL 语句使用相同的风格,包括关键字大写,其它变量、表名、列名等小写;
- 增加合适的注释。特别是文件的开头,注释出测试的目的、可能的引用或者修复的bug编号;
- 为了避免可能的冲突,习惯上表命名使用 t1、t2...视图命名使用v1、v2...;
case运行失败的原因
- 用例文件中的sql可能不合法;
- 产生的结果文件与期望文件diff结果不一致;
- 具体错误原因可以通过查看执行时的输出日志进行排查修改;
处理预期错误
在期望有返回错误的语句前面使用error指令,例如创建一个已经存在的表名时,可以使用以下任一种方式:
--error 1050--error ER_TABLE_EXISTS_ERROR其中数字对应错误码,ER_TABLE_EXISTS_ERROR对应错误的逻辑名。这样在mysqltest运行后,会将返回的错误信息一起写入结果文件,这些错误信息就作为期望结果的一部分了。
也可以使用SQLSTATE来指示期望有错误返回,例如与MySQL错误码1050关联的SQLSTATE值是42S01,使用下面的方式,注意编码增加了S前缀:
--error S42S01在指令error后面是可以加入多个错误码作为参数的,使用逗号分隔即可;.
错误码及逻辑值的对应关系参考MySQL安装包include目录下的mysqld_error.h 和sql_state.h
- MTR其他详细用法可以参考官网:官方文档 https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_MYSQL_TEST_RUN.html
Enjoy GreatSQL 🙂