utPLSQL用户指南四

上一个,utResult包

utAssert包包含以下过程与函数。

  • 通用“Assert This”过程。utAssert.this。
  • 检查NULL与NOT NULL。utAssert.isnull、utAssert.isnotnull。
  • 检查标量值的相等性utAssert.eq。
  • 检查数据库表的相等性utAssert.eqtable。
  • 检查表中数据量的相等性utAssert.eqtabcount。
  • 检查查询结果的相等性utAssert.eqquery。
  • 检查查询与单个值的相等性utAssert.eqqueryvalue。
  • 检查文件的相等性utAssert.eqfile。
  • 检查数据库管道的相等性utAssert.eqpipe。
  • 检查集合的相等性utAssert.eqcoll、utAssert.eqcollapi。
  • 检查过程或函数抛出的异常utAssert.throws。
  • 检查上一个断言成功或失败utAssert.previous_passed、utAssert.previous_failed。
  • 检查DBMS_OUTPUT输出集合的相等性utAssert.eqoutput。
  • 检查数据库对象的存在性utAssert.objexists、utAssert.objnotexists。
  • 检查RefCursor与查询的相等性utAssert.eq_refc_query。
  • 检查RefCursor与数据库表的相等性utAssert.eq_refc_table。

在utAssert断言程序之前(或者断言程序中)调用测试用例,以便记录测试结果并执行断言程序。以下是一个简单的示例。
PROCEDURE ut_BETWNSTR IS
BEGIN
utAssert.eq (
'Typical valid usage',
BETWNSTR(
STRING_IN => 'abcdefg'
,
START_IN => 3
,
END_IN => 5
),
'cde'
);
END;

注释:所有的utAssert断言都在ut_assertion表中定义,实际代码存储在utAssert包中。

1、通用断言参数与特性

许多断言程序拥有类似的参数,如下表所示。

 msg_in  断言失败时显示的信息。这是第一个参数,必选。
 check_this_in  要检查的值。如果是一个布尔表达式,通常是对被测试方法的调用。
 against_this_in  对于相等性断言,断言程序将会比较check_this_in与against_this_in的值。
 null_ok_in  如果将NULL与NULL比较看作测试成功,设置为TRUE;否则设置为FALSE。
 raise_exc_in  如果允许断言程序抛出未处理的异常,设置为TRUE。

2、通用“Assert This”断言程序

这个最常用的断言程序接收一个布尔表达式参数。

PROCEDURE this (
      msg_in          IN   VARCHAR2,
      check_this_in   IN   BOOLEAN,
      null_ok_in      IN   BOOLEAN := FALSE,
      raise_exc_in    IN   BOOLEAN := FALSE,
      register_in     IN   BOOLEAN := TRUE -- 2.0.1
   );

以下是一个检查布尔表达式的示例。

BEGIN
   ...
   utAssert.this (
      'Boolean function result',
      is_valid_account (my_account)
      );

也可以使用该断言注册一个失败的测试,通常用于异常部分。

EXCEPTION
   WHEN OTHERS
   THEN
utAssert.this ( SQLERRM, FALSE);

通常,应该避免使用utAssert.this,而使用专用的断言程序,参考下文。

3、检查NULL与NOT NULL

使用以下断言检查某个值为NULL或者NOT NULL。

PROCEDURE utAssert.isnotnull (
msg_in IN VARCHAR2,
check_this_in IN VARCHAR2,
null_ok_in IN BOOLEAN := FALSE,
raise_exc_in IN BOOLEAN := FALSE
);

PROCEDURE utAssert.isnull (
msg_in IN VARCHAR2,
check_this_in IN VARCHAR2,
null_ok_in IN BOOLEAN := FALSE,
raise_exc_in IN BOOLEAN := FALSE
);

PROCEDURE utAssert.isnotnull (
msg_in IN VARCHAR2,
check_this_in IN BOOLEAN,
null_ok_in IN BOOLEAN := FALSE,
raise_exc_in IN BOOLEAN := FALSE
);

