Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 87e456e

Browse files
authored
Merge pull request #529 from utPLSQL/feature/suite_manager_refactoting
Separated suite building from suite run management.
2 parents 72fa833 + 2f919b4 commit 87e456e

16 files changed

Lines changed: 382 additions & 239 deletions

source/core/types/ut_logical_suite.tpb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@ create or replace type body ut_logical_suite as
5252
self.items(self.items.last) := a_item;
5353
end;
5454

55+
overriding member procedure mark_as_skipped(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base) is
56+
begin
57+
a_listener.fire_before_event(ut_utils.gc_suite,self);
58+
self.start_time := current_timestamp;
59+
for i in 1 .. self.items.count loop
60+
self.items(i).mark_as_skipped(a_listener);
61+
end loop;
62+
self.end_time := self.start_time;
63+
a_listener.fire_after_event(ut_utils.gc_suite,self);
64+
self.calc_execution_result();
65+
end;
66+
5567
overriding member function do_execute(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base) return boolean is
5668
l_suite_savepoint varchar2(30);
5769
l_item_savepoint varchar2(30);

source/core/types/ut_logical_suite.tps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ create or replace type ut_logical_suite under ut_suite_item (
3030
*/
3131
member function item_index(a_name varchar2) return pls_integer,
3232
member procedure add_item(self in out nocopy ut_logical_suite, a_item ut_suite_item),
33+
overriding member procedure mark_as_skipped(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base),
3334
overriding member function do_execute(self in out nocopy ut_logical_suite, a_listener in out nocopy ut_event_listener_base) return boolean,
3435
overriding member procedure calc_execution_result(self in out nocopy ut_logical_suite),
3536
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),

source/core/types/ut_run.tpb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,17 @@ create or replace type body ut_run as
4747
return;
4848
end;
4949

50+
overriding member procedure mark_as_skipped(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base) is
51+
begin
52+
null;
53+
end;
54+
5055
overriding member function do_execute(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base) return boolean is
5156
l_completed_without_errors boolean;
5257
begin
5358
ut_utils.debug_log('ut_run.execute');
5459

5560
a_listener.fire_before_event(ut_utils.gc_run, self);
56-
5761
self.start_time := current_timestamp;
5862

5963
-- clear anything that might stay in the session's cache

source/core/types/ut_run.tps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ create or replace type ut_run under ut_suite_item (
3333
a_project_file_mappings ut_file_mappings := null,
3434
a_test_file_mappings ut_file_mappings := null
3535
) return self as result,
36+
overriding member procedure mark_as_skipped(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base),
3637
overriding member function do_execute(self in out nocopy ut_run, a_listener in out nocopy ut_event_listener_base) return boolean,
3738
overriding member procedure calc_execution_result(self in out nocopy ut_run),
3839
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),

source/core/types/ut_suite.tpb

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,11 @@ create or replace type body ut_suite as
5454

5555
ut_utils.set_action(self.object_name);
5656

57-
a_listener.fire_before_event(ut_utils.gc_suite,self);
58-
59-
self.start_time := current_timestamp;
60-
6157
if self.get_disabled_flag() then
62-
for i in 1 .. self.items.count loop
63-
self.items(i).do_execute(a_listener);
64-
end loop;
65-
ut_utils.debug_log('ut_suite.execute - disabled');
58+
self.mark_as_skipped(a_listener);
6659
else
67-
60+
a_listener.fire_before_event(ut_utils.gc_suite,self);
61+
self.start_time := current_timestamp;
6862
if self.is_valid() then
6963

7064
l_suite_savepoint := self.create_savepoint_if_needed();
@@ -90,10 +84,10 @@ create or replace type body ut_suite as
9084
else
9185
propagate_error(ut_utils.table_to_clob(self.get_error_stack_traces()));
9286
end if;
87+
self.calc_execution_result();
88+
self.end_time := current_timestamp;
89+
a_listener.fire_after_event(ut_utils.gc_suite,self);
9390
end if;
94-
self.calc_execution_result();
95-
self.end_time := current_timestamp;
96-
a_listener.fire_after_event(ut_utils.gc_suite,self);
9791

9892
ut_utils.set_action(null);
9993

source/core/types/ut_suite.tps

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ create or replace type ut_suite under ut_logical_suite (
3232
a_after_all_proc_name varchar2 := null
3333
) return self as result,
3434
overriding member function is_valid(self in out nocopy ut_suite) return boolean,
35-
/**
36-
* Finds the item in the suite by it's name and returns the item index
37-
*/
3835
overriding member function do_execute(self in out nocopy ut_suite , a_listener in out nocopy ut_event_listener_base) return boolean,
3936
overriding member function get_error_stack_traces(self ut_suite) return ut_varchar2_list,
4037
overriding member function get_serveroutputs return clob

