MySQL自动测试框架介绍

1、概述

在我们給MySQL打了patch后,不仅需要测试新增的功能,同时更重要的问题是,需要对原有的功能作回归――若新增的patch导致原有其他功能产生bug,就得不偿失。

MySQL自动测试框架是一个以MySQL框架和内部引擎为测试对象的工具。主要执行脚本在发布路径的mysql-test目录下。自动测试框架的主要测试步骤,是通过执行一个case,将该case的输出结果,与标准的输出结果作diff。这里的“标准输出结果”指代在可信任的MySQL版本上的执行结果。

如果某个case的执行结果与标准输出结果不同,则说明正在执行的这个MySQL服务有问题,或许是框架,或许是引擎。 当然若干case执行正确并不能确保被测试的框架和引擎是没有问题的,除非能够证明执行的case已经覆盖了所有的分支(这太难了)。

这里说到的case,是指一系列的语句,包括SQL语句和一些必要的shell语句。在mysql-test/t/目录下,可以找到很多这样的case,他们的文件名以.test为后缀。接下来我们用一个简单的例子来说明用法。

 

2、初体验

       再简单的例子也不如自己写的简单。因此我们通过自己作一个case,来体验一下这个框架的便捷。

a)          在mysql-test/t/目录下创建文件 mytest.test, 内容为

  1 — source include/have_innodb.inc

 

  2 use test;

  3 create table t(c int) engine=InnoDB ;

  4 insert into t values(1);

  5 select c from t;

  6 drop table t;

       从第二行开始是我们熟悉的SQL语句,创建一个InnoDB表,插入一行,执行一个查询,删除这个表。输出也是显而易见的。

b)      在mysql-test/r/目录下创建文件 mytest.result, 内容为

  1 use test;

 

  2 create table t(c int) engine=InnoDB ;

  3 insert into t values(1);

  4 select c from t;

  5 c

  6 1

  7 drop table t;

 

c)      在mysql-test/ 目录下执行 ./mtr mytest

 

 

===================================================================

TEST                                      RESULT   TIME (ms)

————————————————————

worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 13000..13009

worker[1] mysql-test-run: WARNING: running this script as _root_ will cause some tests to be skipped

main.mytest                              [ skipped ]  No innodb support

main.mytest ‘innodb_plugin’              [ pass ]      5

————————————————————

The servers were restarted 0 times

Spent 0.005 of 3 seconds executing testcases

Completed: All 1 tests were successful.

最后一句话说明,测试通过了。

说明:

1)      mysql-test/mtr这个文件,是一个perl脚本。同目录下还有 mysql-test-run 和mysql-test-run.pl这两个文件,这三个文件一模一样。

2)      每个case会启动一个mysql服务,默认端口为13000。如果这个case涉及到需要启动多个服务(比如主从),则端口从13000递增。

3)      ./mtr的参数只需要指明测试case的前缀即可,如你看到的。当你执行./mtr testname会自动到t/目录下搜索 testname.test文件来执行。当然你也可以执行./mtr mytest.test, 效果相同。

4)      mytest.test第一行是必须的,当你需要使用InnoDB引擎的时候。可以看到mtr能够解释source语法,等效于将目标文件的内容全部拷贝到当前位置。Mysql-test/include目录下有很多这样的文件,他们提供了类似函数的功能,以简化每个case的代码。注意souce前面的 –, 大多数的非SQL语句都要求加 –。

5)      mytest.test最后一行是删除这个创建的表。因为每个case都要求不要受别的case影响,也不要影响别的case,因此自己在case中创建的表要删除。

6)      mtr会将mytest.test的执行结果与r/mytest.result作diff。 若完全相同,则表示测试结果正常。注意到我们例子中的mytest.result. 其中不仅包括了这个case的输出,也包括了输入的所有内容。实际上有效输出只有5、6两行。如果希望输出文件中只有执行结果,可以在第一行后面加入 — disable_query_log。