PROCEDURE utAssert.isnull (
msg_in IN VARCHAR2,
check_this_in IN BOOLEAN,

null_ok_in IN BOOLEAN := FALSE,
raise_exc_in IN BOOLEAN := FALSE
);

这些断言用于检查标量表达式(字符串、日期、数字以及布尔值)为NULL或者NOT NULL,如下所示。

BEGIN
   ...
   utAssert.isNULL (
      'Should be nothing left',
      TRANSLATE (digits_in_string, 'A1234567890', 'A')
      );

4、检查标量值的相等性

如果需要比较两个日期、字符串、数字或者布尔值,使用utAssert.eq断言程序。

PROCEDURE utAssert.eq (
   msg_in IN VARCHAR2,
   check_this_in IN VARCHAR2|BOOLEAN|DATE|NUMBER,
   against_this_in IN VARCHAR2|BOOLEAN|DATE|NUMBER,
   null_ok_in IN BOOLEAN := FALSE,
   raise_exc_in IN BOOLEAN := FALSE
);

如果该测试允许比较两个NULL值,为null_ok_in传入TRUE。如果希望在失败时抛出异常并且停止测试,为raise_exc_in传入TRUE。
PROCEDURE ut_emp_dept_lookuprowcount
IS l_rowcount1 PLS_INTEGER;
l_rowcount2 PLS_INTEGER;
BEGIN
-- Run baseline code.
SELECT COUNT (*)
INTO l_rowcount1
FROM employee
WHERE department_id = 30; -- Compare to program call:
l_rowcount2 :=
te_employee.emp_dept_lookuprowcount (30); -- Test results
utassert.eq (
'Successful EMP_DEPT_LOOKUPROWCOUNT',
l_rowcount2,
l_rowcount1
);
END;

5、检查数据库表的相等性

测试DML操作时,需要在数据库表中检查操作的结果。utAssert.eqtable可以比较另个表的内容。

PROCEDURE utAssert.eqtable (
   msg_in IN VARCHAR2,
   check_this_in IN VARCHAR2,
   against_this_in IN VARCHAR2,
   check_where_in IN VARCHAR2 := NULL,
   against_where_in IN VARCHAR2 := NULL,
   raise_exc_in IN BOOLEAN := FALSE
);

其中,check_this_in与against_this_in是表或视图的名称。可以提供可选的WHERE从句限制进行比较的数据行。以下是一个示例,它调用了eqTable两次,测试不同的条件。

PROCEDURE ut_del1
IS
fdbk PLS_INTEGER;
BEGIN
/* Delete that finds now rows. */

EXECUTE IMMEDIATE '
DELETE FROM ut_DEL1
WHERE employee_id = -1
';
te_employee.del (-1, rowcount_out => fdbk); -- Test results
utassert.eqtable ('Delete rows', 'EMPLOYEE', 'ut_DEL1');
/* Successful delete */

EXECUTE IMMEDIATE '
DELETE FROM ut_DEL1
WHERE employee_id between 7800 and 7899
';

FOR rec IN (SELECT *
FROM employee
WHERE employee_id BETWEEN 7800 AND 7899)
LOOP
te_employee.del (
rec.employee_id,
rowcount_out => fdbk
);
END LOOP;

-- Test results
utassert.eqtable ('Delete rows', 'EMPLOYEE', 'ut_DEL1');
ROLLBACK;
EXCEPTION
WHEN OTHERS
THEN
utassert.this (
'DEL1 exception ' || SQLERRM,
SQLCODE = 0
);
END;

6、检查表中数据量的相等性

如果只是简单地检查表中数据的行数,使用utAssert.eqtabcount。

PROCEDURE utAssert.eqtabcount (
   msg_in IN VARCHAR2,
   check_this_in IN VARCHAR2,
   against_this_in IN VARCHAR2,
   check_where_in IN VARCHAR2 := NULL,
   against_where_in IN VARCHAR2 := NULL,
   raise_exc_in IN BOOLEAN := FALSE
);

参数参见utAssert.eqtable。以下测试比较表CD_COLLECTION与表U_TEST_5_1中给定条件下的行数。

