Skip to content

Commit 203f6a1

Browse files
committed
Separated suite building from suite run management.
Added ability to pass cursor to build suites.
1 parent fac6a80 commit 203f6a1

File tree

5 files changed

+294
-209
lines changed

5 files changed

+294
-209
lines changed

source/core/ut_suite_builder.pkb

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
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+
47+
begin
48+
l_suite_rollback := ut_utils.gc_rollback_auto;
49+
for i in 1 .. a_object.annotations.count loop
50+
51+
if a_object.annotations(i).subobject_name is null then
52+
53+
if a_object.annotations(i).name in ('suite','displayname') then
54+
l_suite_name := a_object.annotations(i).text;
55+
if a_object.annotations(i).name = 'suite' then
56+
l_is_suite := true;
57+
end if;
58+
elsif a_object.annotations(i).name = 'disabled' then
59+
l_suite_disabled := true;
60+
elsif a_object.annotations(i).name = 'suitepath' and a_object.annotations(i).text is not null then
61+
l_suite_path := a_object.annotations(i).text || '.' || lower(a_object.object_name);
62+
elsif a_object.annotations(i).name = 'rollback' then
63+
if lower(a_object.annotations(i).text) = 'manual' then
64+
l_suite_rollback := ut_utils.gc_rollback_manual;
65+
else
66+
l_suite_rollback := ut_utils.gc_rollback_auto;
67+
end if;
68+
end if;
69+
70+
elsif l_is_suite then
71+
72+
l_proc_name := a_object.annotations(i).subobject_name;
73+
74+
if a_object.annotations(i).name = 'beforeeach' and l_default_setup_proc is null then
75+
l_default_setup_proc := l_proc_name;
76+
elsif a_object.annotations(i).name = 'aftereach' and l_default_teardown_proc is null then
77+
l_default_teardown_proc := l_proc_name;
78+
elsif a_object.annotations(i).name = 'beforeall' and l_suite_setup_proc is null then
79+
l_suite_setup_proc := l_proc_name;
80+
elsif a_object.annotations(i).name = 'afterall' and l_suite_teardown_proc is null then
81+
l_suite_teardown_proc := l_proc_name;
82+
83+
84+
elsif a_object.annotations(i).name = 'disabled' then
85+
l_test_disabled := true;
86+
elsif a_object.annotations(i).name = 'beforetest' then
87+
l_beforetest_procedure := a_object.annotations(i).text;
88+
elsif a_object.annotations(i).name = 'aftertest' then
89+
l_aftertest_procedure := a_object.annotations(i).text;
90+
elsif a_object.annotations(i).name in ('displayname','test') then
91+
l_displayname := a_object.annotations(i).text;
92+
if a_object.annotations(i).name = 'test' then
93+
l_is_test := true;
94+
end if;
95+
elsif a_object.annotations(i).name = 'rollback' then
96+
if lower(a_object.annotations(i).text) = 'manual' then
97+
l_rollback_type := ut_utils.gc_rollback_manual;
98+
elsif lower(a_object.annotations(i).text) = 'auto' then
99+
l_rollback_type := ut_utils.gc_rollback_auto;
100+
end if;
101+
end if;
102+
103+
if l_is_test
104+
and (i = a_object.annotations.count
105+
or l_proc_name != nvl(a_object.annotations(i+1).subobject_name, ' ') ) then
106+
l_suite_items.extend;
107+
l_suite_items(l_suite_items.last) :=
108+
ut_test(a_object_owner => a_object.object_owner
109+
,a_object_name => a_object.object_name
110+
,a_name => l_proc_name
111+
,a_description => l_displayname
112+
,a_rollback_type => coalesce(l_rollback_type, l_suite_rollback)
113+
,a_disabled_flag => l_suite_disabled or l_test_disabled
114+
,a_before_test_proc_name => l_beforetest_procedure
115+
,a_after_test_proc_name => l_aftertest_procedure);
116+
117+
l_is_test := false;
118+
l_test_disabled := false;
119+
l_aftertest_procedure := null;
120+
l_beforetest_procedure := null;
121+
l_rollback_type := null;
122+
end if;
123+
124+
end if;
125+
end loop;
126+
127+
if l_is_suite then
128+
l_suite := ut_suite (
129+
a_object_owner => a_object.object_owner,
130+
a_object_name => a_object.object_name,
131+
a_name => a_object.object_name, --this could be different for sub-suite (context)
132+
a_path => l_suite_path, --a patch for this suite (excluding the package name of current suite)
133+
a_description => l_suite_name,
134+
a_rollback_type => l_suite_rollback,
135+
a_disabled_flag => l_suite_disabled,
136+
a_before_all_proc_name => l_suite_setup_proc,
137+
a_after_all_proc_name => l_suite_teardown_proc
138+
);
139+
for i in 1 .. l_suite_items.count loop
140+
l_test := treat(l_suite_items(i) as ut_test);
141+
l_test.set_beforeeach(l_default_setup_proc);
142+
l_test.set_aftereach(l_default_teardown_proc);
143+
l_test.path := l_suite.path || '.' || l_test.name;
144+
l_suite.add_item(l_test);
145+
end loop;
146+
end if;
147+
148+
return l_suite;
149+
150+
end create_suite;
151+
152+
function build_suites_hierarchy(a_suites_by_path tt_schema_suites) return tt_schema_suites is
153+
l_result tt_schema_suites;
154+
l_suite_path varchar2(4000 char);
155+
l_parent_path varchar2(4000 char);
156+
l_name varchar2(4000 char);
157+
l_suites_by_path tt_schema_suites;
158+
begin
159+
l_suites_by_path := a_suites_by_path;
160+
--were iterating in reverse order of the index by path table
161+
-- so the first paths will be the leafs of hierarchy and next will their parents
162+
l_suite_path := l_suites_by_path.last;
163+
ut_utils.debug_log('Input suites to process = '||l_suites_by_path.count);
164+
165+
while l_suite_path is not null loop
166+
l_parent_path := substr( l_suite_path, 1, instr(l_suite_path,'.',-1)-1);
167+
ut_utils.debug_log('Processing l_suite_path = "'||l_suite_path||'", l_parent_path = "'||l_parent_path||'"');
168+
--no parent => I'm a root element
169+
if l_parent_path is null then
170+
ut_utils.debug_log(' suite "'||l_suite_path||'" is a root element - adding to return list.');
171+
l_result(l_suite_path) := l_suites_by_path(l_suite_path);
172+
-- not a root suite - need to add it to a parent suite
173+
else
174+
--parent does not exist and needs to be added
175+
if not l_suites_by_path.exists(l_parent_path) then
176+
l_name := substr( l_parent_path, instr(l_parent_path,'.',-1)+1);
177+
ut_utils.debug_log(' Parent suite "'||l_parent_path||'" not found in the list - Adding suite "'||l_name||'"');
178+
l_suites_by_path(l_parent_path) :=
179+
ut_logical_suite(
180+
a_object_owner => l_suites_by_path(l_suite_path).object_owner,
181+
a_object_name => l_name, a_name => l_name, a_path => l_parent_path
182+
);
183+
else
184+
ut_utils.debug_log(' Parent suite "'||l_parent_path||'" found in list of suites');
185+
end if;
186+
ut_utils.debug_log(' adding suite "'||l_suite_path||'" to "'||l_parent_path||'" items');
187+
l_suites_by_path(l_parent_path).add_item( l_suites_by_path(l_suite_path) );
188+
end if;
189+
l_suite_path := l_suites_by_path.prior(l_suite_path);
190+
end loop;
191+
ut_utils.debug_log(l_result.count||' root suites created.');
192+
return l_result;
193+
end;
194+
195+
function build_suites(a_annotated_objects sys_refcursor) return t_schema_suites_info is
196+
l_suite ut_logical_suite;
197+
l_annotated_objects ut_annotated_objects;
198+
l_all_suites tt_schema_suites;
199+
l_result t_schema_suites_info;
200+
begin
201+
fetch a_annotated_objects bulk collect into l_annotated_objects;
202+
close a_annotated_objects;
203+
204+
for i in 1 .. l_annotated_objects.count loop
205+
l_suite := create_suite(l_annotated_objects(i));
206+
if l_suite is not null then
207+
l_all_suites(l_suite.path) := l_suite;
208+
l_result.suite_paths(l_suite.object_name) := l_suite.path;
209+
end if;
210+
end loop;
211+
212+
--build hierarchical structure of the suite
213+
-- Restructure single-dimension list into hierarchy of suites by the value of %suitepath attribute value
214+
l_result.schema_suites := build_suites_hierarchy(l_all_suites);
215+
216+
return l_result;
217+
end;
218+
219+
function build_schema_suites(a_owner_name varchar2) return t_schema_suites_info is
220+
l_annotations_cursor sys_refcursor;
221+
begin
222+
-- form the single-dimension list of suites constructed from parsed packages
223+
open l_annotations_cursor for
224+
q'[select value(x)
225+
from table(
226+
]'||ut_utils.ut_owner||q'[.ut_annotation_manager.get_annotated_objects(:a_owner_name, 'PACKAGE')
227+
)x ]'
228+
using a_owner_name;
229+
230+
return build_suites(l_annotations_cursor);
231+
end;
232+
233+
end ut_suite_builder;
234+
/

source/core/ut_suite_builder.pks

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
create or replace package ut_suite_builder authid current_user 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+
* Responsible for converting annotations into unit test suites
21+
*/
22+
23+
type tt_schema_suites is table of ut_logical_suite index by varchar2(4000 char);
24+
type t_object_suite_path is table of varchar2(4000) index by varchar2(4000 char);
25+
26+
type t_schema_suites_info is record (
27+
schema_suites tt_schema_suites,
28+
suite_paths t_object_suite_path
29+
);
30+
31+
/**
32+
* Builds set of hierarchical suites for a given schema
33+
*
34+
* @param a_owner_name name of the schema to builds suites for
35+
* @return list of suites organized into hierarchy
36+
*
37+
*/
38+
function build_schema_suites(a_owner_name varchar2) return t_schema_suites_info;
39+
40+
/**
41+
* Builds set of hierarchical suites for given annotations
42+
*
43+
* @param a_annotated_objects cursor returning ut_annotated_object type
44+
* @return list of suites organized into hierarchy
45+
*
46+
*/
47+
function build_suites(a_annotated_objects sys_refcursor) return t_schema_suites_info;
48+
49+
end ut_suite_builder;
50+
/

0 commit comments

Comments
 (0)