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,它记录了测试的结果。