utassert.eqtabcount('Test 5.1: Insert new rows',
                    'CD_COLLECTION',
                    'UT_TEST_5_1',
                    'ARTIST = ''The Fall''',
                    'ARTIST = ''The Fall''');

7、检查查询结果的相等性

程序utAssert.eqquery比较两个查询(由check_this_in与against_this_in指定)的结果。这样可以不需要构建具有预置数据的表。

PROCEDURE utAssert.eqquery (
   msg_in IN VARCHAR2,
   check_this_in IN VARCHAR2,
   against_this_in IN VARCHAR2,
   raise_exc_in IN BOOLEAN := FALSE
);

以下是一个示例。

PROCEDURE ut_upd1
IS
BEGIN
/* Update 3 columns by ID */

EXECUTE IMMEDIATE '
UPDATE ut_UPD1 SET
FIRST_NAME = ''SILLY'',
HIRE_DATE = trunc (SYSDATE+100),
COMMISSION = 5000
WHERE
EMPLOYEE_ID = 7600
';
te_employee.upd (
7600,
first_name_in => 'SILLY',
commission_in => 5000,
hire_date_in => TRUNC (SYSDATE + 100),
rowcount_out => fdbk
);
-- Test results (audit fields are different so do a query)
utassert.eqquery (
'Update three columns',
'select first_name, commission, hire_date from EMPLOYEE',
'select first_name, commission, hire_date from ut_upd1'
);
ROLLBACK;
END;

8、检查查询与单个值的相等性

utAssert.eqqueryvalue用于比较查询结果与某个给定值,定义如下。

PROCEDURE utAssert.eqqueryvalue (
      msg_in IN VARCHAR2,
      check_query_in IN VARCHAR2,
      against_value_in IN VARCHAR2|NUMBER|DATE,
null_ok_in IN BOOLEAN := FALSE,
  raise_exc_in IN BOOLEAN := FALSE );

其中,check_query_in是检查的查询,against_value_in是比较的值。如果查询返回多个值,错误信息会进行说明。同样,如果查询结果返回了错误的值,错误信息会描述两个值。以下示例比较表中的最大值与给定的数字值。

utAssert.eqqueryvalue('Maximum value test',
                      'SELECT MAX(MEMORY)
                       FROM COMPUTERS
                       WHERE OS IN (''Linux'', ''Unix'')',
                       256);

9、检查文件的相等性

许多程序产生输出信息到操作系统文件中,或者写入数据到文件中以便测试结果。eqfile过程使用UTL_FILE包比较两个文件的内容。注意:UTL_FILE包使用前需要进行配置

PROCEDURE utAssert.eqfile (
   msg_in IN VARCHAR2,
   check_this_in IN VARCHAR2,
   check_this_dir_in IN VARCHAR2,
   against_this_in IN VARCHAR2,
   against_this_dir_in IN VARCHAR2 := NULL,
   raise_exc_in IN BOOLEAN := FALSE
);

如果不指定目录against_this_dir,使用check_this_dir设置。以下是一个使用eqFile的示例,参见ut_DEPARTMENT2file.pkg文件。

PROCEDURE ut_DEPARTMENT2FILE IS
BEGIN
DEPARTMENT2FILE (
LOC => 'c:\temp',
FILE => 'department.dat',
DELIM => '***'
);

utAssert.eqfile (
'Test of DEPARTMENT2FILE',
'department.dat',
'c:\temp',
'department.tst',
'c:\temp'
);
END ut_DEPARTMENT2FILE;

10、检查数据库管道的相等性

数据管道提供了一个在不同会话之间传递数据的便利机制。使用eqpipe检查管道中的内容。

PROCEDURE eqpipe (
      msg_in            IN   VARCHAR2,
      check_this_in     IN   VARCHAR2,
      against_this_in   IN   VARCHAR2,
      check_nth_in      IN   VARCHAR2 := NULL,
      against_nth_in    IN   VARCHAR2 := NULL,
      raise_exc_in      IN   BOOLEAN := FALSE
   );

要检查代码的管道内容,需要再生成一个管道进行比较。参考employee_pipe.pkg文件。