3、冲突结果及处理

              我们来测试一个错误的输入输出。就在上文的mytest.test中加入一行,如下:

  1 — source include/have_innodb.inc

 

  2 — disable_query_log

  3 use test;

  4 create table t(c int) engine=InnoDB ;

  5 insert into t values(1);

  6 select c from t;

  7 drop table t;

       执行 ./mtr mytest,我们知道,他只会输出两行,分别为c和1.

执行结果

。。。。。。

 

@@ -1,7 +1,2 @@

-use test;

-create table t(c int) engine=InnoDB ;

-insert into t values(1);

-select c from t;

 c

 1

-drop table t;

mysqltest: Result length mismatch

。。。。。。

Completed: Failed 1/1 tests, 0.00% were successful.

最后一句话说明我们的这个case测试没有通过。我们知道mtr将执行结果与r/mytest.result文件作diff,这个结果的前面部分就是diff的结果。

       说明:

1)      执行case失败有很多中可能,比如中间执行了某个非法的语句,这个例子中的失败,指代的是执行结果与预期结果不同。

2)      当前的执行结果会保存在r/mytest.reject中

3)      如果mytest.reject中的结果才是正确的结果(错入出现在mytest.result中),可以用mytest.reject将result覆盖掉,这样正确的标准测试case就完成了。可以直接使用 ./mtr mytest –record命令生成mytest.result.

4)      注意mtr在作diff的时候是直接文本比较,因此如果你的case中出现了多次执行结果可能不同的情况(比如时间相关),这不是一个好的case。当然处理的办法是有的,请参加附录中关于 replace_column的描述。

      4、批量执行的一些命令

实际上我们更常用到的是批量执行的命令。

1)      ./mtr

就是这么简单。会执行所有的case。当然包括刚刚我们加入的mytest.这里说的”所有的case”,包括t/目录下所有以.test为后缀的文件。也包括 suits目录下的所有以.test为后缀的文件。

注意只要任何一个case执行失败(包括内部执行失败和与result校验失败)都会导致整个执行计划退出。因此–force很常用,加入这个参数后,mtr会忽略错误并继续执行下一个case直到所有的case执行结束。

2)      ./mtr –suite=funcs_1

Suits目录下有多个目录,是一些测试的套餐。此命令单独执行 suits/funcs_1目录下的所有case。(其他目录不执行)