source/core/types/ut_suite_item.tps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ create or replace type ut_suite_item force under ut_suite_item_base (
2323
a_description varchar2, a_path varchar2, a_rollback_type integer, a_disabled_flag boolean),
2424
member procedure set_disabled_flag(self in out nocopy ut_suite_item, a_disabled_flag boolean),
2525
member function get_disabled_flag return boolean,
26+
not instantiable member procedure mark_as_skipped(self in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base),
2627
member function create_savepoint_if_needed return varchar2,
2728
member procedure rollback_to_savepoint(self in out nocopy ut_suite_item, a_savepoint varchar2),
2829
member function get_transaction_invalidators return ut_varchar2_list,

source/core/types/ut_test.tpb

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,29 @@ create or replace type body ut_test as
5353
return l_is_valid;
5454
end;
5555

56+
overriding member procedure mark_as_skipped(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base) is
57+
begin
58+
a_listener.fire_before_event(ut_utils.gc_test,self);
59+
self.start_time := current_timestamp;
60+
self.result := ut_utils.tr_disabled;
61+
ut_utils.debug_log('ut_test.execute - disabled');
62+
self.results_count.set_counter_values(self.result);
63+
self.end_time := self.start_time;
64+
a_listener.fire_after_event(ut_utils.gc_test,self);
65+
end;
66+
5667
overriding member function do_execute(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base) return boolean is
5768
l_completed_without_errors boolean;
5869
l_savepoint varchar2(30);
5970
begin
6071

6172
ut_utils.debug_log('ut_test.execute');
6273

63-
a_listener.fire_before_event(ut_utils.gc_test,self);
64-
self.start_time := current_timestamp;
65-
6674
if self.get_disabled_flag() then
67-
self.result := ut_utils.tr_disabled;
68-
ut_utils.debug_log('ut_test.execute - disabled');
69-
self.results_count.set_counter_values(self.result);
70-
self.end_time := self.start_time;
75+
mark_as_skipped(a_listener);
7176
else
77+
a_listener.fire_before_event(ut_utils.gc_test,self);
78+
self.start_time := current_timestamp;
7279
if self.is_valid() then
7380

7481
l_savepoint := self.create_savepoint_if_needed();
@@ -94,8 +101,8 @@ create or replace type body ut_test as
94101

95102
self.calc_execution_result();
96103
self.end_time := current_timestamp;
104+
a_listener.fire_after_event(ut_utils.gc_test,self);
97105
end if;
98-
a_listener.fire_after_event(ut_utils.gc_test,self);
99106
return l_completed_without_errors;
100107
end;
101108

source/core/types/ut_test.tps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ create or replace type ut_test under ut_suite_item (
5858
member function is_valid(self in out nocopy ut_test) return boolean,
5959
member procedure set_beforeeach(self in out nocopy ut_test, a_before_each_proc_name varchar2),
6060
member procedure set_aftereach(self in out nocopy ut_test, a_after_each_proc_name varchar2),
61+
overriding member procedure mark_as_skipped(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base),
6162
overriding member function do_execute(self in out nocopy ut_test, a_listener in out nocopy ut_event_listener_base) return boolean,
6263
overriding member procedure calc_execution_result(self in out nocopy ut_test),
6364
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),