PROCEDURE ut_fillpipe IS
stat PLS_INTEGER;
BEGIN
emptypipe ('emps');
emptypipe ('emps2');

fillpipe ('emps');

/* Direct filling of pipe. */

FOR rec IN (SELECT *
FROM employee)
LOOP
DBMS_PIPE.RESET_BUFFER;
DBMS_PIPE.PACK_MESSAGE (rec.EMPLOYEE_ID);
DBMS_PIPE.PACK_MESSAGE (rec.LAST_NAME);
DBMS_PIPE.PACK_MESSAGE (rec.FIRST_NAME);
DBMS_PIPE.PACK_MESSAGE (rec.MIDDLE_INITIAL);
DBMS_PIPE.PACK_MESSAGE (rec.JOB_ID);
DBMS_PIPE.PACK_MESSAGE (rec.MANAGER_ID);
DBMS_PIPE.PACK_MESSAGE (rec.HIRE_DATE);
DBMS_PIPE.PACK_MESSAGE (rec.SALARY);
DBMS_PIPE.PACK_MESSAGE (rec.COMMISSION);
DBMS_PIPE.PACK_MESSAGE (rec.DEPARTMENT_ID);
DBMS_PIPE.PACK_MESSAGE (rec.CHANGED_BY);
DBMS_PIPE.PACK_MESSAGE (rec.CHANGED_ON);

stat := DBMS_PIPE.SEND_MESSAGE ('emps2', 0);
END LOOP;

/* Compare the two */
utassert.eqpipe (
'Two employee pipes', 'emps', 'emps2');

END ut_fillpipe;

11、检查集合的相等性

使用eqColl过程比较在包规范中定义的集合。使用eqCollAPI过程比较在包体中定义的集合,它利用包体中的程序(以及API)访问并操作集合。它们的定义如下。

/* Direct access to collections */
   PROCEDURE utAssert.eqcoll (
      msg_in IN VARCHAR2,
      check_this_in IN VARCHAR2, /* pkg1.coll */
      against_this_in IN VARCHAR2, /* pkg2.coll */
      eqfunc_in IN VARCHAR2 := NULL,
      check_startrow_in IN PLS_INTEGER := NULL,
      check_endrow_in IN PLS_INTEGER := NULL,
      against_startrow_in IN PLS_INTEGER := NULL,
      against_endrow_in IN PLS_INTEGER := NULL,
      match_rownum_in IN BOOLEAN := FALSE,
      null_ok_in IN BOOLEAN := TRUE,
      raise_exc_in IN BOOLEAN := FALSE
   );
 
   /* API based access to collections */
   PROCEDURE utAssert.eqcollapi (
      msg_in IN VARCHAR2,
      check_this_pkg_in IN VARCHAR2,
      against_this_pkg_in IN VARCHAR2,
      eqfunc_in IN VARCHAR2 := NULL,
      countfunc_in IN VARCHAR2 := 'COUNT',
      firstrowfunc_in IN VARCHAR2 := 'FIRST',
      lastrowfunc_in IN VARCHAR2 := 'LAST',
      nextrowfunc_in IN VARCHAR2 := 'NEXT',
      getvalfunc_in IN VARCHAR2 := 'NTHVAL',
      check_startrow_in IN PLS_INTEGER := NULL,
      check_endrow_in IN PLS_INTEGER := NULL,
      against_startrow_in IN PLS_INTEGER := NULL,
      against_endrow_in IN PLS_INTEGER := NULL,
      match_rownum_in IN BOOLEAN := FALSE,
      null_ok_in IN BOOLEAN := TRUE,
      raise_exc_in IN BOOLEAN := FALSE
   );

其中,eqColl特有的参数如下表。

 参数  描述
 msg_in  测试失败时显示的信息
 check_this_in  被检查的集合名称。格式:package.collection。也就是说,集合必须在包规范中定义。
 against_this_in  参照的集合名称。格式:package.collection。也就是说,集合必须在包规范中定义。

