如何对PL / SQL过程进行单元测试? (使用utplsql)

时间:2009-07-14 16:06:51

标签: oracle unit-testing plsql

包非常非常基础。 循环遍历游标,并更新record_ids相等的2个值。

对于这种程序,什么是适当的单元测试?

我将添加一些骷髅代码,因为到目前为止答案虽然很好,但却与我的问题紧密相关:我该测试什么?

PROCEDURE set_shift_times_to_null( RETVAL OUT VARCHAR2,
                                 ERRBUF OUT VARCHAR2,
                                RECORDS_UPDATED OUT NUMBER) IS 

   CURSOR evening_shift_employees_cur IS
   select employee
   FROM employees
   where SHIFT='EVENING'
   ;

BEGIN
   RECORDS_UPDATED := 0;
   RETVAL := '2';

   FOR evening_shift_employees IN evening_shift_employees_cur LOOP
      UPDATE NIGHT_SHIFT 
      Set SOME_DUMB_FIELD = evening_shift_employees.employee;

      RECORDS_UPDATED := RECORDS_UPDATED + 1;
   END LOOP;
   COMMIT;
   RETVAL := 0;
EXCEPTION WHEN OTHERS THEN
   ROLLBACK;
   ERRBUF := 'Error occurred - ' || SQLERRM;
END set_shift_times_to_null;

5 个答案:

答案 0 :(得分:1)

适当的单元测试它以验证受影响的表以检查更新的记录是否符合预期。

您可以使用期望的结果创建临时表,并且单元测试代码可以比较结果。当然是努力工作,但如果你想测试你必须做这样的事情。

这取决于程序的工作,但如果你想确保测试没问题,你必须尽可能检查。

许多条件必须使用约束进行验证,并且测试单元过程必须执行强制数据库检查约束(插入等)的代码。

答案 1 :(得分:1)

一些建议。

使用SQL%ROWCOUNT:

BEGIN
  UPDATE NIGHT_SHIFT
   Set SOME_DUMB_FIELD = evening_shift_employees.employee;
  v_rows_processed := SQL%ROWCOUNT;
  dbms_output.put_line('There were '||v_rows_processed||' rows updated');
END;

不要在其他人使用时(为什么要丢失堆栈跟踪)。只能使用例外,您将依赖调用者来检查ERRBUF的内容。

begin
  insert into t values ( 1 );
  exception when others then 
  log_error; 
  raise; 
end;

log_error实现如下:

create or replace procedure log_error
as
  pragma autonomous_transaction;
  l_whence varchar2(1024);
  l_msg    varchar2(1020) default sqlerrm;
  l_code   number default sqlcode;
  begin
    l_whence := whence;
    insert into error_table
     ( timestamp, whence, msg, code )
    values
     ( sysdate, whence, l_msg, l_code );
    commit;
   exception
  when others then
   rollback;
   raise;
  end;

考虑不使用任何pl / sql。在表面上,更新看起来完全“可行”而没有任何光标。也许是一个可更新的内联视图:

update (
  select e.sal as emp_sal, e.comm as emp_comm,
    ns.sal as ns_sal, ns.sal/2 as ns_comm
  from employees e, night_shift ns
  where e.deptno = ns.deptno
  ) 
set emp_sal = ns_sal, emp_comm = ns_comm

答案 2 :(得分:0)

基本上,您希望锻炼手术的所有可能性:

  • 使用相同的记录ID进行测试。
  • 使用不相等的记录ID进行测试。
  • 使用无效(非整数?否定?)记录ID进行测试。

另外,测试边界条件:

  • 使用记录ID关闭测试(例如:104和105)。
  • 使用最大记录ID(MAX_INT?)进行测试。
  • 使用零值记录ID进行测试。

这是一个很好的example良好的单元测试实践。

编辑:我不知道有一个强大的数据库查询单元测试工具。我会设置一个 evening_shift_employees 的测试表,其中包含各种记录ID条件,如上所述。然后,按照FerranB的建议,检查记录是否按预期进行更新以进行验证。

答案 3 :(得分:0)

我最终做的是以下内容:

  1. 记录主光标将字段更新为空的记录的计数
  2. 执行程序(返回更新的行的值)
  3. 记录第一次记录相同的记录
  4. 记录计数之间的差异应该等于过程中更新的记录数。如果是这样,测试通过。
  5. 这是否有意义,还是循环逻辑?

答案 4 :(得分:0)

对于其他任何看过这个的人,我在utplsql的文档中找到了这个: 程序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
);

这是断言文件;看起来它完全符合我的目的。