Skip to content
Permalink
Browse files

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
  • Loading branch information...
jgebal committed Jun 7, 2018
1 parent eb1088e commit 4f8caa4917239cefb3964f155f32d55168a801bd
@@ -30,7 +30,7 @@ We strongly recommend putting package level annotations at the very top of packa
| `--%aftertest(<procedure_name>)` | Procedure | Denotes that mentioned procedure should be executed after the annotated `%test` procedure. |
| `--%rollback(<type>)` | 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(<description>)` | Package | Denotes start of a nested context (sub-suite) in a suite package |
| `--%context(<name>)` | 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)
@@ -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);
@@ -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();
@@ -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
/
@@ -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;
/
@@ -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
)
/
@@ -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();
@@ -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)
*/
@@ -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);
@@ -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);
@@ -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
*/

/**
@@ -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,'--');
@@ -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
Oops, something went wrong.

0 comments on commit 4f8caa4

Please sign in to comment.
You can’t perform that action at this time.