source/core/ut_suite_builder.pkb

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
create or replace package body ut_suite_builder is
2+
/*
3+
utPLSQL - Version 3
4+
Copyright 2016 - 2017 utPLSQL Project
5+
6+
Licensed under the Apache License, Version 2.0 (the "License"):
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
------------------
20+
21+
function create_suite(a_object ut_annotated_object) return ut_logical_suite is
22+
l_is_suite boolean := false;
23+
l_is_test boolean := false;
24+
l_suite_disabled boolean := false;
25+
l_test_disabled boolean := false;
26+
l_suite_items ut_suite_items := ut_suite_items();
27+
l_suite_name varchar2(4000);
28+
29+
l_default_setup_proc varchar2(250 char);
30+
l_default_teardown_proc varchar2(250 char);
31+
l_suite_setup_proc varchar2(250 char);
32+
l_suite_teardown_proc varchar2(250 char);
33+
l_suite_path varchar2(4000 char);
34+
35+
l_proc_name varchar2(250 char);
36+
37+
l_suite ut_logical_suite;
38+
l_test ut_test;
39+
40+
l_suite_rollback integer;
41+
42+
l_beforetest_procedure varchar2(250 char);
43+
l_aftertest_procedure varchar2(250 char);
44+
l_rollback_type integer;
45+
l_displayname varchar2(4000);
46+
function is_last_annotation_for_proc(a_annotations ut_annotations, a_index binary_integer) return boolean is
47+
begin
48+
return a_index = a_annotations.count or a_annotations(a_index).subobject_name != nvl(a_annotations(a_index+1).subobject_name, ' ');
49+
end;
50+
begin
51+
l_suite_rollback := ut_utils.gc_rollback_auto;
52+
for i in 1 .. a_object.annotations.count loop
53+
54+
if a_object.annotations(i).subobject_name is null then
55+
56+
if a_object.annotations(i).name in ('suite','displayname') then
57+
l_suite_name := a_object.annotations(i).text;
58+
if a_object.annotations(i).name = 'suite' then
59+
l_is_suite := true;
60+
end if;
61+
elsif a_object.annotations(i).name = 'disabled' then
62+
l_suite_disabled := true;
63+
elsif a_object.annotations(i).name = 'suitepath' and a_object.annotations(i).text is not null then
64+
l_suite_path := a_object.annotations(i).text || '.' || lower(a_object.object_name);
65+
elsif a_object.annotations(i).name = 'rollback' then
66+
if lower(a_object.annotations(i).text) = 'manual' then
67+
l_suite_rollback := ut_utils.gc_rollback_manual;
68+
else
69+
l_suite_rollback := ut_utils.gc_rollback_auto;
70+
end if;
71+
end if;
72+
73+
elsif l_is_suite then
74+
75+
l_proc_name := a_object.annotations(i).subobject_name;
76+
77+
if a_object.annotations(i).name = 'beforeeach' and l_default_setup_proc is null then
78+
l_default_setup_proc := l_proc_name;
79+
elsif a_object.annotations(i).name = 'aftereach' and l_default_teardown_proc is null then
80+
l_default_teardown_proc := l_proc_name;
81+
elsif a_object.annotations(i).name = 'beforeall' and l_suite_setup_proc is null then
82+
l_suite_setup_proc := l_proc_name;
83+
elsif a_object.annotations(i).name = 'afterall' and l_suite_teardown_proc is null then
84+
l_suite_teardown_proc := l_proc_name;
85+
86+
87+
elsif a_object.annotations(i).name = 'disabled' then
88+
l_test_disabled := true;
89+
elsif a_object.annotations(i).name = 'beforetest' then
90+
l_beforetest_procedure := a_object.annotations(i).text;
91+
elsif a_object.annotations(i).name = 'aftertest' then
92+
l_aftertest_procedure := a_object.annotations(i).text;
93+
elsif a_object.annotations(i).name in ('displayname','test') then
94+
l_displayname := a_object.annotations(i).text;
95+
if a_object.annotations(i).name = 'test' then
96+
l_is_test := true;
97+
end if;
98+
elsif a_object.annotations(i).name = 'rollback' then
99+
if lower(a_object.annotations(i).text) = 'manual' then
100+
l_rollback_type := ut_utils.gc_rollback_manual;
101+
elsif lower(a_object.annotations(i).text) = 'auto' then
102+
l_rollback_type := ut_utils.gc_rollback_auto;
103+
end if;
104+
end if;
105+
106+
if l_is_test and is_last_annotation_for_proc(a_object.annotations, i) then
107+
l_suite_items.extend;
108+
l_suite_items(l_suite_items.last) :=
109+
ut_test(a_object_owner => a_object.object_owner
110+
,a_object_name => a_object.object_name
111+
,a_name => l_proc_name
112+
,a_description => l_displayname
113+
,a_rollback_type => coalesce(l_rollback_type, l_suite_rollback)
114+
,a_disabled_flag => l_test_disabled
115+
,a_before_test_proc_name => l_beforetest_procedure
116+
,a_after_test_proc_name => l_aftertest_procedure);
117+
118+
l_is_test := false;
119+
l_test_disabled := false;
120+
l_aftertest_procedure := null;
121+
l_beforetest_procedure := null;
122+
l_rollback_type := null;
123+
end if;
124+
125+
end if;
126+
end loop;
127+
128+
if l_is_suite then
129+
l_suite := ut_suite (
130+
a_object_owner => a_object.object_owner,
131+
a_object_name => a_object.object_name,
132+
a_name => a_object.object_name, --this could be different for sub-suite (context)
133+
a_path => l_suite_path, --a patch for this suite (excluding the package name of current suite)
134+
a_description => l_suite_name,
135+
a_rollback_type => l_suite_rollback,
136+
a_disabled_flag => l_suite_disabled,
137+
a_before_all_proc_name => l_suite_setup_proc,
138+
a_after_all_proc_name => l_suite_teardown_proc
139+
);
140+
for i in 1 .. l_suite_items.count loop
141+
l_test := treat(l_suite_items(i) as ut_test);
142+
l_test.set_beforeeach(l_default_setup_proc);
143+
l_test.set_aftereach(l_default_teardown_proc);
144+
l_test.path := l_suite.path || '.' || l_test.name;
145+
l_suite.add_item(l_test);
146+
end loop;
147+
end if;
148+
149+
return l_suite;
150+
151+
end create_suite;
152+
153+
function build_suites_hierarchy(a_suites_by_path tt_schema_suites) return tt_schema_suites is
154+
l_result tt_schema_suites;
155+
l_suite_path varchar2(4000 char);
156+
l_parent_path varchar2(4000 char);
157+
l_name varchar2(4000 char);
158+
l_suites_by_path tt_schema_suites;
159+
begin
160+
l_suites_by_path := a_suites_by_path;
161+
--were iterating in reverse order of the index by path table
162+
-- so the first paths will be the leafs of hierarchy and next will their parents
163+
l_suite_path := l_suites_by_path.last;
164+
ut_utils.debug_log('Input suites to process = '||l_suites_by_path.count);
165+
166+
while l_suite_path is not null loop
167+
l_parent_path := substr( l_suite_path, 1, instr(l_suite_path,'.',-1)-1);
168+
ut_utils.debug_log('Processing l_suite_path = "'||l_suite_path||'", l_parent_path = "'||l_parent_path||'"');
169+
--no parent => I'm a root element
170+
if l_parent_path is null then
171+
ut_utils.debug_log(' suite "'||l_suite_path||'" is a root element - adding to return list.');
172+
l_result(l_suite_path) := l_suites_by_path(l_suite_path);
173+
-- not a root suite - need to add it to a parent suite
174+
else
175+
--parent does not exist and needs to be added
176+
if not l_suites_by_path.exists(l_parent_path) then
177+
l_name := substr( l_parent_path, instr(l_parent_path,'.',-1)+1);
178+
ut_utils.debug_log(' Parent suite "'||l_parent_path||'" not found in the list - Adding suite "'||l_name||'"');
179+
l_suites_by_path(l_parent_path) :=
180+
ut_logical_suite(
181+
a_object_owner => l_suites_by_path(l_suite_path).object_owner,
182+
a_object_name => l_name, a_name => l_name, a_path => l_parent_path
183+
);
184+
else
185+
ut_utils.debug_log(' Parent suite "'||l_parent_path||'" found in list of suites');
186+
end if;
187+
ut_utils.debug_log(' adding suite "'||l_suite_path||'" to "'||l_parent_path||'" items');
188+
l_suites_by_path(l_parent_path).add_item( l_suites_by_path(l_suite_path) );
189+
end if;
190+
l_suite_path := l_suites_by_path.prior(l_suite_path);
191+
end loop;
192+
ut_utils.debug_log(l_result.count||' root suites created.');
193+
return l_result;
194+
end;
195+
196+
function build_suites(a_annotated_objects sys_refcursor) return t_schema_suites_info is
197+
l_suite ut_logical_suite;
198+
l_annotated_objects ut_annotated_objects;
199+
l_all_suites tt_schema_suites;
200+
l_result t_schema_suites_info;
201+
begin
202+
fetch a_annotated_objects bulk collect into l_annotated_objects;
203+
close a_annotated_objects;
204+
205+
for i in 1 .. l_annotated_objects.count loop
206+
l_suite := create_suite(l_annotated_objects(i));
207+
if l_suite is not null then
208+
l_all_suites(l_suite.path) := l_suite;
209+
l_result.suite_paths(l_suite.object_name) := l_suite.path;
210+
end if;
211+
end loop;
212+
213+
--build hierarchical structure of the suite
214+
-- Restructure single-dimension list into hierarchy of suites by the value of %suitepath attribute value
215+
l_result.schema_suites := build_suites_hierarchy(l_all_suites);
216+
217+
return l_result;
218+
end;
219+
220+
function build_schema_suites(a_owner_name varchar2) return t_schema_suites_info is
221+
l_annotations_cursor sys_refcursor;
222+
begin
223+
-- form the single-dimension list of suites constructed from parsed packages
224+
open l_annotations_cursor for
225+
q'[select value(x)
226+
from table(
227+
]'||ut_utils.ut_owner||q'[.ut_annotation_manager.get_annotated_objects(:a_owner_name, 'PACKAGE')
228+
)x ]'
229+
using a_owner_name;
230+
231+
return build_suites(l_annotations_cursor);
232+
end;
233+
234+
end ut_suite_builder;
235+
/

0 commit comments

Comments
 (0)