eqCollAPI特有的参数如下表。

 参数  描述
 msg_in  测试失败时显示的信息。
 check_this_pkg_in  包含被测试集合的包名。
 against_this_pkg_in  包含参照集合的包名。
 countfunc_in  包中返回集合的行数的函数名称。
 firstrowfunc_in  包中返回集合第一行的函数名称。
 lastrowfunc_in  包中返回集合最后一行的函数名称。
 nextrowfunc_in  包中返回集合下一行的函数名称。
 getvalfunc_in  包中返回集合指定行的内容的函数名称。

以上两个过程共同的参数如下表。


 参数  描述
 eqfunc_in  判断数据行的内容是否相同的函数。如果参数为NULL,使用标准的相等性检查。这对于标量值有效,但不能用于记录表等。
 check_startrow_in  被测试集合中参与比较的第一行。如果为NULL,从集合的首行开始。
 check_endrow_in  被测试集合中参与比较的最后一行。如果为NULL,比较到集合的末行结束。
 against_startrow_in  参照集合中参与比较的第一行。如果为NULL,从集合的首行开始。
 against_endrow_in  参照集合中参与比较的最后一行。如果为NULL,比较到集合的末行结束。
 match_rownum_in  设置为TRUE时两个集合中参与比较的行号必须相同。如果为FALSE,行号可以不同,但是对应行内容必须相同。
 null_ok_in  设置为TRUE时,两个NULL集合返回测试成功。
 raise_exc_in  设置为TRUE时,如果测试失败,断言将会抛出一个异常并停止测试。

以下是一个使用utAssert.eqColl的示例,参见filepath1.pkg文件。

PROCEDURE ut_setpath
IS
BEGIN
/* Populate base collection */
ut_dirs.DELETE;
ut_dirs.EXTEND(2);
ut_dirs(1) := 'c:\temp';
ut_dirs(2) := 'e:\demo';

/* Call setpath to do the work */
setpath ('c:\temp;e:\demo');

utAssert.eqColl (
'Valid double entry',
'fileio.dirs',
'fileio.ut_dirs'
);
END;

12、检查过程或函数抛出的异常

有时候过程或者函数被设计为在特定情况下抛出异常。utAssert.throws用于测试这种情况。

PROCEDURE throws (
      msg_in VARCHAR2,
      check_call_in IN VARCHAR2,
      against_exc_in IN VARCHAR2|NUMBER
   );

其中,check_call_in是执行的过程或函数调用,包括参数和结束的分号。参数against_exc_in是期望抛出的异常,可以是命名异常,或者SQLCODE代码。

以下示例显示了两种用法。

/* Test the Except Function */
PROCEDURE ut_except
IS
BEGIN

/* Call the procedure with a negative number */
/* We expect a NO_DATA_FOUND exception */
utAssert.throws('Negative Number',
'Except(-1);',
'NO_DATA_FOUND'
);

/* Call the procedure with zero and a string */
/* over 2 in length - We expect a SQLCODE of -1 */
utAssert.throws('Zero and String',
'Except(0, ''Hello'');',
-1
);
END;

注意对字符串参数的引用和结束的分号。

13、检查上一个断言成功或失败

有时候,过程可能执行了大量的操作,例如执行了多个表的插入和更新。要测试这些修改,需要多个utAssert断言。有可能在测试失败时输出整个屏幕的错误信息。为了避免这种情况,只显示一个错误信息,可以使用previous_passed函数和previous_failed函数。它们返回上一个断言成功或失败的布尔参数。