t/目录下的所有文件组成了默认的套餐main。 因此 ./mtr –suite=main则只执行t/*.test.

3)      ./mtr  –do-test=events

执行所有以 events为前缀的case(搜索范围为t/和所有的suite)。

–do-test的参数支持正则表达式,上诉命令等效于./mtr –do-test=events.*

所以如果想测试所有的包括innodb的case,可以用 ./mtr –do-test=.*innodb.*

5、结束了

好吧。上面说的一些太简单了,简单到入门都不够。需要详细了解的可以到官网看e文。以下的tips是看官网的一些笔记。看到一点记录一点的,不成章。

附录

1、目录下的mtr文件即为mysql-test-run的缩写,文件内容相同

 

2、Mtr会启动mysql,有些case下可能重启server,为了使用不同的参数启动

3、调用bin/mysqltest读case并发送給mysql-server

4、输入和输出分别放在不同的文件中,执行结果与输出文件内容作对比

5、输入文件都在t目录下,输出文件在r目录下。对应的输入输出文件仅后缀名不同,分别为 *.test 和 *.result

6、每个testfile是一个测试用例,多个测试用例之间可能有关联。 一个file中任何一个非预期的失败都会导致整个test停止(使用force参数则可继续执行)。

7、注意如果服务端输出了未过滤的warning或error,则会也会导致test退出。

8、t目录下的*.opt文件是指在这个测试中,mysql必须以opt文件的内容作为测试参数启动。 *.sh文件是在执行启动mysql-server之前必须提前执行的脚本。disabled.def中定义了不执行的testfile。

9、r目录下, 若一个执行输出结果和testname.result文件不同,会生成一个testname.reject文件。 该文件在下次执行成功之后被删除。

10、            include目录是一些头文件,这些文件在t/*.test文件中使用,用source 命令引入

11、            lib目录是一些库函数,被mtr脚本调用

12、            有些测试需要用到一些标准数据,存在std_data目录下。

13、            Suite目录也是一些测试用例,每个目录下包含一套,./mtr –suite=funcs_1执行suits/funcs_1目录下的所有case

14、            Mtr实际调用mysqltest作测试。 –result-file文件用于指定预定义的输出,用于与实际输出作对比。若同时指定了 –recored参数,则表示这个输出数据不是用来对比的,而是要求将这个输出结果写入到指定的这个文件中。

15、            Mtr所在的目录路径中不能有空格

16、            Mtr  –force参数会跳过某个错误继续执行,以查看所有的错误。

17、            执行./mtr时另外启动了一个mysql server,默认端口13000

18、            指定执行某个具体case使用 ./mtr testname, 会自动使用t/testname.rest

19、            ./mtr  –do-test=events 执行以events开头的所有case,包括events_grant.test 等

   同理 –skip-test=events 将以events打头的所有case跳过。 这里支持正则表达是,如./mtr –do-test=.*innodb.*则会执行t/目录下所有包含innodb子串的case

20、            Mtr允许并行执行,端口会从13000开始使用。但需要特别指定不同的—vardir指定不同的日志目录。但并行执行的case可能导致写同一个testname.reject. 

21、            使用–parallel=auto可以多线程执行case。

22、            Mtr对比结果使用简单的diff,因此自己编写的测试case不应该因为执行时间不同而导致结果不同。当然框架在执行diff之前,允许自定义处理规则对得到的result作处理,来应对一些变化。

23、            ./mtr –record test_name 会将输出结果存入文件 r/test_name.result

24、            自己在脚本中创建的库、表等信息,要删除,否则会出warnning

25、            Mtr默认使用的是mysql-test/var/my.cnf文件,需要替换该文件为自定义的配置文件

26、            若要使用innodb引擎,必须明确在testname.test文件头加

– source include/have_innodb.inc

27、            Test文件名由字母数字、下划线、中划线组成,但只能以字母数字打头

28、            — sleep 10 等待10s 注意前面的—和后面没有分号

29、            默认情况下, r/testname.result中会包含原语句和执行结果,若不想输出原语句,需要自t/restname.test文件头使用 — disable_query_log

30、            每个单独的case会重启服务并要求之前的数据是清空的。

31、            如果要测试出错语句,必须在testname.test文件中,在会出错的语句之前加入 –error 错误号。

比如重复创建表,语句如下

create table t(c int) engine=InnoDB ;

– error 1050

create table t(c int) engine=InnoDB ;

这样在testname.result中输出

create table t(c int) engine=InnoDB ;

  ERROR 42S01: Table ‘t’ already exists

则能够正常通过

也可使用 ER_TABLE_EXISTS_TABLE (宏定义为1050)

也可使用 –error S42S01 (注意需要加前缀S),但S系列的可能一个错误号对应多种错误。

32、            –enable_info 在testname.test文件头增加这个命令,在结果中会多输出影响行数。

    对应的关闭命令为 –disable_info

33、            enable_metadata 可以显示更多信息 disable_result_log不输出执行结果

34、            有些case的输出结果可能包含时间因素的影响,导致无法重复验证。–replace_column 可以解决部分情况。

–replace_column 1 XXXXX

Select a, b from t;

输出结果会是

XXXXX     b.value

即将第一列固定替换为xxxxx。 注意,每个replace_column的影响范围仅局限于下一行的第一个select语句。

35、            mtr –mysqld=–skip-innodb –mysqld=–key_buffer_size=16384 用这种将参数启动传递給mysql server 。 每个选项必须有一个—mysqld打头,不能连在一起写,即使引号包含多个也不行。

36、            mysql-test-run.pl –combination=–skip-innodb   –combination=–innodb,–innodb-file-per-table

这个命令是参数传给多个test case, 第一个参数传 skip-innodb, 第二个参数传 –innodb, innodb-file-per-table。  若所有启动参数中combination只出现一次,则无效。

37、            skip-core-file 强行控制server不要core

38、            如果需要在server启动前执行一些脚本,可以写在 t/testname.sh文件中,由mtr自动执行。

39、            等待语句

let $wait_condition= SELECT c = 3 FROM t;

–source include/wait_condition.inc

              Mtr会一直停在 source这行,每隔0.1s检测,直到上个语句中的$wait_condition返回值非0

40、            主从测试case

                  a)        testname.test头部必须包含 souce include/master-slave.inc

                  b)        主库的配置写在testname-master.opt, 从库的写在testname-slave.opt

                  c)        对出从库的操作统一写在testname.test中,要对主库操作时,先执行connection master,之后的语句都是在主库上操作;同理connection slave;

从库上执行start slave之后要执行 –source include/wait_for_slave_to_start.inc 等待启动完成, 执行stop slave之后要执行–source include/wait_for_slave_to_stop.inc 等待停止完成。

41、            Case完成后,mtr会检测server的错误日志,如果里面包含Error或Warning,则会认为case fail。

                 a)        如果要忽略整个验证server日志的过程,可以在文件头增加 –nowarnings

                 b)        如果要指定忽略某些行,允许使用正则表达式,比如 call mtr.add_suppression(“The table ‘t[0-9]*’ is full”); 能够忽略 The table ‘t12′ is full 这样的warning

                 c)        注意上面这个call语句也是输入语句的一部分,因此会输出到结果内容中,除非

–disable_query_log

call mtr.add_suppression(“The table ‘t[0-9]*’ is full”);

–enable_query_log

42、            在一个case中重启server

–exec echo “wait” > $MYSQL_TMP_DIR/mysqld.1.expect

–shutdown_server 10

–source include/wait_until_disconnected.inc

# Do something while server is down

–enable_reconnect

–exec echo “restart” > $MYSQL_TMP_DIR/mysqld.1.expect

–source include/wait_until_connected_again.inc

43、            循环语句语法

let $1= 1000;

while ($1)

{

 # execute your statements here

 dec $1;

}

44、            mysql_client_test是一个单独的case,里面包含了多个case, 但并不是写成脚本,而是直接调用,可以直接从源码中看到里面调用的各个语句。源码位置tests/mysql_client_test.c

45、            直接执行 ./mtr 会执行t/目录下的所有case,外加suits目录

46、            若在不同目录中有重名的case,则会依次全部执行

47、            Mysql-stress-test.pl用于压力测试,注意默认的my.cnf中的参数,比如innodb_buffer_pool_size只有128M

48、            Case中的语句是以分号结尾的。echo a; select 1 from t limit 1; echo b;是三个语句,在result文件中的对应输出是  a \n 1 \n b

49、            Testcase中支持的脚本语言函数
http://dev.mysql.com/doc/mysqltest/2.0/en/mysqltest-commands.html

没有列出的函数可以用 – exec +shell命令实现

50、            设置变量 let $a = xx, 前面可加 –

51、            若是数字,可使用 inc $a / dec $a, 前面可加 –

52、            可以赋值为sql返回值 let $q = `select c from t limit 1`,
    可以赋值为系统变量 let $q = $PATH

 

 

时间: 2024-08-01 20:45:12

MySQL自动测试框架介绍的相关文章

基于Openstack的Tempest测试框架介绍

本文简要分析了 Tempest 的工作原理及其关键技术,并详细地介绍了如何实现 Tempest 配置与运行,最终结合实际的项目需求展示了如何对 Tempest 进行扩展.您可以通过本文了解 OpenStack Tempest,并进行合理地应用. OpenStack(OS)是由网络主机服务商 Rackspace 和美国宇航局联合推出的一个开源项目,于 2010 年 7 月 18 日正式启动,迄今为止已经得到二百多家公司的支持,其中包括很多大型企业,如 IBM,惠普.戴尔.红帽和 Canonical

WF4.0实战(五):实现一个直观易扩展的自动测试框架

概述: 这篇文章用WF实现一个软件自动测试框架,这个框架你可以随意扩展.本这个框架根据WF流程去自动地点击你的页面:自动的在你的文 本上输入值:自动的做一些人为的操作.也就是说WF相当于一个测试用户,自动地帮你测试软件.只需要你定制测试流程. 写一个待测试的软件: 这里我写了一个很简单的待测试的软件:一个加法运算.界面如下图,就一个Form. 后台代码如下: 1 public partial class MainForm : Form 2 { 3 public MainForm() 4 { 5

基于JUnit的InstallAnywhere安装程序图形界面自动测试框架

JUnit 简介 JUnit 是一个开源的单元测试框架,用于编写和运行自动测试,由 Erich Gamma 和 Kent Beck 在 1997 年开发完成.它包括以下特性: 提供的 API 可以让你写出测试结果明确的可重用单元测试用例: 提供了三种方式来显示你的测试结果,而且还可以扩展: 提供了单元测试用例成批运行的功能: 超轻量级而且使用简单,没有商业性的欺骗和无用的向导: 整个框架设计良好,易扩展. InstallAnywhere 简介 InstallAnywhere(下文简称 IA)是一

ios app 自动测试框架

问题描述 ios app 自动测试框架 我现在通过命令行在越狱后的手机上可以安装网上下载的ipa文件 我现在需要模拟运行这些安装好的app,需要 1.启动运行app 2.模拟操作 3.退出应用 我该需要使用什么框架或者工具能够实现啊 我在网上找到的好多都是需要自已的app源码的 没有别的方法了嘛? 求各位大大帮帮忙 解决方案 很高深的样子 mark一下

obotium测试框架-在使用Robotium自动测试框架中遇到问题,求大神解答

问题描述 在使用Robotium自动测试框架中遇到问题,求大神解答 我测试一个Activity,想点击最下方id为video_iv的imageview,代码如下: @Before protected void setUp() throws Exception { super.setUp(); this.solo = new Solo( this.getInstrumentation(), this.getActivity() ); } @After protected void tearDown

Openstack测试框架Tempest介绍

Tempest是Openstack的集成测试框架,它的实现基于python的unittest2测试框架和nose测试框架.Tempest对Openstack终端发起一系列API请求,并且对终端的响应进行验证.Tempest通过config文件来描述整个测试环境,包括compute API端点,Keystone server以及Glance server安装的镜像的UUID等信息.以下是Tempest的目录结构: Tempest的优点 1.Tempest可以自动寻找,执行测试:自动查找当前目录下所

《高度安全环境下的高级渗透测试》—第1章1.7节Dradis框架介绍

1.7 Dradis框架介绍Dradis框架是一个Rails应用程序,它可以用于管理在渗透测试时出现的数据过载情况.Dradis基于Web的用户界面体验良好,它简化了渗透测试周期的数据收集过程,并且能够将数据方便地分享给团队其他成员. 在结合不同的数据源,例如Nmap.Nessus,甚至Metasploit时,你通常需要构造某种数据库,然后使用各种方法管理导入的数据.Dradis可以让你单击几下鼠标,就能通过插件导入这些数据.Dradis也允许你上传附件(例如截图),或将你自己的注释添加至数据库

《精通移动App测试实战:技术、工具和案例》一第2章 JUnit框架基础2.1 JUnit框架介绍

第2章 JUnit框架基础 精通移动App测试实战:技术.工具和案例 2.1 JUnit框架介绍 瀑布模型是最早出现的软件开发模型,如图2-1所示.该开发模型可以说在软件工程中占有重要的地位,它提供了软件开发的基本框架.其过程是从上一项活动接收该项活动的工作对象作为输入,利用这一输入实施该项活动应完成的内容,给出该项活动的工作成果,并作为输出传给下一项活动.同时评审该项活动的实施,若确认,则继续下一项活动:否则返回前面,甚至更前面的活动.对于经常变化的项目而言,瀑布模型毫无价值.然而,时至今日,

iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角)

图像: 1.图片浏览控件MWPhotoBrowser        实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存.可对图片进行缩放等操作.       下载:https://github.com/mwaterfall/MWPhotoBrowser   目前比较活跃的社区仍旧是Github,除此以外也有一些不错的库散落在Google Code.SourceForge等地方.由于Github社区太过主流,这里主要介绍一下Gith