diff --git a/client_source/sqlplus/ut_run.sql b/client_source/sqlplus/ut_run.sql index 50a926916..e9b2e3053 100644 --- a/client_source/sqlplus/ut_run.sql +++ b/client_source/sqlplus/ut_run.sql @@ -111,7 +111,7 @@ set define & /* * Make SQLPlus parameters optional and pass parameters call to param_list variable */ -@@define_params_variable.sql.tmp +@define_params_variable.sql.tmp @@ -293,8 +293,8 @@ begin p(' v_reporter.reporter_id := '''||l_reporter_id||''';'); p(' v_reporters_list.extend; v_reporters_list(v_reporters_list.last) := v_reporter;'); end loop; + close :l_run_params_cur; end if; - close :l_run_params_cur; p( ' ut_runner.run( ut_varchar2_list('||:l_paths||'), v_reporters_list, a_color_console => '||:l_color_enabled||' );'); p( 'end;'); p( '/'); diff --git a/source/api/ut.pkb b/source/api/ut.pkb index 41f60f7b8..41be3643f 100644 --- a/source/api/ut.pkb +++ b/source/api/ut.pkb @@ -84,7 +84,7 @@ create or replace package body ut is procedure fail(a_message in varchar2) is begin - ut_assert_processor.report_error(a_message); + ut_assert_processor.report_failure(a_message); end; procedure run_autonomous(a_paths ut_varchar2_list, a_reporter ut_reporter_base, a_color_console integer) is diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index 4433f1254..0be9f9573 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -39,57 +39,85 @@ create or replace package body ut_coverage is return l_result; end; + -- The source query has two important transformations done in it. + -- the flag: to_be_skipped ='Y' is set for a line of code that is badly reported by DBMS_PROFILER as executed 0 times. + -- This includes lines that are: + -- - PACKAGE, PROCEDURE, FUNCTION definition line, + -- - BEGIN, END of a block + -- Another transformation is adjustment of line number for TRIGGER body. + -- DBMS_PROFILER is reporting line numbers for triggers not as defined in DBA_SOURCE, its usign line numbers as defined in DBA_TRIGGERS + -- the DBA_TRIGGERS does not contain the trigger specification lines, only lines that define the trigger body. + -- the query adjusts the line numbers for triggers by finding first occurrence of begin|declare|compound in the trigger body line. + -- The subquery is optimized by: + -- - COALESCE function -> it will execute only for TRIGGERS + -- - scalar subquery cache -> it will only execute once for one trigger source code. function get_sources_query return varchar2 is l_result varchar2(32767); + l_full_name varchar2(100); begin - l_result := 'insert /*+ append */ into ut_coverage_sources_tmp(full_name,owner,name,line,text, to_be_skipped)'; if g_file_mappings is not null then - l_result := 'insert /*+ append */ into ut_coverage_sources_tmp(full_name,owner,name,line,text, to_be_skipped) - select f.file_name, s.owner,s.name,s.line,s.text,'; + l_full_name := 'f.file_name'; else - l_result := 'insert /*+ append */ into ut_coverage_sources_tmp(full_name,owner,name,line,text, to_be_skipped) - select lower(s.owner||''.''||s.name) as file_name, s.owner,s.name,s.line,s.text,'; + l_full_name := 'lower(s.owner||''.''||s.name)'; end if; - l_result := l_result || q'[ - case - when - -- to avoid execution of regexp_like on every line - -- first do a rough check for existence of search pattern keyword - (lower(s.text) like '%procedure%' - or lower(s.text) like '%function%' - or lower(s.text) like '%begin%' - or lower(s.text) like '%end%' - or lower(s.text) like '%package%' - ) and - regexp_like( - s.text, - '^\s*(((not)?\s*(overriding|final|instantiable)\s*)*(static|constructor|member)?\s*(procedure|function)|package(\s+body)|begin|end(\s+\S+)?\s*;)', 'i' - ) - then 'Y' - end as to_be_skipped - from all_source s]'; + l_result := ' + insert /*+ append */ into ut_coverage_sources_tmp(full_name,owner,name,line,text, to_be_skipped) + select * + from ( + select '||l_full_name||q'[, + s.owner, + s.name, + s.line - + coalesce( + case when type!='TRIGGER' then 0 end, + (select min(t.line) - 1 + from dba_source t + where t.owner = s.owner and t.type = s.type and t.name = s.name + and regexp_like( t.text, '\w*(begin|declare|compound).*','i')) + ) as line, + s.text, + case + when + -- to avoid execution of regexp_like on every line + -- first do a rough check for existence of search pattern keyword + (lower(s.text) like '%procedure%' + or lower(s.text) like '%function%' + or lower(s.text) like '%begin%' + or lower(s.text) like '%end%' + or lower(s.text) like '%package%' + ) and + regexp_like( + s.text, + '^\s*(((not)?\s*(overriding|final|instantiable)\s*)*(static|constructor|member)?\s*(procedure|function)|package(\s+body)|begin|end(\s+\S+)?\s*;)', 'i' + ) + then 'Y' + end as to_be_skipped + from all_source s]'; if g_file_mappings is not null then l_result := l_result || ' - join table(:g_file_mappings) f - on s.name = f.object_name - and s.type = f.object_type - and s.owner = f.object_owner - where 1 = 1'; + join table(:g_file_mappings) f + on s.name = f.object_name + and s.type = f.object_type + and s.owner = f.object_owner + where 1 = 1'; else l_result := l_result || ' - where s.owner in (select upper(t.column_value) from table(:l_schema_names) t)'; + where s.owner in (select upper(t.column_value) from table(:l_schema_names) t)'; end if; l_result := l_result || q'[ - and s.type not in ('PACKAGE', 'TYPE') - --Exclude calls to utPLSQL framework, Unit Test packages and objects from a_exclude_list parameter of coverage reporter - and (s.owner, s.name) not in (select el.owner, el.name from table(:l_skipped_objects) el)]'; + and s.type not in ('PACKAGE', 'TYPE') + --Exclude calls to utPLSQL framework, Unit Test packages and objects from a_exclude_list parameter of coverage reporter + and (s.owner, s.name) not in (select el.owner, el.name from table(:l_skipped_objects) el)]'; if g_include_list is null then l_result := l_result || ' - and :g_include_list is null'; + and :g_include_list is null'; else l_result := l_result || ' - and (s.owner, s.name) in (select il.owner, il.name from table(:g_include_list) il)'; + and (s.owner, s.name) in (select il.owner, il.name from table(:g_include_list) il)'; end if; + l_result := l_result || ' + ) + where line > 0'; return l_result; end; /** diff --git a/source/core/types/ut_assert_result.tpb b/source/core/types/ut_assert_result.tpb index d676db471..db048923c 100644 --- a/source/core/types/ut_assert_result.tpb +++ b/source/core/types/ut_assert_result.tpb @@ -62,12 +62,9 @@ create or replace type body ut_assert_result is if a_clob is not null and l_text is not null then l_text := chr(10) || l_text; end if; - if l_text is not null then - dbms_lob.writeappend(a_clob, length(l_text), l_text); - end if; + ut_utils.append_to_clob(a_clob, l_text); end; begin - dbms_lob.createtemporary(l_result, true); if self.result != ut_utils.tr_success or self.error_message is not null then if self.message is not null then add_text_line(l_result, ' expectation description: ', self.message); diff --git a/source/core/types/ut_executable.tpb b/source/core/types/ut_executable.tpb index 383544f37..d34c70bbe 100644 --- a/source/core/types/ut_executable.tpb +++ b/source/core/types/ut_executable.tpb @@ -33,32 +33,22 @@ create or replace type body ut_executable is return self.procedure_name is not null and self.object_name is not null; end; - member function is_valid return boolean is - l_result boolean := true; + member function is_valid(self in out nocopy ut_executable) return boolean is + l_result boolean := false; + l_message_part varchar2(4000) := 'Call params for ' || self.associated_event_name || ' are not valid: '; begin if self.object_name is null then - l_result := false; - ut_assert_processor.report_error('Call params for ' || self.associated_event_name || ' are not valid: package is not defined'); - end if; - - if self.procedure_name is null then - l_result := false; - ut_assert_processor.report_error('Call params for ' || self.associated_event_name || ' are not valid: procedure is not defined'); - end if; - - if l_result and not ut_metadata.package_valid(self.owner_name, self.object_name) then - l_result := false; - ut_assert_processor.report_error('Call params for ' || self.associated_event_name || - ' are not valid: package does not exist or is invalid: ' ||nvl(self.owner_name, '')||'.'|| - nvl(self.object_name, '')); - end if; - - if l_result and not ut_metadata.procedure_exists(self.owner_name, self.object_name, self.procedure_name) then - l_result := false; - ut_assert_processor.report_error('Call params for ' || self.associated_event_name || ' are not valid: package missing ' || - ' procedure ' || self.object_name || '.' || - nvl(self.procedure_name, '')); + self.error_stack := l_message_part || 'package is not defined'; + elsif not ut_metadata.package_valid(self.owner_name, self.object_name) then + self.error_stack := l_message_part || 'package does not exist or is invalid: ' ||upper(self.owner_name||'.'||self.object_name); + elsif self.procedure_name is null then + self.error_stack := l_message_part || 'procedure is not defined'; + elsif not ut_metadata.procedure_exists(self.owner_name, self.object_name, self.procedure_name) then + self.error_stack := l_message_part || 'package missing procedure ' + || upper(self.owner_name || '.' || self.object_name || '.' ||self.procedure_name); + else + l_result := true; end if; return l_result; @@ -85,28 +75,16 @@ create or replace type body ut_executable is l_completed_without_errors boolean := true; - function process_errors_from_call(a_error_stack varchar2, a_error_backtrace varchar2) return boolean is - l_errors_stack_trace varchar2(32767) := rtrim(a_error_stack||a_error_backtrace, chr(10)); - begin - if l_errors_stack_trace is not null then - ut_utils.debug_log('test method failed- ' ||l_errors_stack_trace ); - ut_assert_processor.report_error( l_errors_stack_trace ); - return false; - else - return true; - end if; - end; - procedure save_dbms_output is l_status number; l_line varchar2(32767); begin dbms_lob.createtemporary(self.serveroutput, true, dur => dbms_lob.session); - + loop dbms_output.get_line(line => l_line, status => l_status); exit when l_status = 1; - + dbms_lob.writeappend(lob_loc => self.serveroutput, amount => length(l_line), buffer => l_line); @@ -153,10 +131,10 @@ create or replace type body ut_executable is dbms_sql.variable_value(l_cursor_number, 'a_error_stack', self.error_stack); dbms_sql.variable_value(l_cursor_number, 'a_error_backtrace', self.error_backtrace); dbms_sql.close_cursor(l_cursor_number); - + save_dbms_output; - l_completed_without_errors := process_errors_from_call(self.error_stack, self.error_backtrace); + l_completed_without_errors := (self.error_stack||self.error_backtrace) is null; a_listener.fire_after_event(self.associated_event_name, a_item); --listener - after call to executable @@ -164,5 +142,9 @@ create or replace type body ut_executable is return l_completed_without_errors; end do_execute; + member function get_error_stack_trace return varchar2 is + begin + return rtrim(self.error_stack||self.error_backtrace, chr(10)); + end; end; / diff --git a/source/core/types/ut_executable.tps b/source/core/types/ut_executable.tps index 472c5627d..b0bf49be5 100644 --- a/source/core/types/ut_executable.tps +++ b/source/core/types/ut_executable.tps @@ -26,7 +26,7 @@ create or replace type ut_executable authid current_user as object( error_stack varchar2(4000), serveroutput clob, constructor function ut_executable( self in out nocopy ut_executable, a_context ut_suite_item, a_procedure_name varchar2, a_associated_event_name varchar2) return self as result, - member function is_valid return boolean, + member function is_valid(self in out nocopy ut_executable) return boolean, member function is_defined return boolean, member function form_name return varchar2, member procedure do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base), @@ -35,6 +35,7 @@ create or replace type ut_executable authid current_user as object( * returns true if executed without exceptions * returns false if exceptions were raised */ - member function do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base) return boolean + member function do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base) return boolean, + member function get_error_stack_trace return varchar2 ) final / diff --git a/source/core/types/ut_logical_suite.tpb b/source/core/types/ut_logical_suite.tpb index da9c1f28b..b0e19a3cb 100644 --- a/source/core/types/ut_logical_suite.tpb +++ b/source/core/types/ut_logical_suite.tpb @@ -26,7 +26,7 @@ create or replace type body ut_logical_suite as return; end; - member function is_valid return boolean is + member function is_valid(self in out nocopy ut_logical_suite) return boolean is begin return true; end; @@ -58,14 +58,14 @@ create or replace type body ut_logical_suite as l_completed_without_errors boolean; begin ut_utils.debug_log('ut_logical_suite.execute'); - - a_listener.fire_before_event(ut_utils.gc_suite,self); - self.start_time := current_timestamp; - if self.get_ignore_flag() then - self.result := ut_utils.tr_ignore; + a_listener.fire_before_event(ut_utils.gc_suite,self); + self.start_time := current_timestamp; + + if self.get_disabled_flag() then + self.result := ut_utils.tr_disabled; self.end_time := self.start_time; - ut_utils.debug_log('ut_logical_suite.execute - ignored'); + ut_utils.debug_log('ut_logical_suite.execute - disabled'); else self.start_time := current_timestamp; @@ -79,7 +79,7 @@ create or replace type body ut_logical_suite as self.end_time := current_timestamp; end if; - + a_listener.fire_after_event(ut_utils.gc_suite,self); return l_completed_without_errors; @@ -100,20 +100,30 @@ create or replace type body ut_logical_suite as self.result := l_result; end; - - overriding member procedure fail(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base, a_failure_msg varchar2) is + + overriding member procedure mark_as_errored(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2) is begin ut_utils.debug_log('ut_logical_suite.fail'); a_listener.fire_before_event(ut_utils.gc_suite, self); self.start_time := current_timestamp; for i in 1 .. self.items.count loop -- execute the item (test or suite) - self.items(i).fail(a_listener,a_failure_msg); + self.items(i).mark_as_errored(a_listener, a_error_stack_trace); end loop; self.calc_execution_result(); self.end_time := self.start_time; a_listener.fire_after_event(ut_utils.gc_suite, self); - end; + end; + + overriding member function get_error_stack_traces return ut_varchar2_list is + begin + return ut_varchar2_list(); + end; + + overriding member function get_serveroutputs return clob is + begin + return null; + end; end; / diff --git a/source/core/types/ut_logical_suite.tps b/source/core/types/ut_logical_suite.tps index e90e51589..fd6d6121e 100644 --- a/source/core/types/ut_logical_suite.tps +++ b/source/core/types/ut_logical_suite.tps @@ -24,7 +24,7 @@ create or replace type ut_logical_suite under ut_suite_item ( constructor function ut_logical_suite( self in out nocopy ut_logical_suite,a_object_owner varchar2, a_object_name varchar2, a_name varchar2, a_description varchar2 := null, a_path varchar2 ) return self as result, - member function is_valid return boolean, + member function is_valid(self in out nocopy ut_logical_suite) return boolean, /** * Finds the item in the suite by it's name and returns the item index */ @@ -32,6 +32,8 @@ create or replace type ut_logical_suite under ut_suite_item ( member procedure add_item(self in out nocopy ut_logical_suite, a_item ut_suite_item), overriding member function do_execute(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base) return boolean, overriding member procedure calc_execution_result(self in out nocopy ut_logical_suite), - overriding member procedure fail(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base, a_failure_msg varchar2) + overriding member procedure mark_as_errored(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2), + overriding member function get_error_stack_traces return ut_varchar2_list, + overriding member function get_serveroutputs return clob ) not final / diff --git a/source/core/types/ut_reporter_base.tpb b/source/core/types/ut_reporter_base.tpb index 3e1cdbb49..3e735de1b 100644 --- a/source/core/types/ut_reporter_base.tpb +++ b/source/core/types/ut_reporter_base.tpb @@ -29,6 +29,17 @@ create or replace type body ut_reporter_base is ut_output_buffer.send_line(self,a_text); end; + member procedure print_clob(self in out nocopy ut_reporter_base, a_clob clob) is + l_lines ut_varchar2_list; + begin + if a_clob is not null and dbms_lob.getlength(a_clob) > 0 then + l_lines := ut_utils.clob_to_table(a_clob); + for i in 1 .. l_lines.count loop + self.print_text(l_lines(i)); + end loop; + end if; + end; + -- run hooks member procedure before_calling_run(self in out nocopy ut_reporter_base, a_run in ut_run) is begin diff --git a/source/core/types/ut_reporter_base.tps b/source/core/types/ut_reporter_base.tps index ed1e2dfce..2c6794571 100644 --- a/source/core/types/ut_reporter_base.tps +++ b/source/core/types/ut_reporter_base.tps @@ -22,6 +22,8 @@ create or replace type ut_reporter_base authid current_user as object( member procedure print_text(self in out nocopy ut_reporter_base, a_text varchar2), + member procedure print_clob(self in out nocopy ut_reporter_base, a_clob clob), + -- run hooks member procedure before_calling_run(self in out nocopy ut_reporter_base, a_run in ut_run), diff --git a/source/core/types/ut_results_counter.tpb b/source/core/types/ut_results_counter.tpb index 5c0daba51..e3136102f 100644 --- a/source/core/types/ut_results_counter.tpb +++ b/source/core/types/ut_results_counter.tpb @@ -17,7 +17,7 @@ create or replace type body ut_results_counter as */ constructor function ut_results_counter(self in out nocopy ut_results_counter) return self as result is begin - self.ignored_count := 0; + self.disabled_count := 0; self.success_count := 0; self.failure_count := 0; self.errored_count := 0; @@ -27,22 +27,23 @@ create or replace type body ut_results_counter as constructor function ut_results_counter(self in out nocopy ut_results_counter, a_status integer) return self as result is begin - self.ignored_count := case when a_status = ut_utils.tr_ignore then 1 else 0 end; - self.success_count := case when a_status = ut_utils.tr_success then 1 else 0 end; - self.failure_count := case when a_status = ut_utils.tr_failure then 1 else 0 end; - self.errored_count := case when a_status = ut_utils.tr_error then 1 else 0 end; + self.disabled_count := case when a_status = ut_utils.tr_disabled then 1 else 0 end; + self.success_count := case when a_status = ut_utils.tr_success then 1 else 0 end; + self.failure_count := case when a_status = ut_utils.tr_failure then 1 else 0 end; + self.errored_count := case when a_status = ut_utils.tr_error then 1 else 0 end; + self.warnings_count := 0; return; end; member procedure sum_counter_values(self in out nocopy ut_results_counter, a_item ut_results_counter) is begin - self.ignored_count := self.ignored_count + a_item.ignored_count; + self.disabled_count := self.disabled_count + a_item.disabled_count; self.success_count := self.success_count + a_item.success_count; self.failure_count := self.failure_count + a_item.failure_count; self.errored_count := self.errored_count + a_item.errored_count; self.warnings_count := self.warnings_count + a_item.warnings_count; end; - + member procedure increase_warning_count(self in out nocopy ut_results_counter) is begin self.warnings_count := self.warnings_count + 1; @@ -51,7 +52,7 @@ create or replace type body ut_results_counter as member function total_count return integer is begin --skip warnings here - return self.ignored_count + self.success_count + self.failure_count + self.errored_count; + return self.disabled_count + self.success_count + self.failure_count + self.errored_count; end; member function result_status return integer is @@ -63,8 +64,8 @@ create or replace type body ut_results_counter as l_result := ut_utils.tr_failure; elsif self.success_count > 0 then l_result := ut_utils.tr_success; - elsif self.ignored_count > 0 then - l_result := ut_utils.tr_ignore; + elsif self.disabled_count > 0 then + l_result := ut_utils.tr_disabled; else l_result := ut_utils.tr_error; end if; diff --git a/source/core/types/ut_results_counter.tps b/source/core/types/ut_results_counter.tps index 7d4e7a7f2..d2be0aa50 100644 --- a/source/core/types/ut_results_counter.tps +++ b/source/core/types/ut_results_counter.tps @@ -15,10 +15,10 @@ create or replace type ut_results_counter as object( See the License for the specific language governing permissions and limitations under the License. */ - ignored_count integer, - success_count integer, - failure_count integer, - errored_count integer, + disabled_count integer, + success_count integer, + failure_count integer, + errored_count integer, warnings_count integer, constructor function ut_results_counter(self in out nocopy ut_results_counter) return self as result, constructor function ut_results_counter(self in out nocopy ut_results_counter, a_status integer) return self as result, diff --git a/source/core/types/ut_run.tpb b/source/core/types/ut_run.tpb index 7e2aa2f55..08b26228c 100644 --- a/source/core/types/ut_run.tpb +++ b/source/core/types/ut_run.tpb @@ -66,7 +66,7 @@ create or replace type body ut_run as self.result := l_result; end; - overriding member procedure fail(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base, a_failure_msg varchar2) is + overriding member procedure mark_as_errored(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2) is begin ut_utils.debug_log('ut_run.fail'); @@ -74,7 +74,7 @@ create or replace type body ut_run as self.start_time := current_timestamp; for i in 1 .. self.items.count loop - self.items(i).fail(a_listener, a_failure_msg); + self.items(i).mark_as_errored(a_listener, a_error_stack_trace); end loop; self.calc_execution_result(); @@ -118,5 +118,17 @@ create or replace type body ut_run as return l_schemes; end; + + overriding member function get_error_stack_traces return ut_varchar2_list is + begin + return ut_varchar2_list(); + end; + + overriding member function get_serveroutputs return clob is + begin + return null; + end; + + end; / diff --git a/source/core/types/ut_run.tps b/source/core/types/ut_run.tps index 2ac7d2a9b..06ccc4ddf 100644 --- a/source/core/types/ut_run.tps +++ b/source/core/types/ut_run.tps @@ -23,7 +23,9 @@ create or replace type ut_run under ut_suite_item ( constructor function ut_run( self in out nocopy ut_run, a_items ut_suite_items, a_run_paths ut_varchar2_list := null) return self as result, overriding member function do_execute(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base) return boolean, overriding member procedure calc_execution_result(self in out nocopy ut_run), - overriding member procedure fail(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base, a_failure_msg varchar2), - member function get_run_schemes return ut_varchar2_list + overriding member procedure mark_as_errored(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2), + member function get_run_schemes return ut_varchar2_list, + overriding member function get_error_stack_traces return ut_varchar2_list, + overriding member function get_serveroutputs return clob ) / diff --git a/source/core/types/ut_suite.tpb b/source/core/types/ut_suite.tpb index 87b1e1859..09d316ec6 100644 --- a/source/core/types/ut_suite.tpb +++ b/source/core/types/ut_suite.tpb @@ -18,19 +18,19 @@ create or replace type body ut_suite as constructor function ut_suite ( self in out nocopy ut_suite , a_object_owner varchar2 := null, a_object_name varchar2, a_name varchar2, a_path varchar2, a_description varchar2 := null, - a_rollback_type integer := null, a_ignore_flag boolean := false, a_before_all_proc_name varchar2 := null, + a_rollback_type integer := null, a_disabled_flag boolean := false, a_before_all_proc_name varchar2 := null, a_after_all_proc_name varchar2 := null ) return self as result is begin self.self_type := $$plsql_unit; - self.init(a_object_owner, a_object_name, a_name, a_description, a_path, a_rollback_type, a_ignore_flag); + self.init(a_object_owner, a_object_name, a_name, a_description, a_path, a_rollback_type, a_disabled_flag); self.before_all := ut_executable(self, a_before_all_proc_name, ut_utils.gc_before_all); self.items := ut_suite_items(); self.after_all := ut_executable(self, a_after_all_proc_name, ut_utils.gc_after_all); return; end; - overriding member function is_valid return boolean is + overriding member function is_valid(self in out nocopy ut_suite) return boolean is l_is_valid boolean; begin l_is_valid := @@ -44,11 +44,10 @@ create or replace type body ut_suite as l_item_savepoint varchar2(30); l_suite_step_without_errors boolean; - procedure do_fail(a_prefix varchar2) is - l_results ut_assert_results := ut_assert_processor.get_asserts_results(); + procedure propagate_error(a_error_stack_trace varchar2) is begin for i in 1..self.items.count loop - self.items(i).fail(a_listener, a_prefix||l_results(1).error_message); + self.items(i).mark_as_errored(a_listener, a_error_stack_trace); end loop; end; begin @@ -57,10 +56,10 @@ create or replace type body ut_suite as self.start_time := current_timestamp; - if self.get_ignore_flag() then - self.result := ut_utils.tr_ignore; + if self.get_disabled_flag() then + self.result := ut_utils.tr_disabled; self.end_time := self.start_time; - ut_utils.debug_log('ut_suite .execute - ignored'); + ut_utils.debug_log('ut_suite.execute - disabled'); else if self.is_valid() then @@ -75,18 +74,18 @@ create or replace type body ut_suite as self.items(i).do_execute(a_listener); end loop; else - do_fail('Beforeall procedure failed: '||chr(10)); + propagate_error(self.before_all.get_error_stack_trace()); end if; l_suite_step_without_errors := self.after_all.do_execute(self, a_listener); if not l_suite_step_without_errors then - self.put_warning('Afterall procedure failed: '||chr(10)||ut_assert_processor.get_asserts_results()(1).error_message); + self.put_warning(self.after_all.get_error_stack_trace()); end if; self.rollback_to_savepoint(l_suite_savepoint); else - do_fail(null); + propagate_error(ut_utils.table_to_clob(self.get_error_stack_traces())); end if; self.calc_execution_result(); @@ -98,5 +97,21 @@ create or replace type body ut_suite as return l_suite_step_without_errors; end; + overriding member function get_error_stack_traces(self ut_suite) return ut_varchar2_list is + l_stack_traces ut_varchar2_list := ut_varchar2_list(); + begin + ut_utils.append_to_varchar2_list(l_stack_traces, self.before_all.get_error_stack_trace()); + ut_utils.append_to_varchar2_list(l_stack_traces, self.after_all.get_error_stack_trace()); + return l_stack_traces; + end; + + overriding member function get_serveroutputs return clob is + l_outputs clob; + begin + ut_utils.append_to_clob(l_outputs, self.before_all.serveroutput ); + ut_utils.append_to_clob(l_outputs, self.after_all.serveroutput ); + return l_outputs; + end; + end; / diff --git a/source/core/types/ut_suite.tps b/source/core/types/ut_suite.tps index 0570c6ee8..636123520 100644 --- a/source/core/types/ut_suite.tps +++ b/source/core/types/ut_suite.tps @@ -28,13 +28,15 @@ create or replace type ut_suite under ut_logical_suite ( after_all ut_executable, constructor function ut_suite ( self in out nocopy ut_suite , a_object_owner varchar2 := null, a_object_name varchar2, a_name varchar2, a_path varchar2, a_description varchar2 := null, - a_rollback_type integer := null, a_ignore_flag boolean := false, a_before_all_proc_name varchar2 := null, + a_rollback_type integer := null, a_disabled_flag boolean := false, a_before_all_proc_name varchar2 := null, a_after_all_proc_name varchar2 := null ) return self as result, - overriding member function is_valid return boolean, + overriding member function is_valid(self in out nocopy ut_suite) return boolean, /** * Finds the item in the suite by it's name and returns the item index */ - overriding member function do_execute(self in out nocopy ut_suite , a_listener in out nocopy ut_event_listener_base) return boolean + overriding member function do_execute(self in out nocopy ut_suite , a_listener in out nocopy ut_event_listener_base) return boolean, + overriding member function get_error_stack_traces(self ut_suite) return ut_varchar2_list, + overriding member function get_serveroutputs return clob ) / diff --git a/source/core/types/ut_suite_item.tpb b/source/core/types/ut_suite_item.tpb index 394f64983..7d1a88bd2 100644 --- a/source/core/types/ut_suite_item.tpb +++ b/source/core/types/ut_suite_item.tpb @@ -18,7 +18,7 @@ create or replace type body ut_suite_item as member procedure init( self in out nocopy ut_suite_item, a_object_owner varchar2, a_object_name varchar2, a_name varchar2, - a_description varchar2, a_path varchar2, a_rollback_type integer, a_ignore_flag boolean + a_description varchar2, a_path varchar2, a_rollback_type integer, a_disabled_flag boolean ) is begin self.object_owner := a_object_owner; @@ -27,26 +27,26 @@ create or replace type body ut_suite_item as self.description := a_description; self.path := nvl(lower(trim(a_path)), self.object_name); self.rollback_type := a_rollback_type; - self.ignore_flag := ut_utils.boolean_to_int(a_ignore_flag); + self.disabled_flag := ut_utils.boolean_to_int(a_disabled_flag); self.results_count := ut_results_counter(); self.warnings := ut_varchar2_list(); end; - member procedure set_ignore_flag(self in out nocopy ut_suite_item, a_ignore_flag boolean) is + member procedure set_disabled_flag(self in out nocopy ut_suite_item, a_disabled_flag boolean) is begin - self.ignore_flag := ut_utils.boolean_to_int(a_ignore_flag); + self.disabled_flag := ut_utils.boolean_to_int(a_disabled_flag); end; - member function get_ignore_flag return boolean is + member function get_disabled_flag return boolean is begin - return ut_utils.int_to_boolean(self.ignore_flag); + return ut_utils.int_to_boolean(self.disabled_flag); end; - + final member procedure do_execute(self in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base) is l_completed_without_errors boolean; begin l_completed_without_errors := self.do_execute(a_listener); - end; + end; member function create_savepoint_if_needed return varchar2 is l_savepoint varchar2(30); @@ -74,7 +74,7 @@ create or replace type body ut_suite_item as begin return ut_utils.time_diff(start_time, end_time); end; - + member procedure put_warning(self in out nocopy ut_suite_item, a_message varchar2) is begin self.warnings.extend; diff --git a/source/core/types/ut_suite_item.tps b/source/core/types/ut_suite_item.tps index 4023231c5..5a4ee05c8 100644 --- a/source/core/types/ut_suite_item.tps +++ b/source/core/types/ut_suite_item.tps @@ -1,4 +1,4 @@ -create or replace type ut_suite_item under ut_suite_item_base ( +create or replace type ut_suite_item force under ut_suite_item_base ( /* utPLSQL - Version X.X.X.X Copyright 2016 - 2017 utPLSQL Project @@ -19,9 +19,9 @@ create or replace type ut_suite_item under ut_suite_item_base ( results_count ut_results_counter, member procedure init( self in out nocopy ut_suite_item, a_object_owner varchar2, a_object_name varchar2, a_name varchar2, - a_description varchar2, a_path varchar2, a_rollback_type integer, a_ignore_flag boolean), - member procedure set_ignore_flag(self in out nocopy ut_suite_item, a_ignore_flag boolean), - member function get_ignore_flag return boolean, + a_description varchar2, a_path varchar2, a_rollback_type integer, a_disabled_flag boolean), + member procedure set_disabled_flag(self in out nocopy ut_suite_item, a_disabled_flag boolean), + member function get_disabled_flag return boolean, member function create_savepoint_if_needed return varchar2, member procedure rollback_to_savepoint(self in ut_suite_item, a_savepoint varchar2), member function execution_time return number, @@ -29,9 +29,10 @@ create or replace type ut_suite_item under ut_suite_item_base ( not instantiable member function do_execute(self in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base) return boolean, final member procedure do_execute(self in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base), not instantiable member procedure calc_execution_result(self in out nocopy ut_suite_item), - not instantiable member procedure fail(self in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base, a_failure_msg varchar2), + not instantiable member procedure mark_as_errored(self in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2), + not instantiable member function get_error_stack_traces return ut_varchar2_list, + not instantiable member function get_serveroutputs return clob, member procedure put_warning(self in out nocopy ut_suite_item, a_message varchar2) - ) not final not instantiable / diff --git a/source/core/types/ut_suite_item_base.tps b/source/core/types/ut_suite_item_base.tps index bff144dec..021289e18 100644 --- a/source/core/types/ut_suite_item_base.tps +++ b/source/core/types/ut_suite_item_base.tps @@ -47,9 +47,9 @@ create or replace type ut_suite_item_base authid current_user as object ( */ rollback_type integer(1), /** - * Indicates if the test is to be ignored by execution + * Indicates if the test is to be disabled by execution */ - ignore_flag integer(1), + disabled_flag integer(1), --execution result fields start_time timestamp with time zone, end_time timestamp with time zone, diff --git a/source/core/types/ut_test.tpb b/source/core/types/ut_test.tpb index 615720489..7cabdf1b7 100644 --- a/source/core/types/ut_test.tpb +++ b/source/core/types/ut_test.tpb @@ -18,13 +18,13 @@ create or replace type body ut_test as constructor function ut_test( self in out nocopy ut_test, a_object_owner varchar2 := null, a_object_name varchar2, a_name varchar2, a_description varchar2 := null, - a_path varchar2 := null, a_rollback_type integer := null, a_ignore_flag boolean := false, + a_path varchar2 := null, a_rollback_type integer := null, a_disabled_flag boolean := false, a_before_each_proc_name varchar2 := null, a_before_test_proc_name varchar2 := null, a_after_test_proc_name varchar2 := null, a_after_each_proc_name varchar2 := null ) return self as result is begin self.self_type := $$plsql_unit; - self.init(a_object_owner, a_object_name, a_name, a_description, a_path, a_rollback_type, a_ignore_flag); + self.init(a_object_owner, a_object_name, a_name, a_description, a_path, a_rollback_type, a_disabled_flag); self.before_each := ut_executable(self, a_before_each_proc_name, ut_utils.gc_before_each); self.before_test := ut_executable(self, a_before_test_proc_name, ut_utils.gc_before_test); self.item := ut_executable(self, a_name, ut_utils.gc_test_execute); @@ -33,7 +33,7 @@ create or replace type body ut_test as return; end; - member function is_valid return boolean is + member function is_valid(self in out nocopy ut_test) return boolean is l_is_valid boolean; begin l_is_valid := @@ -55,9 +55,9 @@ create or replace type body ut_test as a_listener.fire_before_event(ut_utils.gc_test,self); self.start_time := current_timestamp; - if self.get_ignore_flag() then - self.result := ut_utils.tr_ignore; - ut_utils.debug_log('ut_test.execute - ignored'); + if self.get_disabled_flag() then + self.result := ut_utils.tr_disabled; + ut_utils.debug_log('ut_test.execute - disabled'); self.results_count := ut_results_counter(self.result); self.end_time := self.start_time; else @@ -67,7 +67,7 @@ create or replace type body ut_test as --includes listener calls for before and after actions l_completed_without_errors := self.before_each.do_execute(self, a_listener); - + if l_completed_without_errors then l_completed_without_errors := self.before_test.do_execute(self, a_listener); @@ -79,11 +79,11 @@ create or replace type body ut_test as -- perform cleanup regardless of the test or setup failure self.after_test.do_execute(self, a_listener); end if; - + self.after_each.do_execute(self, a_listener); self.rollback_to_savepoint(l_savepoint); end if; - + self.calc_execution_result(); self.end_time := current_timestamp; end if; @@ -93,23 +93,47 @@ create or replace type body ut_test as overriding member procedure calc_execution_result(self in out nocopy ut_test) is begin - self.result := ut_assert_processor.get_aggregate_asserts_result(); + if self.get_error_stack_traces().count = 0 then + self.result := ut_assert_processor.get_aggregate_asserts_result(); + else + self.result := ut_utils.tr_error; + end if; --expectation results need to be part of test results self.results := ut_assert_processor.get_asserts_results(); self.results_count := ut_results_counter(self.result); end; - overriding member procedure fail(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base, a_failure_msg varchar2) is + overriding member procedure mark_as_errored(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2) is begin ut_utils.debug_log('ut_test.fail'); a_listener.fire_before_event(ut_utils.gc_test, self); self.start_time := current_timestamp; - ut_assert_processor.report_error(a_failure_msg); + self.parent_error_stack_trace := a_error_stack_trace; self.calc_execution_result(); self.end_time := self.start_time; a_listener.fire_after_event(ut_utils.gc_test, self); end; - + overriding member function get_error_stack_traces(self ut_test) return ut_varchar2_list is + l_stack_traces ut_varchar2_list := ut_varchar2_list(); + begin + ut_utils.append_to_varchar2_list(l_stack_traces, self.parent_error_stack_trace); + ut_utils.append_to_varchar2_list(l_stack_traces, self.before_each.get_error_stack_trace()); + ut_utils.append_to_varchar2_list(l_stack_traces, self.before_test.get_error_stack_trace()); + ut_utils.append_to_varchar2_list(l_stack_traces, self.item.get_error_stack_trace()); + ut_utils.append_to_varchar2_list(l_stack_traces, self.after_test.get_error_stack_trace()); + ut_utils.append_to_varchar2_list(l_stack_traces, self.after_each.get_error_stack_trace()); + return l_stack_traces; + end; + overriding member function get_serveroutputs return clob is + l_outputs clob; + begin + ut_utils.append_to_clob(l_outputs, self.before_each.serveroutput ); + ut_utils.append_to_clob(l_outputs, self.before_test.serveroutput ); + ut_utils.append_to_clob(l_outputs, self.item.serveroutput ); + ut_utils.append_to_clob(l_outputs, self.after_test.serveroutput ); + ut_utils.append_to_clob(l_outputs, self.after_each.serveroutput ); + return l_outputs; + end; end; / diff --git a/source/core/types/ut_test.tps b/source/core/types/ut_test.tps index fbe90a5b0..4f3b8aea4 100644 --- a/source/core/types/ut_test.tps +++ b/source/core/types/ut_test.tps @@ -44,15 +44,18 @@ create or replace type ut_test under ut_suite_item ( * The test procedure and the before_test/after_test blocks */ results ut_assert_results, + parent_error_stack_trace varchar2(4000), constructor function ut_test( self in out nocopy ut_test, a_object_owner varchar2 := null, a_object_name varchar2, a_name varchar2, a_description varchar2 := null, - a_path varchar2 := null, a_rollback_type integer := null, a_ignore_flag boolean := false, + a_path varchar2 := null, a_rollback_type integer := null, a_disabled_flag boolean := false, a_before_each_proc_name varchar2 := null, a_before_test_proc_name varchar2 := null, a_after_test_proc_name varchar2 := null, a_after_each_proc_name varchar2 := null ) return self as result, - member function is_valid return boolean, + member function is_valid(self in out nocopy ut_test) return boolean, overriding member function do_execute(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base) return boolean, overriding member procedure calc_execution_result(self in out nocopy ut_test), - overriding member procedure fail(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base, a_failure_msg varchar2) + overriding member procedure mark_as_errored(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base, a_error_stack_trace varchar2), + overriding member function get_error_stack_traces(self ut_test) return ut_varchar2_list, + overriding member function get_serveroutputs return clob ) / diff --git a/source/core/ut_assert_processor.pkb b/source/core/ut_assert_processor.pkb index 1071ad091..65724470f 100644 --- a/source/core/ut_assert_processor.pkb +++ b/source/core/ut_assert_processor.pkb @@ -69,9 +69,9 @@ create or replace package body ut_assert_processor as g_asserts_called(g_asserts_called.last) := a_assert_result; end; - procedure report_error(a_message in varchar2) is + procedure report_failure(a_message in varchar2) is begin - add_assert_result(ut_assert_result(ut_utils.tr_error, a_message)); + add_assert_result(ut_assert_result(ut_utils.tr_failure, a_message)); end; function get_session_parameters return tt_nls_params is diff --git a/source/core/ut_assert_processor.pks b/source/core/ut_assert_processor.pks index 3e2a5e1e8..2b7e1fec3 100644 --- a/source/core/ut_assert_processor.pks +++ b/source/core/ut_assert_processor.pks @@ -32,7 +32,7 @@ create or replace package ut_assert_processor authid current_user as procedure add_assert_result(a_assert_result ut_assert_result); - procedure report_error(a_message in varchar2); + procedure report_failure(a_message in varchar2); procedure set_xml_nls_params; diff --git a/source/core/ut_metadata.pkb b/source/core/ut_metadata.pkb index 4b96fa783..51e9cc300 100644 --- a/source/core/ut_metadata.pkb +++ b/source/core/ut_metadata.pkb @@ -121,10 +121,8 @@ create or replace package body ut_metadata as schema_name => a_owner, object_name => a_object_name); - sys.dbms_lob.createtemporary(lob_loc => l_source, cache => true); - for i in 1..l_lines.count loop - sys.dbms_lob.writeappend(l_source, length(l_lines(i)), l_lines(i)); + ut_utils.append_to_clob(l_source, l_lines(i)); end loop; end; diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 213691b04..52056b2be 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -118,7 +118,7 @@ create or replace package body ut_suite_manager is a_path => l_suite_path, --a patch for this suite (excluding the package name of current suite) a_description => l_suite_name, a_rollback_type => l_suite_rollback, - a_ignore_flag => l_annotation_data.package_annotations.exists('disabled'), + a_disabled_flag => l_annotation_data.package_annotations.exists('disabled'), a_before_all_proc_name => l_suite_setup_proc, a_after_all_proc_name => l_suite_teardown_proc ); @@ -138,17 +138,17 @@ create or replace package body ut_suite_manager is if l_proc_annotations.exists('beforetest') then l_beforetest_procedure := ut_annotations.get_annotation_param(l_proc_annotations('beforetest'), 1); end if; - + if l_proc_annotations.exists('aftertest') then l_aftertest_procedure := ut_annotations.get_annotation_param(l_proc_annotations('aftertest'), 1); end if; - + if l_proc_annotations.exists('displayname') then l_displayname := ut_annotations.get_annotation_param(l_proc_annotations('displayname'), 1); elsif l_proc_annotations('test').count > 0 then l_displayname := ut_annotations.get_annotation_param(l_proc_annotations('test'), 1); end if; - + if l_proc_annotations.exists('rollback') then l_rollback_annotation := ut_annotations.get_annotation_param(l_proc_annotations('rollback'), 1); l_rollback_type := case lower(l_rollback_annotation) @@ -162,19 +162,19 @@ create or replace package body ut_suite_manager is l_suite_rollback end; end if; - + l_test := ut_test(a_object_owner => l_owner_name ,a_object_name => l_object_name ,a_name => l_proc_name ,a_description => l_displayname ,a_path => l_suite.path || '.' || l_proc_name ,a_rollback_type => l_rollback_type - ,a_ignore_flag => l_proc_annotations.exists('disabled') + ,a_disabled_flag => l_proc_annotations.exists('disabled') ,a_before_test_proc_name => l_beforetest_procedure ,a_after_test_proc_name => l_aftertest_procedure ,a_before_each_proc_name => l_default_setup_proc ,a_after_each_proc_name => l_default_teardown_proc); - + l_suite.add_item(l_test); end; end if; @@ -405,7 +405,7 @@ create or replace package body ut_suite_manager is l_item_name varchar2(32767); begin - a_suite.set_ignore_flag(false); + a_suite.set_disabled_flag(false); if a_path is not null and a_suite is not null and a_suite is of (ut_logical_suite) then l_suite := treat(a_suite as ut_logical_suite); diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index fd2aa879a..aee488e5d 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -30,8 +30,8 @@ create or replace package body ut_utils is l_result := tr_failure_char; elsif a_test_result = tr_error then l_result := tr_error_char; - elsif a_test_result = tr_ignore then - l_result := tr_ignore_char; + elsif a_test_result = tr_disabled then + l_result := tr_disabled_char; else l_result := 'Unknown(' || coalesce(to_char(a_test_result),'NULL') || ')'; end if ; @@ -184,7 +184,6 @@ create or replace package body ut_utils is function string_to_table(a_string varchar2, a_delimiter varchar2:= chr(10), a_skip_leading_delimiter varchar2 := 'N') return ut_varchar2_list is l_offset integer := 1; - l_length integer; l_delimiter_position integer; l_skip_leading_delimiter boolean := coalesce(a_skip_leading_delimiter = 'Y',false); l_result ut_varchar2_list := ut_varchar2_list(); @@ -195,7 +194,7 @@ create or replace package body ut_utils is if a_delimiter is null then return ut_varchar2_list(a_string); end if; - l_length := length(a_string); + loop l_delimiter_position := instr(a_string, a_delimiter, l_offset); if not (l_delimiter_position = 1 and l_skip_leading_delimiter) then @@ -259,10 +258,8 @@ create or replace package body ut_utils is l_result clob; l_text_table_rows integer := coalesce(cardinality(a_text_table),0); begin - - dbms_lob.createtemporary(l_result, true); for i in 1 .. l_text_table_rows loop - dbms_lob.writeappend(l_result, length(a_text_table(i)), a_text_table(i)); + append_to_clob(l_result, a_text_table(i)); end loop; return l_result; end; @@ -292,5 +289,35 @@ create or replace package body ut_utils is return l_result; end; + procedure append_to_varchar2_list(a_list in out nocopy ut_varchar2_list, a_line varchar2) is + begin + if a_line is not null then + if a_list is null then + a_list := ut_varchar2_list(); + end if; + a_list.extend; + a_list(a_list.last) := a_line; + end if; + end append_to_varchar2_list; + + procedure append_to_clob(a_src_clob in out nocopy clob, a_new_data clob) is + begin + if a_new_data is not null and dbms_lob.getlength(a_new_data) > 0 then + if a_src_clob is null then + dbms_lob.createtemporary(a_src_clob, true); + end if; + dbms_lob.append(a_src_clob, a_new_data); + end if; + end; + procedure append_to_clob(a_src_clob in out nocopy clob, a_new_data varchar2) is + begin + if a_new_data is not null then + if a_src_clob is null then + dbms_lob.createtemporary(a_src_clob, true); + end if; + dbms_lob.writeappend(a_src_clob, length(a_new_data), a_new_data); + end if; + end; + end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 78843445f..f5e6f6eb6 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -36,12 +36,12 @@ create or replace package ut_utils authid definer is gc_after_all constant varchar2(12) := 'after_all'; /* Constants: Test Results */ - tr_ignore constant number(1) := 0; -- test/suite was ignored + tr_disabled constant number(1) := 0; -- test/suite was disabled tr_success constant number(1) := 1; -- test passed tr_failure constant number(1) := 2; -- one or more asserts failed tr_error constant number(1) := 3; -- exception was raised - tr_ignore_char constant varchar2(6) := 'Ignore'; -- test/suite was ignored + tr_disabled_char constant varchar2(8) := 'Disabled'; -- test/suite was disabled tr_success_char constant varchar2(7) := 'Success'; -- test passed tr_failure_char constant varchar2(7) := 'Failure'; -- one or more asserts failed tr_error_char constant varchar2(5) := 'Error'; -- exception was raised @@ -199,5 +199,13 @@ create or replace package ut_utils authid definer is */ function get_utplsql_objects_list return ut_object_names; + /* + * Append a line to the end of ut_varchar2_lst + */ + procedure append_to_varchar2_list(a_list in out nocopy ut_varchar2_list, a_line varchar2); + + procedure append_to_clob(a_src_clob in out nocopy clob, a_new_data clob); + procedure append_to_clob(a_src_clob in out nocopy clob, a_new_data varchar2); + end ut_utils; / diff --git a/source/reporters/ut_coverage_html_reporter.tpb b/source/reporters/ut_coverage_html_reporter.tpb index b0d715238..a4e39c4b3 100644 --- a/source/reporters/ut_coverage_html_reporter.tpb +++ b/source/reporters/ut_coverage_html_reporter.tpb @@ -102,10 +102,7 @@ create or replace type body ut_coverage_html_reporter is l_coverage_data := ut_coverage.get_coverage_data(); - l_report_lines := ut_utils.clob_to_table(ut_coverage_report_html_helper.get_index( l_coverage_data, self.assets_path, self.project_name )); - for i in 1 .. l_report_lines.count loop - self.print_text( l_report_lines(i) ); - end loop; + self.print_clob( ut_coverage_report_html_helper.get_index( l_coverage_data, self.assets_path, self.project_name ) ); (self as ut_reporter_base).after_calling_run(a_run); end; diff --git a/source/reporters/ut_coverage_report_html_helper.pkb b/source/reporters/ut_coverage_report_html_helper.pkb index e1009f4cf..6ee93399d 100644 --- a/source/reporters/ut_coverage_report_html_helper.pkb +++ b/source/reporters/ut_coverage_report_html_helper.pkb @@ -26,7 +26,7 @@ create or replace package body ut_coverage_report_html_helper is gc_missed constant varchar2(7) := 'missed'; gc_skipped constant varchar2(7) := 'skipped'; - gc_ignored constant varchar2(7) := 'never'; + gc_disabled constant varchar2(7) := 'never'; gc_covered constant varchar2(7) := 'covered'; @@ -58,7 +58,7 @@ create or replace package body ut_coverage_report_html_helper is case when a_executions > 0 then gc_covered when a_executions = 0 then gc_missed - else gc_ignored + else gc_disabled end; return l_result; end; diff --git a/source/reporters/ut_coverage_sonar_reporter.tpb b/source/reporters/ut_coverage_sonar_reporter.tpb index 2b9f2975f..3c6d87243 100644 --- a/source/reporters/ut_coverage_sonar_reporter.tpb +++ b/source/reporters/ut_coverage_sonar_reporter.tpb @@ -140,10 +140,7 @@ create or replace type body ut_coverage_sonar_reporter is l_coverage_data := ut_coverage.get_coverage_data(); - l_report_lines := ut_utils.clob_to_table(get_coverage_xml( l_coverage_data )); - for i in 1 .. l_report_lines.count loop - self.print_text( l_report_lines(i) ); - end loop; + self.print_clob( get_coverage_xml( l_coverage_data ) ); (self as ut_reporter_base).after_calling_run(a_run); end; diff --git a/source/reporters/ut_coveralls_reporter.tpb b/source/reporters/ut_coveralls_reporter.tpb index 7972b62d1..a77811dfd 100644 --- a/source/reporters/ut_coveralls_reporter.tpb +++ b/source/reporters/ut_coveralls_reporter.tpb @@ -154,10 +154,7 @@ create or replace type body ut_coveralls_reporter is l_coverage_data := ut_coverage.get_coverage_data(); - l_report_lines := ut_utils.clob_to_table(get_coverage_json( l_coverage_data )); - for i in 1 .. l_report_lines.count loop - self.print_text( l_report_lines(i) ); - end loop; + self.print_clob( get_coverage_json( l_coverage_data ) ); (self as ut_reporter_base).after_calling_run(a_run); end; diff --git a/source/reporters/ut_documentation_reporter.tpb b/source/reporters/ut_documentation_reporter.tpb index 5488c7c9f..b71b977d3 100644 --- a/source/reporters/ut_documentation_reporter.tpb +++ b/source/reporters/ut_documentation_reporter.tpb @@ -2,13 +2,13 @@ create or replace type body ut_documentation_reporter is /* utPLSQL - Version X.X.X.X Copyright 2016 - 2017 utPLSQL Project - + Licensed under the Apache License, Version 2.0 (the "License"): you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -29,25 +29,17 @@ create or replace type body ut_documentation_reporter is return rpad(' ', self.lvl * 2); end tab; - member procedure print_output(a_executable ut_executable) is + overriding member procedure print_text(self in out nocopy ut_documentation_reporter, a_text varchar2) is l_lines ut_varchar2_list; begin - if a_executable is not null and a_executable.is_defined and a_executable.serveroutput is not null and - dbms_lob.getlength(a_executable.serveroutput) > 0 then - l_lines := ut_utils.clob_to_table(a_executable.serveroutput); + if a_text is not null then + l_lines := ut_utils.string_to_table(a_text); for i in 1 .. l_lines.count loop - self.print_text(l_lines(i)); + (self as ut_reporter_base).print_text(tab || l_lines(i)); end loop; end if; end; - overriding member procedure print_text(self in out nocopy ut_documentation_reporter, a_text varchar2) is - begin - if a_text is not null then - (self as ut_reporter_base).print_text(tab || a_text); - end if; - end; - overriding member procedure before_calling_suite(self in out nocopy ut_documentation_reporter, a_suite ut_logical_suite) as begin self.print_text(coalesce(a_suite.description, a_suite.name)); @@ -56,11 +48,11 @@ create or replace type body ut_documentation_reporter is overriding member procedure after_calling_test(self in out nocopy ut_documentation_reporter, a_test ut_test) as l_message varchar2(4000); - + begin l_message := coalesce(a_test.description, a_test.name); --if test failed, then add it to the failures list, print failure with number - if a_test.result = ut_utils.tr_ignore then + if a_test.result = ut_utils.tr_disabled then self.print_yellow_text(l_message || ' (IGNORED)'); elsif a_test.result = ut_utils.tr_success then self.print_green_text(l_message); @@ -68,22 +60,19 @@ create or replace type body ut_documentation_reporter is failed_test_running_count := failed_test_running_count + 1; self.print_red_text(l_message || ' (FAILED - ' || failed_test_running_count || ')'); end if; - + -- reproduce the output from before/after procedures and the test - print_output(a_test.before_each); - print_output(a_test.before_test); - print_output(a_test.item); - print_output(a_test.after_test); - print_output(a_test.after_each); + self.print_clob(a_test.get_serveroutputs); end; - overriding member procedure after_calling_after_all(self in out nocopy ut_documentation_reporter, a_suite in ut_logical_suite) is + overriding member procedure after_calling_before_all(self in out nocopy ut_documentation_reporter, a_suite in ut_logical_suite) is begin - self.print_output(treat(a_suite as ut_suite).after_all); + self.print_clob(treat(a_suite as ut_suite).before_all.serveroutput); end; - overriding member procedure after_calling_before_all(self in out nocopy ut_documentation_reporter, a_suite in ut_logical_suite) is + + overriding member procedure after_calling_after_all(self in out nocopy ut_documentation_reporter, a_suite in ut_logical_suite) is begin - self.print_output(treat(a_suite as ut_suite).before_all); + self.print_clob(treat(a_suite as ut_suite).after_all.serveroutput); end; overriding member procedure after_calling_suite(self in out nocopy ut_documentation_reporter, a_suite ut_logical_suite) as @@ -95,8 +84,7 @@ create or replace type body ut_documentation_reporter is end; overriding member procedure after_calling_run(self in out nocopy ut_documentation_reporter, a_run in ut_run) as - l_summary_text varchar2(4000); - l_warnings ut_varchar2_list := ut_varchar2_list(); + l_summary_text varchar2(4000); procedure print_failure_for_assert(a_assert ut_assert_result) is l_lines ut_varchar2_list; begin @@ -107,7 +95,7 @@ create or replace type body ut_documentation_reporter is self.print_cyan_text(a_assert.caller_info); self.print_text(' '); end; - + procedure print_failures_for_test(a_test ut_test, a_failure_no in out nocopy integer) is begin if a_test.result > ut_utils.tr_success then @@ -115,15 +103,19 @@ create or replace type body ut_documentation_reporter is self.print_text(lpad(a_failure_no, length(failed_test_running_count) + 2, ' ') || ') ' || nvl(a_test.name, a_test.item.form_name)); self.lvl := self.lvl + 3; + + self.print_red_text(ut_utils.table_to_clob(a_test.get_error_stack_traces())); + for j in 1 .. a_test.results.count loop if a_test.results(j).result > ut_utils.tr_success then print_failure_for_assert(a_test.results(j)); end if; end loop; - lvl := lvl - 3; + + self.lvl := self.lvl - 3; end if; end; - + procedure print_failures_from_suite(a_suite ut_logical_suite, a_failure_no in out nocopy integer) is begin for i in 1 .. a_suite.items.count loop @@ -134,12 +126,12 @@ create or replace type body ut_documentation_reporter is end if; end loop; end; - + procedure print_failures_details(a_run in ut_run) is l_failure_no integer := 0; begin if a_run.results_count.failure_count > 0 or a_run.results_count.errored_count > 0 then - + self.print_text('Failures:'); self.print_text(' '); for i in 1 .. a_run.items.count loop @@ -147,58 +139,49 @@ create or replace type body ut_documentation_reporter is end loop; end if; end; - - procedure print_warnings(a_run in ut_run) is - procedure gather_warnings(a_item ut_suite_item) is - l_suite ut_logical_suite; - begin - --process warnings of child items first - if a_item is of(ut_logical_suite) then - l_suite := treat(a_item as ut_logical_suite); - for item_ind in 1 .. l_suite.items.count loop - gather_warnings(l_suite.items(item_ind)); - end loop; - end if; - - --then process self warnings - if a_item.warnings is not null and a_item.warnings.count > 0 then - for warn_ind in 1 .. a_item.warnings.count loop - l_warnings.extend; - l_warnings(l_warnings.last) := ' ' || l_warnings.last || ') ' || a_item.path || ' - ' || - regexp_replace(a_item.warnings(warn_ind) - ,'(' || chr(10) || '|' || chr(13) || ')' - ,'\1 '); - end loop; - end if; - end; + + procedure print_item_warnings(a_item in ut_logical_suite) is + l_suite ut_logical_suite; begin - if a_run.items is not null and a_run.items.count > 0 then - for run_item in 1 .. a_run.items.count loop - gather_warnings(a_run.items(run_item)); + for i in 1 .. a_item.items.count loop + if a_item.items(i) is of(ut_logical_suite) then + print_item_warnings(treat(a_item.items(i) as ut_logical_suite)); + end if; + end loop; + + if a_item.warnings is not null and a_item.warnings.count > 0 then + for i in 1 .. a_item.warnings.count loop + self.print_text(' ' || i || ') ' || a_item.path); + self.lvl := self.lvl + 3; + self.print_red_text(a_item.warnings(i)); + self.lvl := self.lvl - 3; end loop; + self.print_text(' '); end if; - - if l_warnings.count > 0 then + end; + + procedure print_warnings(a_run in ut_run) is + l_suite ut_logical_suite; + begin + if a_run.results_count.warnings_count > 0 then + self.print_text(' '); self.print_text('Warnings:'); self.print_text(' '); - for i in 1 .. l_warnings.count loop - self.print_text(l_warnings(i)); - self.print_text(' '); + for i in 1 .. a_run.items.count loop + print_item_warnings(treat(a_run.items(i) as ut_logical_suite)); end loop; end if; end; - + begin print_failures_details(a_run); print_warnings(a_run); self.print_text('Finished in ' || a_run.execution_time || ' seconds'); - l_summary_text := a_run.results_count.total_count || ' tests, ' || a_run.results_count.failure_count || ' failed, ' || - a_run.results_count.errored_count || ' errored, ' || a_run.results_count.ignored_count || - ' ignored.' || case - when l_warnings.count > 0 then - ' ' || l_warnings.count || ' warning(s)' - end; - if a_run.results_count.failure_count > 0 then + l_summary_text := + a_run.results_count.total_count || ' tests, ' + || a_run.results_count.failure_count || ' failed, ' || a_run.results_count.errored_count || ' errored, ' + || a_run.results_count.disabled_count ||' disabled, ' || a_run.results_count.warnings_count || ' warning(s)'; + if a_run.results_count.failure_count + a_run.results_count.errored_count + a_run.results_count.warnings_count > 0 then self.print_red_text(l_summary_text); else self.print_green_text(l_summary_text); diff --git a/source/reporters/ut_documentation_reporter.tps b/source/reporters/ut_documentation_reporter.tps index 7d7b2471f..e1aa653b1 100644 --- a/source/reporters/ut_documentation_reporter.tps +++ b/source/reporters/ut_documentation_reporter.tps @@ -19,7 +19,6 @@ create or replace type ut_documentation_reporter under ut_console_reporter_base( failed_test_running_count integer, constructor function ut_documentation_reporter(self in out nocopy ut_documentation_reporter) return self as result, member function tab(self in ut_documentation_reporter) return varchar2, - member procedure print_output(a_executable ut_executable), overriding member procedure print_text(self in out nocopy ut_documentation_reporter, a_text varchar2), overriding member procedure before_calling_suite(self in out nocopy ut_documentation_reporter, a_suite ut_logical_suite), diff --git a/source/reporters/ut_teamcity_reporter.tpb b/source/reporters/ut_teamcity_reporter.tpb index e3f1530e5..d70f99f5d 100644 --- a/source/reporters/ut_teamcity_reporter.tpb +++ b/source/reporters/ut_teamcity_reporter.tpb @@ -24,60 +24,74 @@ create or replace type body ut_teamcity_reporter is overriding member procedure before_calling_suite(self in out nocopy ut_teamcity_reporter, a_suite in ut_logical_suite) is begin - self.print_text( - ut_teamcity_reporter_helper.test_suite_started( - a_suite_name => nvl(replace(trim(a_suite.description), '.'),a_suite.name)) - ); + self.print_text(ut_teamcity_reporter_helper.test_suite_started(a_suite_name => nvl(replace(trim(a_suite.description) + ,'.') + ,a_suite.name))); end; overriding member procedure after_calling_suite(self in out nocopy ut_teamcity_reporter, a_suite in ut_logical_suite) is begin - self.print_text( - ut_teamcity_reporter_helper.test_suite_finished( - a_suite_name => nvl(replace(trim(a_suite.description), '.'),a_suite.name)) - ); + self.print_text(ut_teamcity_reporter_helper.test_suite_finished(a_suite_name => nvl(replace(trim(a_suite.description) + ,'.') + ,a_suite.name))); end; overriding member procedure before_calling_test(self in out nocopy ut_teamcity_reporter, a_test in ut_test) is l_test_full_name varchar2(4000); begin - l_test_full_name := lower(a_test.item.owner_name)||'.'||lower(a_test.item.object_name)||'.'||lower(a_test.item.procedure_name); + l_test_full_name := lower(a_test.item.owner_name) || '.' || lower(a_test.item.object_name) || '.' || + lower(a_test.item.procedure_name); - self.print_text(ut_teamcity_reporter_helper.test_started(a_test_name => l_test_full_name,a_capture_standard_output => true)); + self.print_text(ut_teamcity_reporter_helper.test_started(a_test_name => l_test_full_name + ,a_capture_standard_output => true)); end; overriding member procedure after_calling_test(self in out nocopy ut_teamcity_reporter, a_test in ut_test) is - l_assert ut_assert_result; - l_test_full_name varchar2(4000); - procedure print_output(a_exectable ut_executable) is - l_lines ut_varchar2_list; - begin - if a_exectable is not null and a_exectable.is_defined and a_exectable.serveroutput is not null and dbms_lob.getlength(a_exectable.serveroutput) > 0 then - l_lines := ut_utils.clob_to_table(a_exectable.serveroutput); - for i in 1..l_lines.count loop - self.print_text(l_lines(i)); - end loop; - end if; - end; + l_assert ut_assert_result; + l_test_full_name varchar2(4000); + l_std_err_msg varchar2(32767); begin --- l_test_full_name := self.suite_names_stack(self.suite_names_stack.last) || ':' || --- nvl(replace(a_test.description, '.'), a_test.name); - l_test_full_name := lower(a_test.item.owner_name)||'.'||lower(a_test.item.object_name)||'.'||lower(a_test.item.procedure_name); + -- l_test_full_name := self.suite_names_stack(self.suite_names_stack.last) || ':' || + -- nvl(replace(a_test.description, '.'), a_test.name); + l_test_full_name := lower(a_test.item.owner_name) || '.' || lower(a_test.item.object_name) || '.' || + lower(a_test.item.procedure_name); - if a_test.result = ut_utils.tr_ignore then - self.print_text(ut_teamcity_reporter_helper.test_ignored(l_test_full_name)); + if a_test.result = ut_utils.tr_disabled then + self.print_text(ut_teamcity_reporter_helper.test_disabled(l_test_full_name)); else - - -- reproduce the output from before/after procedures and the test - print_output(a_test.before_each); - print_output(a_test.before_test); - print_output(a_test.item); - print_output(a_test.after_test); - print_output(a_test.after_each); - - if a_test.results is not null and a_test.results.count > 0 then + + self.print_clob(a_test.get_serveroutputs()); + + if a_test.result = ut_utils.tr_error then + if a_test.before_each.error_backtrace is not null then + l_std_err_msg := l_std_err_msg || 'Before each exception:' || chr(10) || a_test.before_each.error_backtrace || chr(10); + end if; + + if a_test.before_test.error_backtrace is not null then + l_std_err_msg := l_std_err_msg || 'Before test exception:' || chr(10) || a_test.before_test.error_backtrace || chr(10); + end if; + + if a_test.item.error_backtrace is not null then + l_std_err_msg := l_std_err_msg || 'Test exception:' || chr(10) || a_test.item.error_backtrace || chr(10); + end if; + + if a_test.after_test.error_backtrace is not null then + l_std_err_msg := l_std_err_msg || 'After test exception:' || chr(10) || a_test.after_test.error_backtrace || chr(10); + end if; + + if a_test.after_each.error_backtrace is not null then + l_std_err_msg := l_std_err_msg || 'After each exception:' || chr(10) || a_test.after_each.error_backtrace || chr(10); + end if; + + self.print_text(ut_teamcity_reporter_helper.test_std_err(a_test_name => l_test_full_name + ,a_out => trim(l_std_err_msg))); + self.print_text(ut_teamcity_reporter_helper.test_failed(a_test_name => l_test_full_name + ,a_msg => 'Error occured' + ,a_details => trim(l_std_err_msg) || a_test.results(1) + .message)); + elsif a_test.results is not null and a_test.results.count > 0 then for i in 1 .. a_test.results.count loop l_assert := a_test.results(i); @@ -85,17 +99,24 @@ create or replace type body ut_teamcity_reporter is if l_assert.result > ut_utils.tr_success then self.print_text(ut_teamcity_reporter_helper.test_failed(a_test_name => l_test_full_name ,a_msg => l_assert.message - ,a_expected => l_assert.expected_value_string - ,a_actual => l_assert.actual_value_string)); + ,a_expected => case + when l_assert.matcher_name in + ('equal', 'be false', 'be true') then + l_assert.expected_value_string + end + ,a_actual => case + when l_assert.matcher_name in + ('equal', 'be false', 'be true') then + l_assert.actual_value_string + end)); -- Teamcity supports only a single failure message exit; end if; end loop; elsif a_test.result = ut_utils.tr_failure then - self.print_text(ut_teamcity_reporter_helper.test_failed(a_test_name => l_test_full_name, a_msg => 'Test failed')); - elsif a_test.result = ut_utils.tr_error then - self.print_text(ut_teamcity_reporter_helper.test_failed(a_test_name => l_test_full_name, a_msg => 'Error occured')); + self.print_text(ut_teamcity_reporter_helper.test_failed(a_test_name => l_test_full_name + ,a_msg => 'Test failed')); end if; self.print_text(ut_teamcity_reporter_helper.test_finished(l_test_full_name, trunc(a_test.execution_time * 1e3))); diff --git a/source/reporters/ut_teamcity_reporter_helper.pkb b/source/reporters/ut_teamcity_reporter_helper.pkb index 26aafa08d..30919f42c 100644 --- a/source/reporters/ut_teamcity_reporter_helper.pkb +++ b/source/reporters/ut_teamcity_reporter_helper.pkb @@ -21,7 +21,7 @@ create or replace package body ut_teamcity_reporter_helper is function escape_value(a_value in varchar2) return varchar2 is begin - return regexp_replace(a_value, '(''|"|' || chr(13) || '|' || chr(10) || '|[|])', '|\1'); + return translate(regexp_replace(a_value, '(''|"|[|]|' || chr(13) || '|' || chr(10) || ')', '|\1'),chr(13)||chr(10),'nr'); end; function message(a_command in varchar2, a_props t_props default cast(null as t_props)) return varchar2 is @@ -30,7 +30,7 @@ create or replace package body ut_teamcity_reporter_helper is l_value varchar2(32767); begin l_message := '##teamcity[' || a_command || ' timestamp=''' || - regexp_replace(to_char(systimestamp, 'YYYY-MM-DD"T"HH24:MI:ss.FFTZHTZM'), '(\.\d{3})\d+(\+)', '\1\2') || ''''; + regexp_replace(to_char(systimestamp, 'YYYY-MM-DD"T"HH24:MI:ss.FF3TZHTZM'), '(\.\d{3})\d+(\+)', '\1\2') || ''''; l_index := a_props.first; while l_index is not null loop @@ -101,7 +101,7 @@ create or replace package body ut_teamcity_reporter_helper is return message('testFinished', l_props); end; - function test_ignored(a_test_name varchar2, a_flow_id varchar2 default null) return varchar2 is + function test_disabled(a_test_name varchar2, a_flow_id varchar2 default null) return varchar2 is l_props t_props; begin l_props('name') := a_test_name; diff --git a/source/reporters/ut_teamcity_reporter_helper.pks b/source/reporters/ut_teamcity_reporter_helper.pks index b9adb7120..e3a95e5bb 100644 --- a/source/reporters/ut_teamcity_reporter_helper.pks +++ b/source/reporters/ut_teamcity_reporter_helper.pks @@ -24,7 +24,7 @@ create or replace package ut_teamcity_reporter_helper is function test_started(a_test_name varchar2, a_capture_standard_output boolean default null, a_flow_id varchar2 default null) return varchar2; function test_finished(a_test_name varchar2, a_test_duration_milisec number default null, a_flow_id varchar2 default null) return varchar2; - function test_ignored(a_test_name varchar2, a_flow_id varchar2 default null) return varchar2; + function test_disabled(a_test_name varchar2, a_flow_id varchar2 default null) return varchar2; function test_failed(a_test_name varchar2, a_msg in varchar2 default null, a_details varchar2 default null, a_flow_id varchar2 default null, a_actual varchar2 default null, a_expected varchar2 default null) return varchar2; function test_std_out(a_test_name varchar2, a_out in varchar2, a_flow_id in varchar2 default null) return varchar2; function test_std_err(a_test_name varchar2, a_out in varchar2, a_flow_id in varchar2 default null) return varchar2; diff --git a/source/reporters/ut_xunit_reporter.tpb b/source/reporters/ut_xunit_reporter.tpb index c2e2bdfe2..de7094437 100644 --- a/source/reporters/ut_xunit_reporter.tpb +++ b/source/reporters/ut_xunit_reporter.tpb @@ -24,63 +24,88 @@ create or replace type body ut_xunit_reporter is overriding member procedure after_calling_run(self in out nocopy ut_xunit_reporter, a_run in ut_run) is l_suite_id integer := 0; - l_tests_count integer := a_run.results_count.ignored_count + a_run.results_count.success_count + a_run.results_count.failure_count + a_run.results_count.errored_count; + l_tests_count integer := a_run.results_count.disabled_count + a_run.results_count.success_count + + a_run.results_count.failure_count + a_run.results_count.errored_count; function get_path(a_path_with_name varchar2, a_name varchar2) return varchar2 is begin - return substr(a_path_with_name, 1, instr(a_path_with_name,'.'||a_name)-1); + return substr(a_path_with_name, 1, instr(a_path_with_name, '.' || a_name) - 1); end; procedure print_test_elements(a_test ut_test) is l_lines ut_varchar2_list; + l_output clob; begin - self.print_text( - '' - ); - if a_test.result = ut_utils.tr_ignore then + self.print_text(''); + if a_test.result = ut_utils.tr_disabled then self.print_text(''); end if; - - if a_test.result > ut_utils.tr_success then + if a_test.result = ut_utils.tr_error then + self.print_text(''); + self.print_text(''); + self.print_text(''); + elsif a_test.result > ut_utils.tr_success then self.print_text(''); - self.print_text( ''); self.print_text(''); end if; - -- TODO - separate failure messages, error messages, and dbms_output results from tests execution - -- TODO - decide if to use 'skipped' or 'disabled' - -- - -- - -- + -- TODO - decide if we need/want to use the tag too + l_output := a_test.get_serveroutputs(); + if l_output is not null then + self.print_text(''); + self.print_text(''); + self.print_text(''); + end if; self.print_text(''); end; procedure print_suite_elements(a_suite ut_logical_suite, a_suite_id in out nocopy integer) is - l_tests_count integer := a_suite.results_count.ignored_count + a_suite.results_count.success_count + a_suite.results_count.failure_count + a_suite.results_count.errored_count; + l_tests_count integer := a_suite.results_count.disabled_count + a_suite.results_count.success_count + + a_suite.results_count.failure_count + a_suite.results_count.errored_count; + l_suite ut_suite; begin a_suite_id := a_suite_id + 1; - self.print_text( - '' - ); - -- TODO - separate failure messages, error messages, and dbms_output results from tests execution - -- TODO - decide if to use 'skipped' or 'disabled' - -- - -- + self.print_text(''); + if a_suite is of(ut_suite) then + l_suite := treat(a_suite as ut_suite); + + if l_suite.before_all.serveroutput is not null or l_suite.after_all.serveroutput is not null then + self.print_text(''); + self.print_text(''); + self.print_text(''); + end if; + + if l_suite.before_all.error_stack is not null or l_suite.after_all.error_stack is not null then + self.print_text(''); + self.print_text(''); + self.print_text(''); + end if; + end if; + for i in 1 .. a_suite.items.count loop - if a_suite.items(i) is of (ut_test) then + if a_suite.items(i) is of(ut_test) then print_test_elements(treat(a_suite.items(i) as ut_test)); - elsif a_suite.items(i) is of (ut_logical_suite) then + elsif a_suite.items(i) is of(ut_logical_suite) then print_suite_elements(treat(a_suite.items(i) as ut_logical_suite), a_suite_id); end if; end loop; @@ -88,7 +113,7 @@ create or replace type body ut_xunit_reporter is end; begin l_suite_id := 0; - self.print_text(''); + self.print_text(''); for i in 1 .. a_run.items.count loop print_suite_elements(treat(a_run.items(i) as ut_logical_suite), l_suite_id); end loop; @@ -98,10 +123,7 @@ create or replace type body ut_xunit_reporter is member function get_common_item_attributes(a_item ut_suite_item) return varchar2 is begin - return - ' skipped="'||a_item.results_count.ignored_count||'" error="'||a_item.results_count.errored_count||'"'|| - ' failure="'||a_item.results_count.failure_count||'" name="'||a_item.description||'"'|| - ' time="'||a_item.execution_time()||'" '; + return ' skipped="' || a_item.results_count.disabled_count || '" error="' || a_item.results_count.errored_count || '"' || ' failure="' || a_item.results_count.failure_count || '" name="' || a_item.description || '"' || ' time="' || a_item.execution_time() || '" '; end; end; diff --git a/tests/RunAll.sql b/tests/RunAll.sql index 28d86d21d..8f5f98f12 100644 --- a/tests/RunAll.sql +++ b/tests/RunAll.sql @@ -137,7 +137,7 @@ exec ut_coverage.coverage_start_develop(); @@lib/RunTest.sql ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTop2PackageProcedureByPathCurUser.sql @@lib/RunTest.sql ut_suite_manager/ut_suite_manager.DoesntFindTheSuiteWhenPackageSpecIsInvalid.sql -@@lib/RunTest.sql ut_test/ut_test.IgnoreFlagSkipTest.sql +@@lib/RunTest.sql ut_test/ut_test.DisabledFlagSkipTest.sql @@lib/RunTest.sql ut_test/ut_test.OwnerNameInvalid.sql @@lib/RunTest.sql ut_test/ut_test.OwnerNameNull.sql @@lib/RunTest.sql ut_test/ut_test.PackageInInvalidState.sql @@ -171,7 +171,7 @@ exec ut_coverage.coverage_start_develop(); @@lib/RunTest.sql ut_test_suite/ut_test_suite.ErrorsEachTestWhenBeforeEachFails.sql @@lib/RunTest.sql ut_test_suite/ut_test_suite.ErrorsEachTestWhenPackageHasInvalidBody.sql @@lib/RunTest.sql ut_test_suite/ut_test_suite.ErrorsEachTestWhenPackageHasNoBody.sql -@@lib/RunTest.sql ut_test_suite/ut_test_suite.IgnoreFlagSkipSuite.sql +@@lib/RunTest.sql ut_test_suite/ut_test_suite.DisabledFlagSkipSuite.sql @@lib/RunTest.sql ut_test_suite/ut_test_suite.ReportsWarningsATestWhenAfterAllFails.sql @@lib/RunTest.sql ut_test_suite/ut_test_suite.ReportsWarningsATestWhenAfterEachFails.sql @@lib/RunTest.sql ut_test_suite/ut_test_suite.Rollback_type.Auto.sql diff --git a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByName.sql b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByName.sql index ccb0d965d..3852701b9 100644 --- a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByName.sql +++ b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByName.sql @@ -4,47 +4,47 @@ PROMPT Prepare runner for the top package by package name declare c_path varchar2(100) := USER||'.test_package_1'; l_objects_to_run ut_suite_items; - + l_test0_suite ut_logical_suite; l_test1_suite ut_suite; l_test2_suite ut_suite; -begin +begin --Act l_objects_to_run := ut_suite_manager.configure_execution_by_path(ut_varchar2_list(c_path)); - + --Assert ut.expect(l_objects_to_run.count).to_equal(1); l_test0_suite := treat(l_objects_to_run(1) as ut_logical_suite); - + ut.expect(l_test0_suite.name).to_equal('tests'); ut.expect(l_test0_suite.items.count).to_equal(1); l_test1_suite := treat(l_test0_suite.items(1) as ut_suite); - + ut.expect(l_test1_suite.name).to_equal('test_package_1'); ut.expect(l_test1_suite.items.count).to_equal(3); - + ut.expect(l_test1_suite.items(1).name).to_equal('test1'); ut.expect(l_test1_suite.items(1).description).to_equal('Test1 from test package 1'); ut.expect(treat(l_test1_suite.items(1) as ut_test).before_test.is_defined).to_be_false; ut.expect(treat(l_test1_suite.items(1) as ut_test).after_test.is_defined).to_be_false; ut.expect(treat(l_test1_suite.items(1) as ut_test).before_each.is_defined).to_be_true; - ut.expect(treat(l_test1_suite.items(1) as ut_test).ignore_flag).to_equal(0); - + ut.expect(treat(l_test1_suite.items(1) as ut_test).disabled_flag).to_equal(0); + ut.expect(l_test1_suite.items(2).name).to_equal('test2'); ut.expect(l_test1_suite.items(2).description).to_equal('Test2 from test package 1'); ut.expect(treat(l_test1_suite.items(2) as ut_test).before_test.is_defined).to_be_true; ut.expect(treat(l_test1_suite.items(2) as ut_test).after_test.is_defined).to_be_true; ut.expect(treat(l_test1_suite.items(2) as ut_test).before_each.is_defined).to_be_true; - ut.expect(treat(l_test1_suite.items(2) as ut_test).ignore_flag).to_equal(0); - + ut.expect(treat(l_test1_suite.items(2) as ut_test).disabled_flag).to_equal(0); + -- temporary behavior. -- decided that when executed by package, not path, only that package has to execute l_test2_suite := treat(l_test1_suite.items(3) as ut_suite); - + ut.expect(l_test2_suite.name).to_equal('test_package_2'); ut.expect(l_test2_suite.items.count).to_equal(2); - + if ut_assert_processor.get_aggregate_asserts_result = ut_utils.tr_success then :test_result := ut_utils.tr_success; else diff --git a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByNameCurUser.sql b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByNameCurUser.sql index 71924cdf2..513281577 100644 --- a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByNameCurUser.sql +++ b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageByNameCurUser.sql @@ -4,47 +4,47 @@ PROMPT Prepare runner for the top package by package name for current user declare c_path varchar2(100) := 'test_package_1'; l_objects_to_run ut_suite_items; - + l_test0_suite ut_logical_suite; l_test1_suite ut_suite; l_test2_suite ut_suite; -begin +begin --Act l_objects_to_run := ut_suite_manager.configure_execution_by_path(ut_varchar2_list(c_path)); - + --Assert ut.expect(l_objects_to_run.count).to_equal(1); l_test0_suite := treat(l_objects_to_run(1) as ut_logical_suite); - + ut.expect(l_test0_suite.name).to_equal('tests'); ut.expect(l_test0_suite.items.count).to_equal(1); l_test1_suite := treat(l_test0_suite.items(1) as ut_suite); - + ut.expect(l_test1_suite.name).to_equal('test_package_1'); ut.expect(l_test1_suite.items.count).to_equal(3); - + ut.expect(l_test1_suite.items(1).name).to_equal('test1'); ut.expect(l_test1_suite.items(1).description).to_equal('Test1 from test package 1'); ut.expect(treat(l_test1_suite.items(1) as ut_test).before_test.is_defined).to_be_false; ut.expect(treat(l_test1_suite.items(1) as ut_test).after_test.is_defined).to_be_false; ut.expect(treat(l_test1_suite.items(1) as ut_test).before_each.is_defined).to_be_true; - ut.expect(treat(l_test1_suite.items(1) as ut_test).ignore_flag).to_equal(0); - + ut.expect(treat(l_test1_suite.items(1) as ut_test).disabled_flag).to_equal(0); + ut.expect(l_test1_suite.items(2).name).to_equal('test2'); ut.expect(l_test1_suite.items(2).description).to_equal('Test2 from test package 1'); ut.expect(treat(l_test1_suite.items(2) as ut_test).before_test.is_defined).to_be_true; ut.expect(treat(l_test1_suite.items(2) as ut_test).after_test.is_defined).to_be_true; ut.expect(treat(l_test1_suite.items(2) as ut_test).before_each.is_defined).to_be_true; - ut.expect(treat(l_test1_suite.items(2) as ut_test).ignore_flag).to_equal(0); - + ut.expect(treat(l_test1_suite.items(2) as ut_test).disabled_flag).to_equal(0); + -- temporary behavior. -- decided that when executed by package, not path, only that package has to execute l_test2_suite := treat(l_test1_suite.items(3) as ut_suite); - + ut.expect(l_test2_suite.name).to_equal('test_package_2'); ut.expect(l_test2_suite.items.count).to_equal(2); - + if ut_assert_processor.get_aggregate_asserts_result = ut_utils.tr_success then :test_result := ut_utils.tr_success; else diff --git a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByName.sql b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByName.sql index 4b2762234..bf9ac5638 100644 --- a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByName.sql +++ b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByName.sql @@ -4,34 +4,34 @@ PROMPT Prepare runner for the top package without sub-suites by package name declare c_path varchar2(100) := USER||'.test_package_3'; l_objects_to_run ut_suite_items; - + l_test0_suite ut_logical_suite; l_test1_suite ut_logical_suite; l_test1 ut_test; l_test3 ut_test; -begin +begin --Act l_objects_to_run := ut_suite_manager.configure_execution_by_path(ut_varchar2_list(c_path)); - + --Assert ut.expect(l_objects_to_run.count).to_equal(1); l_test0_suite := treat(l_objects_to_run(1) as ut_logical_suite); - + ut.expect(l_test0_suite.name).to_equal('tests2'); ut.expect(l_test0_suite.items.count).to_equal(1); l_test1_suite := treat(l_test0_suite.items(1) as ut_logical_suite); - + ut.expect(l_test1_suite.name).to_equal('test_package_3'); ut.expect(l_test1_suite.items.count).to_equal(3); - + l_test1 := treat(l_test1_suite.items(1) as ut_test); ut.expect(l_test1.name).to_equal('test1'); - ut.expect(l_test1.ignore_flag).to_equal(0); - + ut.expect(l_test1.disabled_flag).to_equal(0); + l_test3 := treat(l_test1_suite.items(3) as ut_test); ut.expect(l_test3.name).to_equal('disabled_test'); - ut.expect(l_test3.ignore_flag).to_equal(1); - + ut.expect(l_test3.disabled_flag).to_equal(1); + if ut_assert_processor.get_aggregate_asserts_result = ut_utils.tr_success then :test_result := ut_utils.tr_success; end if; diff --git a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByNameCurUser.sql b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByNameCurUser.sql index a44738096..6c3c269b8 100644 --- a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByNameCurUser.sql +++ b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByNameCurUser.sql @@ -4,34 +4,34 @@ PROMPT Prepare runner for the top package without sub-suites by package name for declare c_path varchar2(100) := 'test_package_3'; l_objects_to_run ut_suite_items; - + l_test0_suite ut_logical_suite; l_test1_suite ut_logical_suite; l_test1 ut_test; l_test3 ut_test; -begin +begin --Act l_objects_to_run := ut_suite_manager.configure_execution_by_path(ut_varchar2_list(c_path)); - + --Assert ut.expect(l_objects_to_run.count).to_equal(1); l_test0_suite := treat(l_objects_to_run(1) as ut_logical_suite); - + ut.expect(l_test0_suite.name).to_equal('tests2'); ut.expect(l_test0_suite.items.count).to_equal(1); l_test1_suite := treat(l_test0_suite.items(1) as ut_logical_suite); - + ut.expect(l_test1_suite.name).to_equal('test_package_3'); ut.expect(l_test1_suite.items.count).to_equal(3); - + l_test1 := treat(l_test1_suite.items(1) as ut_test); ut.expect(l_test1.name).to_equal('test1'); - ut.expect(l_test1.ignore_flag).to_equal(0); - + ut.expect(l_test1.disabled_flag).to_equal(0); + l_test3 := treat(l_test1_suite.items(3) as ut_test); ut.expect(l_test3.name).to_equal('disabled_test'); - ut.expect(l_test3.ignore_flag).to_equal(1); - + ut.expect(l_test3.disabled_flag).to_equal(1); + if ut_assert_processor.get_aggregate_asserts_result = ut_utils.tr_success then :test_result := ut_utils.tr_success; end if; diff --git a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPath.sql b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPath.sql index 37cca3d3e..5d2dddcc7 100644 --- a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPath.sql +++ b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPath.sql @@ -4,34 +4,34 @@ PROMPT Prepare runner for the top package without subsuites by path declare c_path varchar2(100) := USER||':tests2.test_package_3'; l_objects_to_run ut_suite_items; - + l_test0_suite ut_logical_suite; l_test1_suite ut_logical_suite; l_test1 ut_test; l_test3 ut_test; -begin +begin --Act l_objects_to_run := ut_suite_manager.configure_execution_by_path(ut_varchar2_list(c_path)); - + --Assert ut.expect(l_objects_to_run.count).to_equal(1); l_test0_suite := treat(l_objects_to_run(1) as ut_logical_suite); - + ut.expect(l_test0_suite.name).to_equal('tests2'); ut.expect(l_test0_suite.items.count).to_equal(1); l_test1_suite := treat(l_test0_suite.items(1) as ut_logical_suite); - + ut.expect(l_test1_suite.name).to_equal('test_package_3'); ut.expect(l_test1_suite.items.count).to_equal(3); - + l_test1 := treat(l_test1_suite.items(1) as ut_test); ut.expect(l_test1.name).to_equal('test1'); - ut.expect(l_test1.ignore_flag).to_equal(0); - + ut.expect(l_test1.disabled_flag).to_equal(0); + l_test3 := treat(l_test1_suite.items(3) as ut_test); ut.expect(l_test3.name).to_equal('disabled_test'); - ut.expect(l_test3.ignore_flag).to_equal(1); - + ut.expect(l_test3.disabled_flag).to_equal(1); + if ut_assert_processor.get_aggregate_asserts_result = ut_utils.tr_success then :test_result := ut_utils.tr_success; end if; diff --git a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPathCurUser.sql b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPathCurUser.sql index 3443f5dee..b20401adf 100644 --- a/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPathCurUser.sql +++ b/tests/ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageWithoutSubsuitesByPathCurUser.sql @@ -4,34 +4,34 @@ PROMPT Prepare runner for the top package without subsuites by path for current declare c_path varchar2(100) := ':tests2.test_package_3'; l_objects_to_run ut_suite_items; - + l_test0_suite ut_logical_suite; l_test1_suite ut_logical_suite; l_test1 ut_test; l_test3 ut_test; -begin +begin --Act l_objects_to_run := ut_suite_manager.configure_execution_by_path(ut_varchar2_list(c_path)); - + --Assert ut.expect(l_objects_to_run.count).to_equal(1); l_test0_suite := treat(l_objects_to_run(1) as ut_logical_suite); - + ut.expect(l_test0_suite.name).to_equal('tests2'); ut.expect(l_test0_suite.items.count).to_equal(1); l_test1_suite := treat(l_test0_suite.items(1) as ut_logical_suite); - + ut.expect(l_test1_suite.name).to_equal('test_package_3'); ut.expect(l_test1_suite.items.count).to_equal(3); - + l_test1 := treat(l_test1_suite.items(1) as ut_test); ut.expect(l_test1.name).to_equal('test1'); - ut.expect(l_test1.ignore_flag).to_equal(0); - + ut.expect(l_test1.disabled_flag).to_equal(0); + l_test3 := treat(l_test1_suite.items(3) as ut_test); ut.expect(l_test3.name).to_equal('disabled_test'); - ut.expect(l_test3.ignore_flag).to_equal(1); - + ut.expect(l_test3.disabled_flag).to_equal(1); + if ut_assert_processor.get_aggregate_asserts_result = ut_utils.tr_success then :test_result := ut_utils.tr_success; end if; diff --git a/tests/ut_test/ut_test.IgnoreFlagSkipTest.sql b/tests/ut_test/ut_test.DisabledFlagSkipTest.sql similarity index 94% rename from tests/ut_test/ut_test.IgnoreFlagSkipTest.sql rename to tests/ut_test/ut_test.DisabledFlagSkipTest.sql index d88f03aa1..f91d9f217 100644 --- a/tests/ut_test/ut_test.IgnoreFlagSkipTest.sql +++ b/tests/ut_test/ut_test.DisabledFlagSkipTest.sql @@ -1,4 +1,4 @@ -PROMPT Ignore test by ignore flag +PROMPT Disable test by disabled flag --Arrange declare @@ -13,7 +13,7 @@ begin delete from ut$test_table; - l_test := ut_test(a_object_name => 'ut_transaction_control', a_name => 'test', a_rollback_type => ut_utils.gc_rollback_auto, a_ignore_flag => true); + l_test := ut_test(a_object_name => 'ut_transaction_control', a_name => 'test', a_rollback_type => ut_utils.gc_rollback_auto, a_disabled_flag => true); l_suite := ut_suite (a_description => 'Suite name', a_name => 'UT_TRANSACTION_CONTROL', a_object_name => 'UT_TRANSACTION_CONTROL', a_rollback_type => ut_utils.gc_rollback_auto,a_path => 'ut_transaction_control'); l_suite.add_item(l_test); diff --git a/tests/ut_test_suite/ut_test_suite.IgnoreFlagSkipSuite.sql b/tests/ut_test_suite/ut_test_suite.DisabledFlagSkipSuite.sql similarity index 92% rename from tests/ut_test_suite/ut_test_suite.IgnoreFlagSkipSuite.sql rename to tests/ut_test_suite/ut_test_suite.DisabledFlagSkipSuite.sql index ca88b8062..19706e535 100644 --- a/tests/ut_test_suite/ut_test_suite.IgnoreFlagSkipSuite.sql +++ b/tests/ut_test_suite/ut_test_suite.DisabledFlagSkipSuite.sql @@ -1,4 +1,4 @@ -PROMPT Ignore whole suite by ignore flag +PROMPT Disable whole suite by disabled flag --Arrange declare @@ -16,7 +16,7 @@ begin l_test := ut_test(a_object_name => 'ut_transaction_control',a_name => 'test', a_rollback_type => ut_utils.gc_rollback_auto); l_suite := ut_suite (a_description => 'Suite name', a_name => 'UT_TRANSACTION_CONTROL', a_object_name => 'UT_TRANSACTION_CONTROL', a_rollback_type => ut_utils.gc_rollback_auto,a_path => 'ut_transaction_control'); l_suite.add_item(l_test); - l_suite.set_ignore_flag(true); + l_suite.set_disabled_flag(true); --Act l_suite.do_execute(l_listener);