存储过程测试流程--以MySQL为例

同C/C++/Java等语言编写的代码一样,用SQL语言编写的存储过程也需要进行充分的测试。本文以实际的MySQL存储过程为例,介绍存储过程测试的整个流程。

在本文中,需要被测试的存储过程如下:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30),
    out   p_result       int,
    out   p_outusertype  int
)
pr_dealtestnum_label:begin
    declare   p_boxnumcount    int;
    declare   p_usertype       int;

    set p_boxnumcount = 0;
    set p_usertype     = 0;
    set p_outusertype  = 0;

    select count(*) into p_boxnumcount from tb_testnum where boxnumber=p_boxnumber;
    if p_boxnumcount > 0 then
    begin
        select usertype into p_usertype from tb_testnum where boxnumber=p_boxnumber;

        set p_outusertype =  (p_usertype+1)/10*10;

        set p_result = 0;
    end;
    else
    begin
        set p_result = 1;
    end;
    end if;

    leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procedure pr_dealtestnum ok';

在存储过程中使用到的表tb_testnum如下:

drop table if exists tb_testnum;

create table tb_testnum
(
    boxnumber  varchar(30)  not null,
    usertype   int          not null
);
create unique index idx1_tb_testnum on tb_testnum(boxnumber);

其中,usertype字段的值必须要大于1。

对存储过程进行测试大致遵循以下步骤:
第一步,按照存储过程的输入和输出参数设置正确的调用样式。

第二步,根据调用时的输入参数值来向相关的表中插入测试数据。

第三步,执行第一步中的存储过程调用语句,查看执行结果是否正确,并根据该结果来修改存储过程。

下面具体进行说明。

第一步
就本存储过程pr_dealtestnum而言,根据程序逻辑,我们可设置如下调用语句:

call pr_dealtestnum('2344273520',@1,@2);select @1,@2;
call pr_dealtestnum('2344273521',@1,@2);select @1,@2;
call pr_dealtestnum('2344273522',@1,@2);select @1,@2;
call pr_dealtestnum('2344273523',@1,@2);select @1,@2;
call pr_dealtestnum('2344273524',@1,@2);select @1,@2;
call pr_dealtestnum('2344273525',@1,@2);select @1,@2;
call pr_dealtestnum('2344273526',@1,@2);select @1,@2;
call pr_dealtestnum('2344273527',@1,@2);select @1,@2;
call pr_dealtestnum('2344273528',@1,@2);select @1,@2;
call pr_dealtestnum('2344273529',@1,@2);select @1,@2;
call pr_dealtestnum('2344273530',@1,@2);select @1,@2;
call pr_dealtestnum('2344273531',@1,@2);select @1,@2;
call pr_dealtestnum('2344273532',@1,@2);select @1,@2;
call pr_dealtestnum('2344273533',@1,@2);select @1,@2;
call pr_dealtestnum('2344273534',@1,@2);select @1,@2;
call pr_dealtestnum('15696192523',@1,@2);select @1,@2;

大家还可以设置更多的调用语句,其目的是为了对存储过程进行更加充分的测试。

第二步
根据第一步设置的调用语句,兼顾程序逻辑,我们可执行如下语句向表tb_testnum中插入数据:

insert into tb_testnum(boxnumber,usertype) values('2344273520',1);
insert into tb_testnum(boxnumber,usertype) values('2344273521',3);
insert into tb_testnum(boxnumber,usertype) values('2344273522',4);
insert into tb_testnum(boxnumber,usertype) values('2344273523',5);
insert into tb_testnum(boxnumber,usertype) values('2344273524',7);
insert into tb_testnum(boxnumber,usertype) values('2344273525',8);
insert into tb_testnum(boxnumber,usertype) values('2344273526',9);
insert into tb_testnum(boxnumber,usertype) values('2344273527',10);
insert into tb_testnum(boxnumber,usertype) values('2344273528',11);
insert into tb_testnum(boxnumber,usertype) values('2344273529',13);
insert into tb_testnum(boxnumber,usertype) values('2344273530',14);
insert into tb_testnum(boxnumber,usertype) values('2344273531',15);
insert into tb_testnum(boxnumber,usertype) values('2344273532',26);
insert into tb_testnum(boxnumber,usertype) values('2344273533',52);
insert into tb_testnum(boxnumber,usertype) values('2344273534',87);

第三步
在向表tb_testnum中插入数据之后,我们开始逐条执行第一步中的存储过程调用语句,以验证存储过程代码逻辑的正确性。

首先执行“call pr_dealtestnum(‘2344273520’,@1,@2);select @1,@2;”,结果如下:

mysql> call pr_dealtestnum('2344273520',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    2 |
+------+------+
1 row in set (0.00 sec)

我们来分析执行结果是否是我们想要的。将入参“2344273520”带入存储过程中,首先是“select count(*) into p_boxnumcount from tb_testnum where boxnumber=’2344273520’;”,此时“boxnumcount”变量的值为1(因为之前执行过语句“insert into tb_testnum(boxnumber,usertype) values(‘2344273520’,1);”);接着,程序进入“if p_boxnumcount > 0 then”分支,执行“select usertype into p_usertype from tb_testnum where boxnumber=’2344273520’;”语句,“p_usertype”变量的值为1;然后,执行“set p_outusertype = (1+1)/10*10;”语句,即“p_outusertype”变量的值为“2/10*10”,进一步计算为“0*10”,最终结果为0;最后,执行“set p_result = 0;”语句,“p_result”变量的值为0。因此,最终两个输出参数的值都应该为0。

但是,实际的结果是,两个输出参数的值分别为0和2,是哪里出了问题呢?我们重点分析“(1+1)/10*10”的结果,将之在MySQL中单独执行,结果如下:

mysql> select (1+1)/10*10;
+-------------+
| (1+1)/10*10 |
+-------------+
|      2.0000 |
+-------------+
1 row in set (0.00 sec)

mysql> select (1+1)/10;
+----------+
| (1+1)/10 |
+----------+
|   0.2000 |
+----------+
1 row in set (0.00 sec)

我们可以看到,“(1+1)/10”的结果并不是我们预想的0,而是0.2,看来,在MySQL中,两个整数相除并不是只取结果的整数部分,而是取了小数点后面的若干位。

那么,如果我们只想要整数部分,应该怎么办呢?此时,可以用floor()函数,即“floor((1+1)/10)”就是取了结果的整数部分,如下所示:

mysql> select floor((1+1)/10);
+-----------------+
| floor((1+1)/10) |
+-----------------+
|               0 |
+-----------------+
1 row in set (0.00 sec

现在,我们据此修改存储过程,修改之后如下所示:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30),
    out   p_result       int,
    out   p_outusertype  int
)
pr_dealtestnum_label:begin
    declare   p_boxnumcount    int;
    declare   p_usertype       int;

    set p_boxnumcount = 0;
    set p_usertype    = 0;
    set p_outusertype = 0;

    select count(*) into p_boxnumcount from tb_testnum where boxnumber=p_boxnumber;
    if p_boxnumcount > 0 then
    begin
        select usertype into p_usertype from tb_testnum where boxnumber=p_boxnumber;

        set p_outusertype =  floor((p_usertype+1)/10)*10;

        set p_result = 0;
    end;
    else
    begin
        set p_result = 1;
    end;
    end if;

    leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procedure pr_dealtestnum ok';

再次执行“call pr_dealtestnum(‘2344273520’,@1,@2);select @1,@2;”,结果如下:

mysql> call pr_dealtestnum('2344273520',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

此时的结果就是我们想要的。

我们可以继续执行在第一步中设置的其它存储过程调用语句,结果如下:

mysql> call pr_dealtestnum('2344273521',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273522',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273523',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273524',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273525',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273526',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273527',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273528',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273529',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273530',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273531',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273532',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   20 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273533',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   50 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273534',@1,@2);select @1,@2;
Query OK, 1 row affected (0.01 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   80 |
+------+------+
1 row in set (0.00 sec)
mysql> call pr_dealtestnum('15696192523',@1,@2);select @1,@2;
Query OK, 1 row affected (0.01 sec)

+------+------+
| @1   | @2   |
+------+------+
|    1 |    0 |
+------+------+
1 row in set (0.00 sec)

可以看到,修改之后的存储过程的执行结果就是正确的了。最后一条调用语句“call pr_dealtestnum(‘15696192523’,@1,@2);select @1,@2;”中,因为输入参数中的“15696192523”对应的数据在tb_testnum表中不存在,因此程序进入了“else”分支,“p_result”变量的值就为1,而“p_outusertype”变量的值为0。

总结
存储过程的测试方法和用其它编程语言编写的程序的测试方法是一样的,都需要我们在充分理解程序逻辑的基础上构造完整的、多样化的测试用例,并在测试的过程中根据测试的结果来修改程序,以达到我们预期的结果,并最终满足用户的需求。

需要强调的是,在软件开发过程中,我们测试代码的时间,很可能会多余我们编写代码的时间,大家一定要耐着性子忍受测试代码过程中的“孤独感”。

时间: 2024-09-20 03:36:44

存储过程测试流程--以MySQL为例的相关文章

IBM测试流程

在"测试评估和计划"中的一些测试计划和测试策略等活动的介绍,可以在网上搜索到,而且这些内容对于初学者来说只需要了解就行了,因为这些内容大多是测试经理和测试架构师在做. 在本章节的介绍中 测试用例的内容: 测试用例是为特定的目的而设计的一组测试输入.执行条件和预期的结果.测试用例是执行的最小实体. 开始点:当需求已经被记载和复查,相关的测试方案已获批准的时候,测试用例开发才开始. 结束点:测试用例是用于整个测试执行阶段,并且为后续项目回归测试用例重用而保留. 测试用例的作用:测试用例是执

移动App性能测评与优化1.2.1 测试流程

1.2.1 测试流程 由于内存测试属于性能测试,Android系统又和Linux有很多相通之处,因此我们可以参考常见的Linux性能测试方法和指标,来制定客户端性能测试方案.常见的测试方法包括Monkey/UIAutomator类的常规压力测试.大数据/操作的峰值压力测试.长时间运行的稳定性测试等.这些方法都可以叠加在内存测试的方案中,观察这类场景下的应用内存情况,经常能够发现类似内存泄漏或OOM的问题. 参考了常见性能测试的方案,以及总结了以往对内存性能测试的经验后,我们总结出了一套进行内存测

关于Oracle存储过程测试

常规方式保存测试信息 创建相关数据表 创建数据表TestInfoLog,和序列号SEQ_TestInfoLog 参考当前目录下的 TestInfoLog.sql ,运行这部分脚本. 创建测试信息保存包 创建一个测试信息保存的 Package 参考当前目录下的 PKG_Test_Info.pck,编译这个包. 具体例子 例子1 在一个PL/SQL块中使用测试包来保存测试信息,参考当前目录下的 example1.sql -- 简单使用的一个例子,结果查询 select * from TESTINFO

测试php连接mysql是否成功的代码分享

 很多情况下我们不知道是php错误,还是mysql用户名密码不对导致cms运行错误,可以先用下面的代码测试一下就可以了 方法很简单:   将下面的代码保存为test.php,放到web目录里面执行即可.    代码如下: <?php  /** * 测试php与mysql连接 * 编辑:www.jbxue.com */ $link=mysql_connect("localhost","root","123");  if(!$link) ech

mysql-在Windows32进行自定义环境搭建测试PHP连接MySQL时总是提示Fatal error: Call to undefined function

问题描述 在Windows32进行自定义环境搭建测试PHP连接MySQL时总是提示Fatal error: Call to undefined function 已经打开extension=PHP_mysql和extension=PHP_mysqli用phpmyadmin测试显示PHP配置错误 可是找不到错误 解决方案 PHP连接Mysql数据库报错:Fatal error: Call to undefined function mysql_connect()Fatal error: Call

ttcn-TTCN-3如何应用与协议测试?请教测试流程

问题描述 TTCN-3如何应用与协议测试?请教测试流程 被测系统是:消息中间件,该中间件对消息格式进行了严格的规定,可以连接多个子系统,用于子系统之间的消息通信.测试目的是:消息格式会随着业务需求,在个别字段上有变化,需要测试版本的兼容性和新版本的功能.TTCN-3可以用于协议测试,小弟对TTCN-3语言做了一些了解,但是小弟不清楚具体该如何实施.求问TTCN-3自动化脚本开发和维护维护,adapter开发.具体测试方案和流程等方面该注意的问题? 解决方案 http://wenku.baidu.

测试php连接mysql是否成功的代码分享_php实例

方法很简单: 将下面的代码保存为test.php,放到web目录里面执行即可. 复制代码 代码如下: <?php /*** 测试php与mysql连接* 编辑:www.jb51.net*/$link=mysql_connect("localhost","root","123"); if(!$link) echo "FAILD!连接错误,用户名密码不对"; else echo "OK!可以连接"; ?&

无线客户端测试流程随想

最近在写年度总结时,对目前项目iPhone客户端的测试流程做了一些分析.由于无线客户端产品和传统的Web端测试所注重的点大有不同,客户端的测试更关注视觉和交互,和各种场景下客户端的处理逻辑,所以测试流程也需要和传统的Web测试有所区别. 希望对无线测试有兴趣的同学们,一起讨论,一起分享... 1.目前客户端测试流程.(单线程流程) 1)单线程流程存在问题: (1)测试需要关注视觉,交互,功能等所有的问题,对测试自身专业技能要求过高.测试资源投入和产出比不高. (2)BugBash阶段发现交互,视

移动App性能测评与优化1.2 规范测试流程及常见等问题

1.2 规范测试流程及常见等问题 最开始进行内存测试时,我们可能还有些摸不着头脑,试着找了些工具,看了看教程就开始动手了.有时候因为问题比较明显,就真的发现了问题.再之后遇到类似的测试需求,我们就会按上次的经验去做.有时候可能发现问题,也可能发现不了,还有些时候甚至是在白费工夫.因为随着明显的问题逐渐被找出来,剩下的都是更加复杂而不太明显的问题了,甚至有些问题更是可以归属到优化范畴或者产品策略之内,而不再是简单的内存问题. 随着经验的逐渐增加,我们逐渐意识到,以前的很多测试方法都属于随机乱测.对