/* Test the BookTrips Procedure */
PROCEDURE ut_bookTrips
IS 
BEGIN

  /* Call the procedure */
  Vacation.bookTrips(5, 'Rio de Janeiro');
  
  /* Did it insert 5 rows into TRIPS table */
  utAssert.eqqueryvalue('Insert 5 rows',
    'SELECT COUNT(*)
    FROM TRIPS
    WHERE CITY = ''Rio de Janeiro''',
    5);
    
  /* If that worked, look in more detail */
  IF utAssert.previous_passed THEN
    
    /* Do they all have today's date? */
    utAssert.eqqueryvalue('All with todays date',
      'SELECT COUNT(*)
       FROM TRIPS
       WHERE CITY = ''Rio de Janeiro'''
       AND TRUNC(CREATED) = TRUNC(SYSDATE)',
       5);
     
    /* Do they all have a hotel specified? */
    utAssert.eqqueryvalue('Hotel Specfied',
      'SELECT COUNT(*)
       FROM TRIPS T, HOTELS H
       WHERE T.CITY = ''Rio de Janeiro'''
       AND T.HOTEL = H.ID',
       5);
     
 END IF;
   
END;

14、检查DBMS_OUTPUT输出集合的相等性

utAssert.eqoutput过程补充了utOutput包,允许比较DBMS_OUTPUT.CHARARR类型的集合。与eqColl和eqCollAPI断言不同,eqoutput运行比较本地定义的集合。

PROCEDURE eqoutput (
   msg_in                IN   VARCHAR2,
   check_this_in         IN   DBMS_OUTPUT.CHARARR,
   against_this_in       IN   DBMS_OUTPUT.CHARARR,
   ignore_case_in        IN   BOOLEAN := FALSE,
   ignore_whitespace_in  IN   BOOLEAN := FALSE,
   null_ok_in            IN   BOOLEAN := TRUE,
   raise_exc_in          IN   BOOLEAN := FALSE
);

PROCEDURE eqoutput (
   msg_in                IN   VARCHAR2,
   check_this_in         IN   DBMS_OUTPUT.CHARARR,
   against_this_in       IN   VARCHAR2,
   line_delimiter_in     IN   CHAR := NULL,
   ignore_case_in        IN   BOOLEAN := FALSE,
   ignore_whitespace_in  IN   BOOLEAN := FALSE,
   null_ok_in            IN   BOOLEAN := TRUE,
   raise_exc_in          IN   BOOLEAN := FALSE
);

第一个版本比较两个集合,第二个比较集合与分隔字符串。分隔符在参数line_delimiter_in中指定,如果指定为NULL(默认),分隔符为回车符。因此,要测试如下的集合mybuff:

mybuff(0) := 'Zidane';
mybuff(1) := 'Ronaldo';
mybuff(2) := 'Kahn';

可以使用如下参数。

against_this_in => 'Zidane|Ronaldo|Kahn';
line_delimiter_in => '|';

或者

against_this_in =>
'Zidane
Ronaldo
Kahn';
line_delimiter_in => NULL;

以下参数可以改变比较的方式。

  • ignore_case_in。比较时略大小写。
  • ignore_whitspace。比较时忽略空白符。

注意,以上断言只比较文本内容,不考虑集合中记录的编号是否连续,按照顺序进行比较。

15、检查数据库对象的存在性

以下断言检查数据库中的命名对象是否存在。

PROCEDURE objExists (
   msg_in            IN   VARCHAR2,
   check_this_in     IN   VARCHAR2,
   null_ok_in        IN   BOOLEAN := FALSE,
   raise_exc_in      IN   BOOLEAN := FALSE
);

PROCEDURE objnotExists (
   msg_in            IN   VARCHAR2,
   check_this_in     IN   VARCHAR2,
   null_ok_in        IN   BOOLEAN := FALSE,
   raise_exc_in      IN   BOOLEAN := FALSE
);

参数check_this_in指定要检查的对象名称。要检查其他模式下的对象,在该参数中加上模式名称和一个点号。‘ANOTHER.THATTHING’检查ANOTHER模式下THATTHING对象是否存在。

16、检查RefCursor与查询的相等性

如果过程或者函数返回REF CURSOR类型的数据,通常可能需要将它与一个查询进行比较。使用eq_refc_query可以避免构建一个带预置数据的临时表。

在调用比较断言之前需要指定被测试的过程或函数的参数。可以使用以下过程进行注册。

PROCEDURE utPLSQL_Util.reg_In_Param (
   par_pos            PLS_INTEGER,
   par_val            VARCHAR2 | NUMBER | DATE,
   params    IN OUT   utplsql_util.utplsql_params );

PROCEDURE utPLSQL_Util.reg_InOut_Param (
   par_pos            PLS_INTEGER,
   par_val            VARCHAR2 | NUMBER | DATE,
   params    IN OUT   utplsql_util.utplsql_params );

PROCEDURE utPLSQL_Util.reg_Out_Param (
   par_pos            PLS_INTEGER,
   par_type           VARCHAR2,
   params    IN OUT   utplsql_util.utplsql_params );

然后调用比较的断言过程。

PROCEDURE utAssert.eq_refc_query (
   p_msg_nm          IN   VARCHAR2,
   proc_name         IN   VARCHAR2,
   params            IN   utplsql_util.utplsql_params,
   cursor_position   IN   PLS_INTEGER,
   qry               IN   VARCHAR2 );

其中,reg_In_Param、reg_InOut_Param以及reg_Out_Param特有的参数如下表。

 参数  描述
 par_pos  定义从1开始的参数位置,0代表返回值。
 par_type  指定返回值的数据类型,必须是以下之一:NUMBER、VARCHAR、CHAR或者REFCURSOR。
 params  保持参数值的本地变量,用于eq_refc_query。

eq_refc_query特有的参数如下表。


 参数  描述
 p_msg_nm  测试失败时显示的信息。
 proc_name  被测试的过程或者函数名称。
 params  被测试的过程或者函数的参数。
 cursor_position  进行检查的REF CURSOR参数的位置,从1开始,0指定为函数的返回值。
 qry  参照检查的SELECT语句。

注意,断言只比较记录自身,不关心游标中记录的下标是否连续,按照顺序进行比较。

17、检查RefCursor与数据库表的相等性

如果过程或者函数返回代表一个完整表或视图的REF CURSOR类型的数据,通常可能需要将它与一个表或视图进行比较。使用eq_refc_table可以避免构建一个带预置数据的临时表。

在调用比较断言之前需要指定被测试的过程或函数的参数。参见上一小节。eq_refc_table断言过程声明如下。

PROCEDURE utAssert.eq_refc_table (
   p_msg_nm          IN   VARCHAR2,
   proc_name         IN   VARCHAR2,
   params            IN   utplsql_util.utplsql_params,
   cursor_position   IN   PLS_INTEGER,
   table_name        IN   VARCHAR2 );

其中,table_name是参照检查的表名。

18、创建自定义的断言

如果PL/SQL支持继承,就可以扩展utAssert断言程序并使用多态进行定制。但是它缺少了这种特性,可以参照预置的断言编写自己的过程。为了将自定义的断言的测试结果集成到utResult包中,可以模拟utAssert.this过程。以下是2.2版的this过程定义。

PROCEDURE this (
      outcome_in      IN   ut_outcome.id%TYPE,
      msg_in          IN   VARCHAR2,
      check_this_in   IN   BOOLEAN,
      null_ok_in      IN   BOOLEAN := FALSE ,
      raise_exc_in    IN   BOOLEAN := FALSE ,
      register_in     IN   BOOLEAN := TRUE
   )
   IS
      l_failure   BOOLEAN
   :=    NOT check_this_in
      OR (    check_this_in IS NULL
          AND NOT null_ok_in
         );
   BEGIN
      /* START chrisrimmer 42694 */
      g_previous_pass := NOT l_failure;

      /* END chrisrimmer 42694 */

      IF utplsql2.tracing
      THEN
         utreport.pl (
               'utPLSQL TRACE on Assert: '
            || msg_in
         );
         utreport.pl ('Results:');
         utreport.pl (l_failure);
      END IF;

      -- Report results failure and success

      utresult2.report (
         outcome_in,
         l_failure,
         utplsql.currcase.pkg || '.' || utplsql.currcase.name || ': ' || msg_in,
            /* 2.0.10.2 Idea from Alistair Bayley msg_in */
         register_in,
         showing_results
      );

      IF      raise_exc_in
          AND l_failure
      THEN
         RAISE test_failure;
      END IF;
   END;

在自定义的断言中最重要的语句是utResult.report,它记录了测试的结果。

下一个,utGen包

请使用浏览器的分享功能分享到微信等