ITPub博客

首页 > Linux操作系统 > Linux操作系统 > utPLSQL示例一

utPLSQL示例一

原创 Linux操作系统 作者:BUAA_dxy 时间:2012-09-14 14:05:17 0 删除 编辑

1、测试一个存储过程

考虑以下情况:存储过程运行一些代码,然后通过参数列表返回结果。此时,可以编写一个测试单元,分析OUT和IN OUT参数的值;存储过程运行一些代码,修改了应用中的其他部分(例如表或者文件),参数列表不包含用于分析是否成功执行的参数。因此为了测试是否成功,需要分析/比较被修改的数据结构。

1.1、通过参数进行测试

以下过程接受两个日期参数并返回它们之间的秒数。

/*file calc_secs_between.sp */
CREATE OR REPLACE PROCEDURE calc_secs_between (
   date1 IN DATE,
   date2 IN DATE,
   secs OUT NUMBER)
IS
BEGIN
   -- 24 hours in a day, 
   -- 60 minutes in an hour,
   -- 60 seconds in a minute...
   secs := (date2 - date1) * 24 * 60 * 60;
END;
/

编译成功之后,创建测试包:

SQL> SET SERVEROUTPUT ON FORMAT WRAPPED
SQL> exec utGen.testpkg ('calc_secs_between')

以上语句会在屏幕上产生下面的输出:

CREATE OR REPLACE PACKAGE ut_calc_secs_between
IS
   PROCEDURE ut_setup;
   PROCEDURE ut_teardown;

   -- For each program to test...
   PROCEDURE ut_CALC_SECS_BETWEEN;
END ut_calc_secs_between;
/
CREATE OR REPLACE PACKAGE BODY ut_calc_secs_between
IS
   PROCEDURE ut_setup
   IS
   BEGIN
      NULL;
   END;

   PROCEDURE ut_teardown
   IS
   BEGIN
      NULL;
   END;

   -- For each program to test...
   PROCEDURE ut_CALC_SECS_BETWEEN IS
   BEGIN
      CALC_SECS_BETWEEN (
            DATE1 => ''
            ,
            DATE2 => ''
            ,
            SECS => ''
       );

      utAssert.this (
         'Test of CALC_SECS_BETWEEN',
         ''
         );
   END ut_CALC_SECS_BETWEEN;

END ut_calc_secs_between;
/

也可以直接生成两个单独的文件存储包规范与包体,ut_calc_secs_between.pks与ut_calc_secs_between.pkb,方法如下:

SQL> exec utGen.testpkg ('calc_secs_between ', output_type_in => utGen.c_file)

通过以上方式,utPLSQL能够在每次测试之前自动编译代码。编辑文件,添加各种用例,内容如下:

PROCEDURE ut_CALC_SECS_BETWEEN
IS
   secs PLS_INTEGER;
BEGIN
   CALC_SECS_BETWEEN (
         DATE1 => SYSDATE
         ,
         DATE2 => SYSDATE
         ,
         SECS => secs
    );

   utAssert.eq (
      'Same dates',
      secs,
      0
      );
      
   CALC_SECS_BETWEEN (
         DATE1 => SYSDATE
         ,
         DATE2 => SYSDATE+1
         ,
         SECS => secs
    );

   utAssert.eq (
      'Exactly one day',
      secs,
      24 * 60 * 60
      );
      
END ut_CALC_SECS_BETWEEN;

然后运行测试:

SQL> exec utplsql.test ('calc_secs_between')
.
>    SSSS   U     U   CCC     CCC   EEEEEEE   SSSS     SSSS
>   S    S  U     U  C   C   C   C  E        S    S   S    S
>  S        U     U C     C C     C E       S        S
>   S       U     U C       C       E        S        S
>    SSSS   U     U C       C       EEEE      SSSS     SSSS
>        S  U     U C       C       E             S        S
>         S U     U C     C C     C E              S        S
>   S    S   U   U   C   C   C   C  E        S    S   S    S
>    SSSS     UUU     CCC     CCC   EEEEEEE   SSSS     SSSS
.
 SUCCESS: "calc_secs_between"

当然,还可以继续测试其他参数条件。

1.2、通过效果进行测试

以下是一个更复杂的情况。存储过程截断了指定表的所有数据行,定义如下:

/*file truncit.sp */
CREATE OR REPLACE PROCEDURE truncit (
   tab IN VARCHAR2,
   sch IN VARCHAR2 := NULL
)
IS
BEGIN
   EXECUTE IMMEDIATE 'truncate table ' || NVL (sch, USER) || '.' || tab;
END;
/

这个过程的测试不能简单地通过检查返回值决定是否成功,而是应该检查表中还存在多少行数据。以下函数能够返回表中的数据行(也可以使用utAssert.eqqueryvalue):

/*file tabcount.sf */
CREATE OR REPLACE FUNCTION tabcount (
   sch IN VARCHAR2,
   tab IN VARCHAR2)
   RETURN INTEGER
IS
   retval  INTEGER;
BEGIN
   EXECUTE IMMEDIATE 
      'SELECT COUNT(*) FROM ' || sch || '.' || tab
      INTO retval; 
   RETURN retval;
EXCEPTION
    WHEN OTHERS 
    THEN
       RETURN NULL; 
END;
/

然后生成测试包,并修改包体:

SQL> SET SERVEROUTPUT ON FORMAT WRAPPED
SQL> exec utGen.testpkg ('truncit', output_type_in => utGen.c_file)

为了进行测试,需要截断一个表。这是一个不可逆的操作,因此可以在设置程序中创建一个“临时”表,并在清除程序中删除它。然后运行测试并使用tabCount验证结果:

/*file ut_truncit.pkb */
CREATE OR REPLACE PACKAGE BODY ut_truncit
IS
   PROCEDURE ut_setup
   IS
   BEGIN
      EXECUTE IMMEDIATE 
         'CREATE TABLE temp_emp AS SELECT * FROM employee';
   END;
   
   PROCEDURE ut_teardown
   IS
   BEGIN
      EXECUTE IMMEDIATE 
         'DROP TABLE temp_emp';
   END;

   -- For each program to test...
   PROCEDURE ut_TRUNCIT IS
   BEGIN
      TRUNCIT (
            TAB => 'temp_emp'
            ,
            SCH => USER
       );

      utAssert.eq (
         'Test of TRUNCIT',
         tabcount (USER, 'temp_emp'),
         0
         );
   END ut_TRUNCIT;

END ut_truncit;
/

2、测试一个存储函数

与存储过程一样,考虑一下情况:函数返回标量值(数字、日期、字符串、布尔值)。此时,可以直接将函数调用嵌套在utAssert断言程序的调用中;函数返回非标量值,例如对象或者集合。此时,需要调用该函数,并验证返回结构的内容;函数返回一个值,同时执行了其他操作,这些操作的成功与否没有通过返回值体现。要想充分测试这种函数(存在“副作用”)可能会非常困难,因为必须考虑各种情况。

2.1、测试一个标量函数

以下定义了一个包中的函数:

/*file str.pks and str.pkb */
CREATE OR REPLACE PACKAGE str
IS
   FUNCTION betwn (
      string_in IN VARCHAR2,
      start_in IN PLS_INTEGER,
      end_in IN PLS_INTEGER
   )
      RETURN VARCHAR2;
END str;
/

函数str.betwn返回字符串string_in的一个字串,起始位置和结束位置分别为start_in和end_in。

然后生成了一个测试包并修改单元测试程序的内容,如下所示:

/*file ut_str.pkb */
CREATE OR REPLACE PACKAGE BODY ut_str
IS
   PROCEDURE ut_setup
   IS
   BEGIN
      NULL;
   END;
   
   PROCEDURE ut_teardown
   IS
   BEGIN
      NULL;
   END;

   -- For each program to test...
   PROCEDURE ut_betwn IS
   BEGIN
      utAssert.eq (
         'Typical Valid Usage',
         str.betwn ('this is a string', 3, 7),
         'is is' 
         );
         
      utAssert.eq (
         'Test Negative Start',
         str.betwn ('this is a string', -3, 7),
         'ing'
         );
         
      utAssert.isNULL (
         'Start bigger than end',
         str.betwn ('this is a string', 3, 1)
         );
   END ut_betwn;

END ut_str;
/

示例二

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/24945919/viewspace-743236/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: utPLSQL构建测试包
下一篇: utPLSQL用户指南一
请登录后发表评论 登录
全部评论
《SQL编程思想》作者,专注于数据库领域知识的分享。

注册时间:2021-08-26

  • 博文量
    443
  • 访问量
    546865