From 4f8caa4917239cefb3964f155f32d55168a801bd Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 7 Jun 2018 01:47:40 +0100 Subject: [PATCH 1/3] Fixed running single test procedure in context by path Changed context naming (context name can be now explicit) Context description is now only set from `--%displayname` annotation Resolves #679 Resolves #674 Fixed most of compiler-warnings --- docs/userguide/annotations.md | 6 +- source/core/events/ut_event_manager.pkb | 3 +- source/core/types/ut_suite.tpb | 4 +- source/core/types/ut_suite.tps | 4 +- source/core/types/ut_suite_context.tpb | 32 +++++++ source/core/types/ut_suite_context.tps | 22 +++++ source/core/types/ut_suite_item.tpb | 2 +- source/core/types/ut_suite_item.tps | 2 +- source/core/ut_suite_builder.pkb | 26 +++--- source/core/ut_suite_manager.pkb | 83 ++++++++++++++----- source/core/ut_suite_manager.pks | 2 +- source/core/ut_utils.pkb | 4 - .../data_values/ut_compound_data_value.tpb | 14 ++-- .../ut_curr_usr_compound_helper.pkb | 31 ++++--- .../ut_curr_usr_compound_helper.pks | 10 ++- source/install.sql | 6 +- source/install_component.sql | 1 + source/uninstall_objects.sql | 2 + test/core/test_suite_builder.pkb | 26 +++--- test/core/test_suite_manager.pkb | 81 ++++++++++++++++++ test/core/test_suite_manager.pks | 6 ++ 21 files changed, 286 insertions(+), 81 deletions(-) create mode 100644 source/core/types/ut_suite_context.tpb create mode 100644 source/core/types/ut_suite_context.tps diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 636c09264..011626b80 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -30,7 +30,7 @@ We strongly recommend putting package level annotations at the very top of packa | `--%aftertest()` | Procedure | Denotes that mentioned procedure should be executed after the annotated `%test` procedure. | | `--%rollback()` | Package/procedure | Defines transaction control. Supported values: `auto`(default) - a savepoint is created before invocation of each "before block" is and a rollback to specific savepoint is issued after each "after" block; `manual` - rollback is never issued automatically. Property can be overridden for child element (test in suite) | | `--%disabled` | Package/procedure | Used to disable a suite or a test. Disabled suites/tests do not get executed, they are however marked and reported as disabled in a test run. | -| `--%context()` | Package | Denotes start of a nested context (sub-suite) in a suite package | +| `--%context()` | Package | Denotes start of a named context (sub-suite) in a suite package | | `--%endcontext` | Package | Denotes end of a nested context (sub-suite) in a suite package | ### Suite @@ -863,7 +863,7 @@ In essence, context behaves like a suite within a suite. Context have following characteristics: - start with the `--%context` annotation and ends with `--%endcontext` -- can have a name provided a parameter for example `--%context(Remove rooms by name)` +- can have a name provided as parameter for example `--%context(remove_rooms_by_name)` - when no name is provided for context, the context is names `context_N` where `N` is the number of the context in suite - can have their own `--%beforeall`, `--%beforeeach`, `--%afterall` and `--%aftereach` procedures - `--%beforeall`, `--%beforeeach`, `--%afterall` and `--%aftereach` procedures defined at suite level, propagate to context @@ -945,6 +945,7 @@ create or replace package test_rooms_management is --%context(remove_rooms_by_name) + --%description(Remove rooms by name) --%test(Removes a room without content in it) procedure remove_empty_room; @@ -957,6 +958,7 @@ create or replace package test_rooms_management is --%context(add_rooms_content) + --%description(Add content to a room) --%test(Fails when room name is not valid) --%throws(-1403) diff --git a/source/core/events/ut_event_manager.pkb b/source/core/events/ut_event_manager.pkb index 312ddc9c3..cb556050a 100644 --- a/source/core/events/ut_event_manager.pkb +++ b/source/core/events/ut_event_manager.pkb @@ -33,7 +33,8 @@ create or replace package body ut_event_manager as procedure trigger_event( a_event_name t_event_name, a_event_object ut_event_item ) is begin if a_event_name is not null and g_event_listeners_index.exists(a_event_name) - and g_event_listeners_index(a_event_name) is not null + -- disabled due to compiler warning: PLW-06023: invocation of IS NOT NULL computes trivial value +-- and g_event_listeners_index(a_event_name) is not null then for listener_number in 1 .. g_event_listeners_index(a_event_name).count loop g_listeners(listener_number).on_event(a_event_name, a_event_object); diff --git a/source/core/types/ut_suite.tpb b/source/core/types/ut_suite.tpb index 7b5525664..1c5663dd9 100644 --- a/source/core/types/ut_suite.tpb +++ b/source/core/types/ut_suite.tpb @@ -17,11 +17,11 @@ create or replace type body ut_suite as */ constructor function ut_suite ( - self in out nocopy ut_suite, a_object_owner varchar2, a_object_name varchar2, a_suite_name varchar2 := null + self in out nocopy ut_suite, a_object_owner varchar2, a_object_name varchar2 ) return self as result is begin self.self_type := $$plsql_unit; - self.init(a_object_owner, a_object_name, nvl(a_suite_name, a_object_name)); + self.init(a_object_owner, a_object_name, a_object_name); self.items := ut_suite_items(); before_all_list := ut_executables(); after_all_list := ut_executables(); diff --git a/source/core/types/ut_suite.tps b/source/core/types/ut_suite.tps index c80316172..866eefc80 100644 --- a/source/core/types/ut_suite.tps +++ b/source/core/types/ut_suite.tps @@ -27,10 +27,10 @@ create or replace type ut_suite under ut_logical_suite ( */ after_all_list ut_executables, constructor function ut_suite ( - self in out nocopy ut_suite, a_object_owner varchar2, a_object_name varchar2, a_suite_name varchar2 := null + self in out nocopy ut_suite, a_object_owner varchar2, a_object_name varchar2 ) return self as result, overriding member function do_execute(self in out nocopy ut_suite) return boolean, overriding member function get_error_stack_traces(self ut_suite) return ut_varchar2_list, overriding member function get_serveroutputs return clob -) +) not final / diff --git a/source/core/types/ut_suite_context.tpb b/source/core/types/ut_suite_context.tpb new file mode 100644 index 000000000..d09fb824f --- /dev/null +++ b/source/core/types/ut_suite_context.tpb @@ -0,0 +1,32 @@ +create or replace type body ut_suite_context as + /* + utPLSQL - Version 3 + 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. + See the License for the specific language governing permissions and + limitations under the License. + */ + + constructor function ut_suite_context ( + self in out nocopy ut_suite_context, a_object_owner varchar2, a_object_name varchar2, a_context_name varchar2 := null + ) return self as result is + begin + self.self_type := $$plsql_unit; + self.init(a_object_owner, a_object_name, a_context_name); + self.items := ut_suite_items(); + before_all_list := ut_executables(); + after_all_list := ut_executables(); + return; + end; + +end; +/ diff --git a/source/core/types/ut_suite_context.tps b/source/core/types/ut_suite_context.tps new file mode 100644 index 000000000..ea7d6d31c --- /dev/null +++ b/source/core/types/ut_suite_context.tps @@ -0,0 +1,22 @@ +create or replace type ut_suite_context under ut_suite ( + /* + utPLSQL - Version 3 + 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. + See the License for the specific language governing permissions and + limitations under the License. + */ + constructor function ut_suite_context ( + self in out nocopy ut_suite_context, a_object_owner varchar2, a_object_name varchar2, a_context_name varchar2 := null + ) return self as result +) +/ diff --git a/source/core/types/ut_suite_item.tpb b/source/core/types/ut_suite_item.tpb index 5325be9de..b63ed9931 100644 --- a/source/core/types/ut_suite_item.tpb +++ b/source/core/types/ut_suite_item.tpb @@ -98,7 +98,7 @@ final member procedure do_execute(self in out nocopy ut_suite_item) is return transaction_invalidators; end; - member procedure add_transaction_invalidator(a_object_name varchar2) is + member procedure add_transaction_invalidator(self in out nocopy ut_suite_item, a_object_name varchar2) is begin if a_object_name not member of transaction_invalidators then transaction_invalidators.extend(); diff --git a/source/core/types/ut_suite_item.tps b/source/core/types/ut_suite_item.tps index 6a36d88ee..5973f9bd9 100644 --- a/source/core/types/ut_suite_item.tps +++ b/source/core/types/ut_suite_item.tps @@ -61,7 +61,7 @@ create or replace type ut_suite_item force under ut_event_item ( member function create_savepoint_if_needed return varchar2, member procedure rollback_to_savepoint(self in out nocopy ut_suite_item, a_savepoint varchar2), member function get_transaction_invalidators return ut_varchar2_list, - member procedure add_transaction_invalidator(a_object_name varchar2), + member procedure add_transaction_invalidator(self in out nocopy ut_suite_item, a_object_name varchar2), /* Returns execution time in seconds (with miliseconds) */ diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index 1f55d4291..71ed7ed2c 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -552,8 +552,8 @@ create or replace package body ut_suite_builder is procedure add_annotated_procedures( a_annotations tt_package_annotations, a_suite in out nocopy ut_suite, - a_before_each_list out ut_executables, - a_after_each_list out ut_executables + a_before_each_list out nocopy ut_executables, + a_after_each_list out nocopy ut_executables ) is l_position t_annotation_position; begin @@ -653,9 +653,10 @@ create or replace package body ut_suite_builder is ) is l_context_pos t_annotation_position; l_end_context_pos t_annotation_position; - l_package_ann_index tt_annotations_index; + l_context_ann_index tt_annotations_index; + l_context_name t_object_name; l_annotations tt_package_annotations; - l_suite ut_suite; + l_context ut_suite_context; l_context_no binary_integer := 1; function get_endcontext_position( @@ -705,17 +706,20 @@ create or replace package body ut_suite_builder is --create a sub-set of annotations to process as sub-suite (context) l_annotations := get_annotations_in_context(a_annotations, l_context_pos, l_end_context_pos); - l_package_ann_index := build_annotation_index(l_annotations); + l_context_ann_index := build_annotation_index(l_annotations); - l_suite := ut_suite(a_suite.object_owner, a_suite.object_name, gc_context||'_'||l_context_no); + l_context_name := coalesce( + l_annotations( l_context_pos ).text + , gc_context||'_'||l_context_no + ); + l_context := ut_suite_context(a_suite.object_owner, a_suite.object_name, l_context_name ); - l_suite.description := l_annotations(l_package_ann_index(gc_context).first).text; - l_suite.description := l_annotations(l_context_pos).text; - warning_on_duplicate_annot( l_suite, l_package_ann_index, gc_suite ); + l_context.description := l_annotations(l_context_pos).text; + warning_on_duplicate_annot( l_context, l_context_ann_index, gc_suite ); - populate_suite_contents( l_suite, l_annotations, l_package_ann_index, gc_context||'_'||l_context_no ); + populate_suite_contents( l_context, l_annotations, l_context_ann_index, l_context_name ); - a_suite.add_item(l_suite); + a_suite.add_item(l_context); -- remove annotations within context after processing them a_annotations.delete(l_context_pos, l_end_context_pos); diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 4a8927496..dccd745d2 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -213,26 +213,64 @@ create or replace package body ut_suite_manager is end; procedure filter_suite_by_path(a_suite in out nocopy ut_suite_item, a_path varchar2) is - c_root constant varchar2(32767) := lower(regexp_substr(a_path, '[A-Za-z0-9$#_]+')); - c_rest_path constant varchar2(32767) := regexp_substr(a_path, '\.(.+)', subexpression => 1); - l_suite ut_logical_suite; - l_item ut_suite_item; - l_items ut_suite_items := ut_suite_items(); - begin - 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); + c_item_name constant varchar2(32767) := lower(regexp_substr(a_path, '[A-Za-z0-9$#_]+')); + c_child_filter_path constant varchar2(32767) := regexp_substr(a_path, '\.(.+)', subexpression => 1); + l_suite ut_logical_suite; + l_item ut_suite_item; + l_items ut_suite_items := ut_suite_items(); - for i in 1 .. l_suite.items.count loop - l_item := l_suite.items(i); - if lower(l_item.name) = c_root then - filter_suite_by_path(l_item, c_rest_path); - l_items.extend; - l_items(l_items.count) := l_item; + function find_item_in_suite(a_suite ut_logical_suite, a_item_name varchar2) return ut_suite_item is + l_item_index binary_integer; + begin + l_item_index := a_suite.items.first; + while l_item_index is not null loop + if lower(a_suite.items(l_item_index).name) = a_item_name then + return a_suite.items(l_item_index); end if; + l_item_index := a_suite.items.next(l_item_index); end loop; + return null; + end; - if l_items.count = 0 then - raise_application_error(-20203, 'Suite not found'); + function find_item_in_suite_contexts(a_suite ut_logical_suite, a_item_name varchar2) return ut_suite_item is + l_item_index binary_integer; + l_context ut_suite_context; + l_item ut_suite_item; + begin + l_item_index := a_suite.items.first; + while l_item_index is not null loop + if a_suite.items(l_item_index) is of (ut_suite_context) then + l_item := find_item_in_suite( + treat(a_suite.items(l_item_index) as ut_suite_context) + , a_item_name + ); + end if; + + if l_item is not null then + l_context := treat(a_suite.items(l_item_index) as ut_suite_context); + l_context.items := ut_suite_items(l_item); + exit; + end if; + l_item_index := a_suite.items.next(l_item_index); + end loop; + return l_context; + end; + begin + if a_suite is of (ut_logical_suite) then + l_suite := treat(a_suite as ut_logical_suite); + + l_item := coalesce( + find_item_in_suite(l_suite, c_item_name) + , find_item_in_suite_contexts(l_suite, c_item_name) + ); + if l_item is not null then + if c_child_filter_path is not null then + filter_suite_by_path(l_item, c_child_filter_path); + end if; + l_items.extend; + l_items(l_items.count) := l_item; + else + raise_application_error(-20203, 'Suite item '||c_item_name||' not found'); end if; l_suite.items := l_items; @@ -241,12 +279,15 @@ create or replace package body ut_suite_manager is end filter_suite_by_path; function get_suite_filtered_by_path(a_path varchar2, a_schema_suites tt_schema_suites) return ut_logical_suite is - l_suite ut_logical_suite; - c_suite_path constant varchar2(4000) := regexp_substr(a_path, ':(.+)', subexpression => 1); - c_root_suite_name constant varchar2(4000) := regexp_substr(c_suite_path, '^[A-Za-z0-9$#_]+'); + l_suite ut_logical_suite; + c_suite_path constant varchar2(32767) := regexp_substr(a_path, ':(.+)', subexpression => 1); + c_root_suite_name constant varchar2(32767) := regexp_substr(c_suite_path, '^[A-Za-z0-9$#_]+'); + c_child_filter_path constant varchar2(32767) := regexp_substr(c_suite_path, '\.(.+)', subexpression => 1); begin l_suite := a_schema_suites(c_root_suite_name); - filter_suite_by_path(l_suite, regexp_substr(c_suite_path, '\.(.+)', subexpression => 1)); + if c_child_filter_path is not null then + filter_suite_by_path(l_suite, c_child_filter_path); + end if; return l_suite; exception when no_data_found then @@ -293,7 +334,7 @@ create or replace package body ut_suite_manager is l_index varchar2(4000 char); l_suite ut_logical_suite; l_objects_to_run ut_suite_items; - l_schema_paths t_schema_paths; + l_schema_paths t_schema_paths; begin --resolve schema names from paths and group paths by schema name resolve_schema_names(l_paths); diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index 8b1b34335..f35ddb4b3 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -17,7 +17,7 @@ create or replace package ut_suite_manager authid current_user is */ /** - * Reads database source code, parses it and returns annotations + * Resposible for building hierarhy of sutes from individual suites created by suite_builder */ /** diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 4654f9b34..c6ffe2060 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -571,10 +571,6 @@ procedure append_to_clob(a_src_clob in out nocopy clob, a_clob_table t_clob_tab, l_newlines_count binary_integer; l_offset binary_integer := 1; l_length binary_integer := coalesce(dbms_lob.getlength(a_source), 0); - function is_before(a_x binary_integer, a_y binary_integer) return boolean is - begin - return a_x < a_y or a_y = 0; - end; begin l_ml_comment_start := instr(a_source,'/*'); l_comment_start := instr(a_source,'--'); diff --git a/source/expectations/data_values/ut_compound_data_value.tpb b/source/expectations/data_values/ut_compound_data_value.tpb index 45841e5a9..0222c4fd0 100644 --- a/source/expectations/data_values/ut_compound_data_value.tpb +++ b/source/expectations/data_values/ut_compound_data_value.tpb @@ -96,13 +96,13 @@ create or replace type body ut_compound_data_value as function get_diff_message (a_row_diff ut_compound_data_helper.t_row_diffs,a_compare_type varchar2) return varchar2 is begin - if a_compare_type = ut_compound_data_helper.gc_compare_join_by and a_row_diff.pk_value is not null then - return ' PK '||a_row_diff.pk_value||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row; - elsif a_compare_type = ut_compound_data_helper.gc_compare_join_by or a_compare_type = ut_compound_data_helper.gc_compare_normal then - return ' Row No. '||a_row_diff.rn||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row; - elsif a_compare_type = ut_compound_data_helper.gc_compare_unordered then - return rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row; - end if; + if a_compare_type = ut_compound_data_helper.gc_compare_join_by and a_row_diff.pk_value is not null then + return ' PK '||a_row_diff.pk_value||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row; + elsif a_compare_type = ut_compound_data_helper.gc_compare_join_by or a_compare_type = ut_compound_data_helper.gc_compare_normal then + return ' Row No. '||a_row_diff.rn||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row; + elsif a_compare_type = ut_compound_data_helper.gc_compare_unordered then + return rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row; + end if; end; begin diff --git a/source/expectations/data_values/ut_curr_usr_compound_helper.pkb b/source/expectations/data_values/ut_curr_usr_compound_helper.pkb index c07b2801b..c910aca65 100644 --- a/source/expectations/data_values/ut_curr_usr_compound_helper.pkb +++ b/source/expectations/data_values/ut_curr_usr_compound_helper.pkb @@ -15,7 +15,7 @@ create or replace package body ut_curr_usr_compound_helper is end if; end; - function get_column_type(a_desc_rec dbms_sql.desc_rec3,a_desc_user_types boolean := false) return ut_key_anyval_pair is + function get_column_type(a_desc_rec dbms_sql.desc_rec3, a_desc_user_types boolean := false) return ut_key_anyval_pair is l_data ut_data_value; l_result ut_key_anyval_pair; l_data_type varchar2(500) := 'unknown datatype'; @@ -47,7 +47,9 @@ create or replace package body ut_curr_usr_compound_helper is return ut_key_anyval_pair(a_desc_rec.col_name,l_data); end; - function get_columns_info(a_columns_tab dbms_sql.desc_tab3, a_columns_count integer,a_desc_user_types boolean := false) return ut_key_anyval_pairs is + function get_columns_info( + a_columns_tab dbms_sql.desc_tab3, a_columns_count integer, a_desc_user_types boolean := false + ) return ut_key_anyval_pairs is l_result ut_key_anyval_pairs := ut_key_anyval_pairs(); begin for i in 1 .. a_columns_count loop @@ -57,7 +59,7 @@ create or replace package body ut_curr_usr_compound_helper is return l_result; end; - function get_descr_cursor(a_cursor in out nocopy sys_refcursor,a_desc_user_types boolean := false) return ut_key_anyval_pairs is + function get_descr_cursor(a_cursor in out nocopy sys_refcursor, a_desc_user_types boolean := false) return ut_key_anyval_pairs is l_cursor_number integer; l_columns_count pls_integer; l_columns_desc dbms_sql.desc_tab3; @@ -69,12 +71,15 @@ create or replace package body ut_curr_usr_compound_helper is l_cursor_number := dbms_sql.to_cursor_number( a_cursor ); dbms_sql.describe_columns3( l_cursor_number, l_columns_count, l_columns_desc ); a_cursor := dbms_sql.to_refcursor( l_cursor_number ); - l_columns_tab := get_columns_info( l_columns_desc, l_columns_count,a_desc_user_types); + l_columns_tab := get_columns_info( l_columns_desc, l_columns_count, a_desc_user_types); return l_columns_tab; end; - procedure get_descr_cursor(a_cursor in out nocopy sys_refcursor,a_columns_tab in out ut_key_anyval_pairs, - a_join_by_tab in out ut_key_anyval_pairs) is + procedure get_descr_cursor( + a_cursor in out nocopy sys_refcursor, + a_columns_tab in out nocopy ut_key_anyval_pairs, + a_join_by_tab in out nocopy ut_key_anyval_pairs + ) is l_cursor_number integer; l_columns_count pls_integer; l_columns_desc dbms_sql.desc_tab3; @@ -86,12 +91,16 @@ create or replace package body ut_curr_usr_compound_helper is l_cursor_number := dbms_sql.to_cursor_number( a_cursor ); dbms_sql.describe_columns3( l_cursor_number, l_columns_count, l_columns_desc ); a_cursor := dbms_sql.to_refcursor( l_cursor_number ); - a_columns_tab := get_columns_info( l_columns_desc, l_columns_count,false); - a_join_by_tab := get_columns_info( l_columns_desc, l_columns_count,true); + a_columns_tab := get_columns_info( l_columns_desc, l_columns_count, false); + a_join_by_tab := get_columns_info( l_columns_desc, l_columns_count, true); end; - procedure get_columns_info(a_cursor in out nocopy sys_refcursor,a_columns_info out xmltype, - a_join_by_info out xmltype, a_contains_collection out number) is + procedure get_columns_info( + a_cursor in out nocopy sys_refcursor, + a_columns_info out nocopy xmltype, + a_join_by_info out nocopy xmltype, + a_contains_collection out nocopy number + ) is l_columns_info xmltype; l_join_by_info xmltype; l_result_tmp xmltype; @@ -119,7 +128,7 @@ create or replace package body ut_curr_usr_compound_helper is a_contains_collection := ut_utils.boolean_to_int(g_is_collection); end; - function get_columns_info(a_cursor in out nocopy sys_refcursor,a_desc_user_types boolean := false) return xmltype is + function get_columns_info(a_cursor in out nocopy sys_refcursor, a_desc_user_types boolean := false) return xmltype is l_result xmltype; l_result_tmp xmltype; l_columns_tab ut_key_anyval_pairs; diff --git a/source/expectations/data_values/ut_curr_usr_compound_helper.pks b/source/expectations/data_values/ut_curr_usr_compound_helper.pks index 7c622f0c2..4bf32cf31 100644 --- a/source/expectations/data_values/ut_curr_usr_compound_helper.pks +++ b/source/expectations/data_values/ut_curr_usr_compound_helper.pks @@ -1,12 +1,16 @@ create or replace package ut_curr_usr_compound_helper authid current_user is - procedure get_columns_info(a_cursor in out nocopy sys_refcursor,a_columns_info out xmltype, - a_join_by_info out xmltype, a_contains_collection out number); + procedure get_columns_info( + a_cursor in out nocopy sys_refcursor, + a_columns_info out nocopy xmltype, + a_join_by_info out nocopy xmltype, + a_contains_collection out nocopy number + ); function get_columns_info(a_cursor in out nocopy sys_refcursor, a_desc_user_types boolean := false) return xmltype; - function get_user_defined_type(a_owner varchar2,a_type_name varchar2) return xmltype; + function get_user_defined_type(a_owner varchar2, a_type_name varchar2) return xmltype; end; / diff --git a/source/install.sql b/source/install.sql index 0bd30222c..7a8d89614 100644 --- a/source/install.sql +++ b/source/install.sql @@ -68,6 +68,7 @@ alter session set current_schema = &&ut3_owner; @@install_component.sql 'core/types/ut_test.tps' @@install_component.sql 'core/types/ut_logical_suite.tps' @@install_component.sql 'core/types/ut_suite.tps' +@@install_component.sql 'core/types/ut_suite_context.tps' @@install_component.sql 'core/types/ut_file_mapping.tps' @@install_component.sql 'core/types/ut_file_mappings.tps' @@install_component.sql 'core/types/ut_coverage_options.tps' @@ -151,6 +152,7 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@install_component.sql 'core/types/ut_test.tpb' @@install_component.sql 'core/types/ut_logical_suite.tpb' @@install_component.sql 'core/types/ut_suite.tpb' +@@install_component.sql 'core/types/ut_suite_context.tpb' @@install_component.sql 'core/types/ut_run.tpb' @@install_component.sql 'core/types/ut_expectation_result.tpb' @@install_component.sql 'core/types/ut_reporter_base.tpb' @@ -162,8 +164,6 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@install_component.sql 'core/types/ut_console_reporter_base.tpb' --expectations and matchers -@@install_component.sql 'expectations/data_values/ut_key_anyval_pair.tps' -@@install_component.sql 'expectations/data_values/ut_key_anyval_pairs.tps' @@install_component.sql 'expectations/data_values/ut_compound_data_tmp.sql' @@install_component.sql 'expectations/data_values/ut_compound_data_diff_tmp.sql' @@install_component.sql 'expectations/data_values/ut_data_value.tps' @@ -184,6 +184,8 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@install_component.sql 'expectations/data_values/ut_data_value_varchar2.tps' @@install_component.sql 'expectations/data_values/ut_data_value_yminterval.tps' @@install_component.sql 'expectations/data_values/ut_data_value_xmltype.tps' +@@install_component.sql 'expectations/data_values/ut_key_anyval_pair.tps' +@@install_component.sql 'expectations/data_values/ut_key_anyval_pairs.tps' @@install_component.sql 'expectations/data_values/ut_compound_data_helper.pks' @@install_component.sql 'expectations/data_values/ut_curr_usr_compound_helper.pks' @@install_component.sql 'expectations/matchers/ut_matcher.tps' diff --git a/source/install_component.sql b/source/install_component.sql index 1248c872f..5a9fc7e56 100644 --- a/source/install_component.sql +++ b/source/install_component.sql @@ -18,5 +18,6 @@ set heading off set feedback off exec dbms_output.put_line('Installing component '||upper(regexp_substr('&&1','\/(\w*)\.',1,1,'i',1))); @@&&1 +show errors exec dbms_output.put_line('&&line_separator'); diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index 48bf7cc76..cf8b3905f 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -193,6 +193,8 @@ drop type ut_file_mappings force; drop type ut_file_mapping force; +drop type ut_suite_context force; + drop type ut_suite force; drop type ut_logical_suite force; diff --git a/test/core/test_suite_builder.pkb b/test/core/test_suite_builder.pkb index 4bdd8095d..c159be4f0 100644 --- a/test/core/test_suite_builder.pkb +++ b/test/core/test_suite_builder.pkb @@ -485,8 +485,9 @@ create or replace package body test_suite_builder is ut3.ut_annotation(1, 'suite','Cool', null), ut3.ut_annotation(2, 'beforeall',null, 'suite_level_beforeall'), ut3.ut_annotation(3, 'test','In suite', 'suite_level_test'), - ut3.ut_annotation(4, 'context','A context', null), - ut3.ut_annotation(5, 'beforeall',null, 'context_setup'), + ut3.ut_annotation(4, 'context','a_context', null), + ut3.ut_annotation(5, 'displayname','A context', null), + ut3.ut_annotation(6, 'beforeall',null, 'context_setup'), ut3.ut_annotation(7, 'test', 'In context', 'test_in_a_context'), ut3.ut_annotation(8, 'endcontext',null, null) ); @@ -498,10 +499,10 @@ create or replace package body test_suite_builder is '%' || '%' || '' || - '%context_1A contextsome_package.context_1' || + '%a_contextA contextsome_package.a_context' || '%' || '' || - '%test_in_a_contextIn contextsome_package.context_1.test_in_a_context' || + '%test_in_a_contextIn contextsome_package.a_context.test_in_a_context' || '%' || '' || '' || @@ -529,7 +530,7 @@ create or replace package body test_suite_builder is l_annotations := ut3.ut_annotations( ut3.ut_annotation(1, 'suite','Cool', null), ut3.ut_annotation(2, 'test','In suite', 'suite_level_test'), - ut3.ut_annotation(3, 'context','A context', null), + ut3.ut_annotation(3, 'context','a_context', null), ut3.ut_annotation(4, 'beforeall',null, 'context_beforeall'), ut3.ut_annotation(5, 'beforeeach',null, 'context_beforeeach'), ut3.ut_annotation(6, 'test', 'In context', 'test_in_a_context'), @@ -544,7 +545,7 @@ create or replace package body test_suite_builder is '' || '%' || '%' || - '%context_1' || + '%a_context' || '%' || '%' || '%test_in_a_context' || @@ -579,7 +580,7 @@ create or replace package body test_suite_builder is ut3.ut_annotation(2, 'beforeall',null, 'suite_level_beforeall'), ut3.ut_annotation(3, 'beforeeach',null, 'suite_level_beforeeach'), ut3.ut_annotation(4, 'test','In suite', 'suite_level_test'), - ut3.ut_annotation(5, 'context','A context', null), + ut3.ut_annotation(5, 'context','a_context', null), ut3.ut_annotation(6, 'test', 'In context', 'test_in_a_context'), ut3.ut_annotation(7, 'endcontext',null, null), ut3.ut_annotation(8, 'aftereach',null, 'suite_level_aftereach'), @@ -592,7 +593,7 @@ create or replace package body test_suite_builder is '' || '%' || '%' || - '%context_1' || + '%a_context' || '%' || '%' || '%test_in_a_context' || @@ -665,8 +666,9 @@ create or replace package body test_suite_builder is ut3.ut_annotation(1, 'suite','Cool', null), ut3.ut_annotation(2, 'beforeall',null, 'suite_level_beforeall'), ut3.ut_annotation(3, 'test','In suite', 'suite_level_test'), - ut3.ut_annotation(4, 'context','A context', null), - ut3.ut_annotation(5, 'beforeall',null, 'context_setup'), + ut3.ut_annotation(4, 'context','a_context', null), + ut3.ut_annotation(5, 'displayname','A context', null), + ut3.ut_annotation(6, 'beforeall',null, 'context_setup'), ut3.ut_annotation(7, 'test', 'In context', 'test_in_a_context'), ut3.ut_annotation(8, 'endcontext',null, null), ut3.ut_annotation(9, 'endcontext',null, null) @@ -682,10 +684,10 @@ create or replace package body test_suite_builder is '' || '%' || '' || - '%context_1A contextsome_package.context_1' || + '%a_contextA contextsome_package.a_context' || '%' || '' || - '%test_in_a_contextIn contextsome_package.context_1.test_in_a_context' || + '%test_in_a_contextIn contextsome_package.a_context.test_in_a_context' || '%' || '' || '' || diff --git a/test/core/test_suite_manager.pkb b/test/core/test_suite_manager.pkb index 25f42ab11..59f1f42ea 100644 --- a/test/core/test_suite_manager.pkb +++ b/test/core/test_suite_manager.pkb @@ -242,6 +242,32 @@ end test_package_3;]'; end; end test_package_3;]'; + + execute immediate q'[create or replace package test_package_with_ctx is + + --%suite(test_package_with_ctx) + + gv_glob_val number; + + --%context(some_context) + --%displayname(Some context description) + + --%test + --%displayname(Test1 from test package 1) + procedure test1; + + --%endcontext + +end test_package_with_ctx;]'; + + execute immediate q'[create or replace package body test_package_with_ctx is + + procedure test1 is + begin + null; + end; + +end test_package_with_ctx;]'; end; @@ -251,6 +277,7 @@ end test_package_3;]'; execute immediate 'drop package test_package_1'; execute immediate 'drop package test_package_2'; execute immediate 'drop package test_package_3'; + execute immediate 'drop package test_package_with_ctx'; end; procedure test_schema_run is @@ -1352,5 +1379,59 @@ end;]'; clean_disabled_pck; end; + procedure pck_proc_in_ctx_by_name is + c_path varchar2(100) := USER||'.test_package_with_ctx.test1'; + l_objects_to_run ut3.ut_suite_items; + + l_test_suite ut3.ut_logical_suite; + l_ctx_suite ut3.ut_logical_suite; + l_test_proc ut3.ut_test; + begin + --Act + l_objects_to_run := ut3.ut_suite_manager.configure_execution_by_path(ut3.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + + l_test_suite := treat(l_objects_to_run(1) as ut3.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('test_package_with_ctx'); + ut.expect(l_test_suite.items.count).to_equal(1); + + l_ctx_suite := treat(l_test_suite.items(1) as ut3.ut_logical_suite); + ut.expect(l_ctx_suite.name).to_equal('some_context'); + ut.expect(l_ctx_suite.description).to_equal('Some context description'); + ut.expect(l_ctx_suite.items.count).to_equal(1); + + l_test_proc := treat(l_ctx_suite.items(1) as ut3.ut_test); + ut.expect(l_test_proc.name).to_equal('test1'); + end; + + procedure pck_proc_in_ctx_by_path is + c_path varchar2(100) := USER||':test_package_with_ctx.some_context.test1'; + l_objects_to_run ut3.ut_suite_items; + + l_test_suite ut3.ut_logical_suite; + l_ctx_suite ut3.ut_logical_suite; + l_test_proc ut3.ut_test; + begin + --Act + l_objects_to_run := ut3.ut_suite_manager.configure_execution_by_path(ut3.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + + l_test_suite := treat(l_objects_to_run(1) as ut3.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('test_package_with_ctx'); + ut.expect(l_test_suite.items.count).to_equal(1); + + l_ctx_suite := treat(l_test_suite.items(1) as ut3.ut_logical_suite); + ut.expect(l_ctx_suite.name).to_equal('some_context'); + ut.expect(l_ctx_suite.description).to_equal('Some context description'); + ut.expect(l_ctx_suite.items.count).to_equal(1); + + l_test_proc := treat(l_ctx_suite.items(1) as ut3.ut_test); + ut.expect(l_test_proc.name).to_equal('test1'); + end; + end test_suite_manager; / diff --git a/test/core/test_suite_manager.pks b/test/core/test_suite_manager.pks index 495f317a6..45466b9d2 100644 --- a/test/core/test_suite_manager.pks +++ b/test/core/test_suite_manager.pks @@ -145,5 +145,11 @@ create or replace package test_suite_manager is --%test(Whole suite gets disabled with floating annotation) procedure disable_suite_floating_annot; + --%test(Prepare runner for a package procedure inside context) + procedure pck_proc_in_ctx_by_name; + + --%test(Prepare runner for a package procedure inside context by path) + procedure pck_proc_in_ctx_by_path; + end test_suite_manager; / From 5b33d2f4edbe7f2b449cbd375b776bdb9020f161 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 10 Jun 2018 18:54:15 +0100 Subject: [PATCH 2/3] Fixed coveralls reporting issue with long packages. --- source/reporters/ut_coveralls_reporter.tpb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/reporters/ut_coveralls_reporter.tpb b/source/reporters/ut_coveralls_reporter.tpb index f19d1f3ce..8470d7f76 100644 --- a/source/reporters/ut_coveralls_reporter.tpb +++ b/source/reporters/ut_coveralls_reporter.tpb @@ -42,7 +42,7 @@ create or replace type body ut_coveralls_reporter is if l_last_line_no is null then l_last_line_no := a_unit_coverage.total_lines - 1; for i in 1 .. l_last_line_no loop - ut_utils.append_to_clob(l_result, '0,'); + ut_utils.append_to_clob(l_result, '0,'||chr(10)); end loop; ut_utils.append_to_clob(l_result, '0'); else @@ -55,7 +55,7 @@ create or replace type body ut_coveralls_reporter is if line_no < l_last_line_no then l_file_part := l_file_part ||','; end if; - ut_utils.append_to_clob(l_result, l_file_part); + ut_utils.append_to_clob(l_result, l_file_part||chr(10)); end loop; end if; ut_utils.append_to_clob(l_result, ']'); From ecae542fe46ddf0ea3c234f9f29000d8c405e3b1 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 11 Jun 2018 00:10:31 +0100 Subject: [PATCH 3/3] Fixed failing tests and added additional test for missing coverage. --- source/reporters/ut_coveralls_reporter.tpb | 11 ++-- test/core/reporters/test_coverage.pkb | 17 ++++-- test/core/reporters/test_coverage.pks | 8 +++ .../test_coverage/test_coveralls_reporter.pkb | 54 +++++++++++++++++-- .../test_coverage/test_coveralls_reporter.pks | 3 ++ 5 files changed, 80 insertions(+), 13 deletions(-) diff --git a/source/reporters/ut_coveralls_reporter.tpb b/source/reporters/ut_coveralls_reporter.tpb index 8470d7f76..96df05483 100644 --- a/source/reporters/ut_coveralls_reporter.tpb +++ b/source/reporters/ut_coveralls_reporter.tpb @@ -40,16 +40,15 @@ create or replace type body ut_coveralls_reporter is l_last_line_no := a_unit_coverage.lines.last; if l_last_line_no is null then - l_last_line_no := a_unit_coverage.total_lines - 1; - for i in 1 .. l_last_line_no loop - ut_utils.append_to_clob(l_result, '0,'||chr(10)); - end loop; - ut_utils.append_to_clob(l_result, '0'); + ut_utils.append_to_clob( + l_result + , rpad( to_clob( '0' ), ( a_unit_coverage.total_lines * 3 ) - 2, ','||chr(10)||'0' ) + ); else for line_no in 1 .. l_last_line_no loop if a_unit_coverage.lines.exists(line_no) then l_file_part := to_char(a_unit_coverage.lines(line_no).executions); - else + else l_file_part := c_null; end if; if line_no < l_last_line_no then diff --git a/test/core/reporters/test_coverage.pkb b/test/core/reporters/test_coverage.pkb index 347f4f463..060c8f124 100644 --- a/test/core/reporters/test_coverage.pkb +++ b/test/core/reporters/test_coverage.pkb @@ -1,7 +1,5 @@ create or replace package body test_coverage is - g_run_id integer; - function get_mock_run_id return integer is v_result integer; begin @@ -100,22 +98,32 @@ create or replace package body test_coverage is select a_run_id, c_unit_id, 7, 1, 1 from dual; end; - procedure setup_dummy_coverage is + procedure create_dummy_coverage_pkg is pragma autonomous_transaction; begin create_dummy_coverage_package(); create_dummy_coverage_test(); + end; + + procedure setup_dummy_coverage is + pragma autonomous_transaction; + begin g_run_id := get_mock_run_id(); ut3.ut_coverage.mock_coverage_id(g_run_id, ut3.ut_coverage.gc_proftab_coverage); mock_coverage_data(g_run_id); commit; end; - procedure cleanup_dummy_coverage is + procedure drop_dummy_coverage_pkg is pragma autonomous_transaction; begin begin execute immediate q'[drop package ut3.test_dummy_coverage]'; exception when others then null; end; begin execute immediate q'[drop package ut3.dummy_coverage]'; exception when others then null; end; + end; + + procedure cleanup_dummy_coverage is + pragma autonomous_transaction; + begin delete from ut3.plsql_profiler_data where runid = g_run_id; delete from ut3.plsql_profiler_units where runid = g_run_id; delete from ut3.plsql_profiler_runs where runid = g_run_id; @@ -229,6 +237,7 @@ create or replace package body test_coverage is ) ); cleanup_dummy_coverage(); + drop_dummy_coverage_pkg(); create_dummy_coverage_test_1; --Act diff --git a/test/core/reporters/test_coverage.pks b/test/core/reporters/test_coverage.pks index d507fa0ee..65e99666b 100644 --- a/test/core/reporters/test_coverage.pks +++ b/test/core/reporters/test_coverage.pks @@ -3,9 +3,16 @@ create or replace package test_coverage is --%suite --%suitepath(utplsql.core.reporters) + g_run_id integer; + + --%beforeall + procedure create_dummy_coverage_pkg; --%beforeall procedure setup_dummy_coverage; + + --%afterall + procedure drop_dummy_coverage_pkg; --%afterall procedure cleanup_dummy_coverage; @@ -23,6 +30,7 @@ create or replace package test_coverage is procedure coverage_for_file; --%test(Coverage data is not cached between runs - issue #562 ) + --%aftertest(create_dummy_coverage_pkg) --%aftertest(setup_dummy_coverage) procedure coverage_tmp_data_refresh; diff --git a/test/core/reporters/test_coverage/test_coveralls_reporter.pkb b/test/core/reporters/test_coverage/test_coveralls_reporter.pkb index 2efa8f0ca..3b6b88346 100644 --- a/test/core/reporters/test_coverage/test_coveralls_reporter.pkb +++ b/test/core/reporters/test_coverage/test_coveralls_reporter.pkb @@ -6,10 +6,17 @@ create or replace package body test_coveralls_reporter is l_actual clob; begin --Arrange - l_expected := '{"source_files":[ + l_expected := q'[{"source_files":[ { "name": "test/ut3.dummy_coverage.pkb", -"coverage": [null,null,null,1,0,null,1]}]} - '; +"coverage": [null, +null, +null, +1, +0, +null, +1 +]}]} + ]'; --Act select * bulk collect into l_results @@ -26,5 +33,46 @@ create or replace package body test_coveralls_reporter is ut.expect(l_actual).to_equal(l_expected); end; + procedure report_zero_coverage is + l_results ut3.ut_varchar2_list; + l_expected clob; + l_actual clob; + pragma autonomous_transaction; + begin + --Arrange + l_expected := q'[{"source_files":[ +{ "name": "ut3.dummy_coverage", +"coverage": [0, +0, +0, +0, +0, +0, +0, +0, +0, +0]}]} + ]'; + + test_coverage.cleanup_dummy_coverage; + + --Act + select * + bulk collect into l_results + from table( + ut3.ut.run( + 'ut3.test_dummy_coverage', + ut3.ut_coveralls_reporter(), + a_include_objects => ut3.ut_varchar2_list('UT3.DUMMY_COVERAGE') + ) + ); + l_actual := ut3.ut_utils.table_to_clob(l_results); + --Assert + ut.expect(l_actual).to_equal(l_expected); + + test_coverage.setup_dummy_coverage; + + end; + end; / diff --git a/test/core/reporters/test_coverage/test_coveralls_reporter.pks b/test/core/reporters/test_coverage/test_coveralls_reporter.pks index a479e69a2..bf2b861f7 100644 --- a/test/core/reporters/test_coverage/test_coveralls_reporter.pks +++ b/test/core/reporters/test_coverage/test_coveralls_reporter.pks @@ -6,5 +6,8 @@ create or replace package test_coveralls_reporter is --%test(reports on a project file mapped to database object) procedure report_on_file; + --%test(reports zero coverage on each line of non-executed database object) + procedure report_zero_coverage; + end; /