diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 976630ae9..0cfd513f3 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -39,6 +39,16 @@ To get a full information about suite `TEST_STUFF` including suite description, select * from table(ut_runner.get_suites_info(USER, 'TEST_STUFF')) where item_type = 'UT_TEST'; ``` +To get a full information about suites that have a path like `ut3:tests.test_package_*` including suite description, all contexts and tests in a suite +```sql +select * from table(ut_runner.get_suites_info('ut3:tests.test_package_*') where item_type = 'UT_TEST'; +``` + +To get a full information about suites that have object name like `test_package_*` including suite description, all contexts and tests in a suite +```sql +select * from table(ut_runner.get_suites_info('test_package_*')); +``` + ## Checking if schema contains tests Function `ut_runner.has_suites(a_owner)` returns boolean value indicating if given schema contains test suites. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index e2f308c47..2288bf3f1 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -45,6 +45,9 @@ The **functions** can only be used in SELECT statements. They execute the specif ## ut.run procedures The examples below illustrate different ways and options to invoke `ut.run` procedures. +You can use a wildcard character `*` to call tests by part of their name or to call tests that are located on paths matched by part of path string. +Wildcard character can be placed anywhere on the path and can occur mutliple times. +Schema name cannot contain a wildcard character whether is in a suitepath call or call by object name. ```sql alter session set current_schema=hr; @@ -75,6 +78,23 @@ end; Executes all tests from all packages that are on the _com.my_org.my_project_ suitepath. Check the [annotations documentation](annotations.md) to find out about suitepaths and how they can be used to organize test packages for your project. +```sql +set serveroutput on +begin + ut.run('hr:com*'); +end; +``` + +Executes all tests in schema `hr` from all packages that are on suitepath starting with `com`. + +```sql +set serveroutput on +begin + ut.run('hr:co*.my_*.my_*'); +end; +``` + +Executes all tests in schema `hr` from all packages that starting with `my_` and all tests starting with `my_*` that are on suitepath starting with `co` . ```sql set serveroutput on @@ -124,6 +144,22 @@ Using a list of items to execute allows you to execute a fine-grained set of tes List can be passed as a comma separated list or a list of *ut_varchar2_list objects* or as a list within ut_varchar2_list. +```sql +set serveroutput on +begin + ut.run('hr.test*'); +end; +``` +Executes all tests in schema `hr` located in packages starting with name `test`. + +```sql +set serveroutput on +begin + ut.run('hr.test_apply_bonus.bonus_*'); +end; +``` +Executes test procedures with names starting with `bonus` in package `hr.test_apply_bonus` . + **Note:** diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index cbf1971e7..b69a51a04 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -172,12 +172,14 @@ create or replace package body ut_runner is ut_annotation_manager.purge_cache(a_object_owner, a_object_type); end; - function get_suites_info(a_owner varchar2 := null, a_package_name varchar2 := null) return ut_suite_items_info pipelined is + function get_suites_info(a_owner varchar2, a_package_name varchar2) return ut_suite_items_info pipelined is l_cursor sys_refcursor; l_results ut_suite_items_info; c_bulk_limit constant integer := 100; + l_path varchar2(4000) := nvl(a_owner,sys_context('userenv', 'current_schema'))||'.'||nvl(a_package_name,'*'); begin - l_cursor := ut_suite_manager.get_suites_info( nvl(a_owner,sys_context('userenv', 'current_schema')), a_package_name ); + + l_cursor := ut_suite_manager.get_suites_info(ut_varchar2_list(l_path)); loop fetch l_cursor bulk collect into l_results limit c_bulk_limit; for i in 1 .. l_results.count loop @@ -189,6 +191,26 @@ create or replace package body ut_runner is return; end; + function get_suites_info(a_path varchar2 := null) return ut_suite_items_info pipelined is + l_cursor sys_refcursor; + l_results ut_suite_items_info; + c_bulk_limit constant integer := 100; + i pls_integer; + begin + l_cursor := ut_suite_manager.get_suites_info(ut_varchar2_list(nvl(a_path,sys_context('userenv', 'current_schema')))); + loop + fetch l_cursor bulk collect into l_results limit c_bulk_limit; + i := l_results.first; + while (i is not null) loop + pipe row (l_results(i)); + i := l_results.next(i); + end loop; + exit when l_cursor%notfound; + end loop; + close l_cursor; + return; + end; + function is_test(a_owner varchar2, a_package_name varchar2, a_procedure_name varchar2) return boolean is l_result boolean := false; begin @@ -243,37 +265,6 @@ create or replace package body ut_runner is end loop; end; - function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2 is - l_start_pos pls_integer := 1; - l_end_pos pls_integer := 1; - l_result varchar2(4000); - l_item varchar2(4000); - l_at_end boolean := false; - begin - if a_random_seed is null then - l_result := a_path; - end if; - if a_path is not null then - loop - l_end_pos := instr(a_path,'.',l_start_pos); - if l_end_pos = 0 then - l_end_pos := length(a_path)+1; - l_at_end := true; - end if; - l_item := substr(a_path,l_start_pos,l_end_pos-l_start_pos); - if l_item is not null then - l_result := - l_result || - ut_utils.get_hash( to_char( dbms_utility.get_hash_value( l_item, 1, a_random_seed ) ) ); - end if; - exit when l_at_end; - l_result := l_result || chr(0); - l_start_pos := l_end_pos + 1; - end loop; - end if; - return l_result; - end; - procedure coverage_start(a_coverage_run_id raw) is begin ut_coverage.coverage_start(a_coverage_run_id); diff --git a/source/api/ut_runner.pks b/source/api/ut_runner.pks index 3170dedee..85eff1c93 100644 --- a/source/api/ut_runner.pks +++ b/source/api/ut_runner.pks @@ -104,7 +104,14 @@ create or replace package ut_runner authid current_user is * @param a_package_name name of unit test package to retrieve (optional), if NULL all unit test packages are returned * @return ut_suite_items_info table of objects */ - function get_suites_info(a_owner varchar2 := null, a_package_name varchar2 := null) return ut_suite_items_info pipelined; + function get_suites_info(a_owner varchar2, a_package_name varchar2) return ut_suite_items_info pipelined; + + /** + * Returns a pipelined collection containing information about unit test suites and the tests contained in them + * + * @param a_path a path from which we lookg for object or suite + */ + function get_suites_info(a_path varchar2 := null) return ut_suite_items_info pipelined; /** @@ -144,11 +151,6 @@ create or replace package ut_runner authid current_user is */ function get_reporters_list return tt_reporters_info pipelined; - /* - * Returns a hash value of suitepath based on input path and random seed - */ - function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2; - procedure coverage_start(a_coverage_run_id raw); procedure coverage_stop; diff --git a/source/core/types/ut_path_item.tpb b/source/core/types/ut_path_item.tpb new file mode 100644 index 000000000..6cdb2b8ad --- /dev/null +++ b/source/core/types/ut_path_item.tpb @@ -0,0 +1,42 @@ +create or replace type body ut_path_item as + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 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_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result is + begin + self.schema_name := schema_name; + self.object_name := object_name; + self.procedure_name := procedure_name; + return; + end; + + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2) return self as result is + begin + self.schema_name := schema_name; + self.suite_path := suite_path; + return; + end; + + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result is + begin + self.schema_name := schema_name; + self.object_name := object_name; + self.procedure_name := procedure_name; + self.suite_path := suite_path; + return; + end; +end; +/ diff --git a/source/core/types/ut_path_item.tps b/source/core/types/ut_path_item.tps new file mode 100644 index 000000000..c8ec81be5 --- /dev/null +++ b/source/core/types/ut_path_item.tps @@ -0,0 +1,26 @@ +create or replace type ut_path_item as object ( + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 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. + */ + schema_name varchar2(4000), + object_name varchar2(250), + procedure_name varchar2(250), + suite_path varchar2(4000), + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, suite_path varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result +) +/ diff --git a/source/core/types/ut_path_items.tps b/source/core/types/ut_path_items.tps new file mode 100644 index 000000000..0c87cf28c --- /dev/null +++ b/source/core/types/ut_path_items.tps @@ -0,0 +1,19 @@ +create or replace type ut_path_items as + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 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. + */ + table of ut_path_item +/ diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 1023a515b..d3e832a9b 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -19,26 +19,16 @@ create or replace package body ut_suite_cache_manager is /* * Private code */ - - gc_get_cache_suite_sql constant varchar2(32767) := - q'[with + cursor c_get_bulk_cache_suite(cp_suite_items in ut_suite_cache_rows) is + with suite_items as ( select /*+ cardinality(c 500) */ value(c) as obj - from ut_suite_cache c - where 1 = 1 - and c.object_owner = :l_object_owner - and ( {:path:} - and {:object_name:} - and {:procedure_name:} - ) - ) - ), - {:tags:} + from table(cp_suite_items) c), suitepaths as ( select distinct substr(c.obj.path,1,instr(c.obj.path,'.',-1)-1) as suitepath, c.obj.path as path, c.obj.object_owner as object_owner - from {:suite_item_name:} c + from suite_items c where c.obj.self_type = 'UT_SUITE' ), gen as ( @@ -73,15 +63,10 @@ create or replace package body ut_suite_cache_manager is s.y, null, s.z ) as obj from logical_suite_data s - ), - items as ( - select obj from {:suite_item_name:} - union all - select obj from logical_suites ) - select /*+ no_parallel */ c.obj - from items c - order by c.obj.object_owner,{:random_seed:}]'; + select /*+ no_parallel */ obj from suite_items + union all + select /*+ no_parallel */ obj from logical_suites; function get_missing_cache_objects(a_object_owner varchar2) return ut_varchar2_rows is l_result ut_varchar2_rows; @@ -102,158 +87,264 @@ create or replace package body ut_suite_cache_manager is return l_result; end; - - function get_path_sql(a_path in varchar2) return varchar2 is + function group_paths_by_schema(a_paths ut_varchar2_list) return ut_path_items is + c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_\*]+))?(\.([A-Za-z0-9$#_\*]+))?$'; + l_results ut_path_items := ut_path_items(); + l_path_item ut_path_item; + i pls_integer; begin - return case when a_path is not null then q'[ - :l_path||'.' like c.path || '.%' /*all parents and self*/ - or ( c.path||'.' like :l_path || '.%' /*all children and self*/ - ]' - else ' :l_path is null and ( :l_path is null ' end; + i := a_paths.first; + while (i is not null) loop + l_results.extend; + if a_paths(i) like '%:%' then + l_path_item := ut_path_item(schema_name => upper(regexp_substr(a_paths(i),'^[^.:]+')), + suite_path => ltrim(regexp_substr(a_paths(i),'[.:].*$'),':')); + l_results(l_results.last) := l_path_item; + else + l_path_item := ut_path_item(schema_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 1), + object_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3), + procedure_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5)); + l_results(l_results.last) := l_path_item; + end if; + i := a_paths.next(i); + end loop; + + return l_results; end; - - function get_object_name_sql(a_object_name in varchar2) return varchar2 is - begin - return case when a_object_name is not null - then ' c.object_name = :a_object_name ' - else ' :a_object_name is null' end; + + /* + First SQL queries for objects where procedure is null or its only wildcard. + We split that due to fact that we can use func min to combine rows. + + Second union is responsible expanding paths where the procedure filter is given + We cannot select min here as filter can cover only half of tests within + package. Even if the filter doesnt return anything we still capture a proc filter + name for error reporting later on. + + Third SQL cover scenario where a suitapath only is populated and wildcard is given + + Fourth SQL cover scenario where suitepath is populated with no filters + */ + function expand_paths(a_schema_paths ut_path_items) return ut_path_items is + l_schema_paths ut_path_items:= ut_path_items(); + begin + with + schema_paths as ( + select * from table(a_schema_paths) + ), + paths_for_object as ( + select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, + null as procedure_name + from schema_paths sp left outer join ut_suite_cache c + on ( c.object_owner = upper(sp.schema_name) + and c.object_name like replace(upper(sp.object_name),'*','%')) + where sp.suite_path is null and sp.object_name is not null + and ( sp.procedure_name is null or sp.procedure_name = '*') + group by sp.schema_name,nvl(c.object_name,sp.object_name) + ), + paths_for_procedures as ( + select /*+ no_parallel */ path as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, + nvl(c.name,sp.procedure_name) as procedure_name + from schema_paths sp left outer join ut_suite_cache c + on ( c.object_owner = upper(sp.schema_name) + and c.object_name like replace(upper(sp.object_name),'*','%') + and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name)) + where sp.suite_path is null and sp.object_name is not null + and (sp.procedure_name is not null and sp.procedure_name != '*') + ), + paths_for_suite_path_with_ast as ( + select /*+ no_parallel */ nvl(c.path,sp.suite_path) as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name + from schema_paths sp left outer join ut_suite_cache c on + ( c.object_owner = upper(sp.schema_name) + --and c.path like replace(sp.suite_path,'*','%')) + and regexp_like(c.path,'^'||replace(sp.suite_path,'*','[A-Za-z0-9$#_]*'))) + where sp.suite_path is not null and instr(sp.suite_path,'*') > 0 + ), + straigth_suite_paths as ( + select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name + from schema_paths sp + where + (sp.suite_path is not null and instr(sp.suite_path,'*') = 0) + or + (sp.suite_path is null and sp.object_name is null) + ), + all_suitepaths_together as ( + select * from paths_for_object + union all + select * from paths_for_procedures + union all + select * from paths_for_suite_path_with_ast + union all + select * from straigth_suite_paths + ) + select ut_path_item(schema_name,object_name,procedure_name,suite_path) + bulk collect into l_schema_paths + from + (select schema_name,object_name,procedure_name,suite_path, + row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) as r_num + from all_suitepaths_together) + where r_num = 1 ; + return l_schema_paths; end; - - function get_procedure_name_sql(a_procedure_name in varchar2) return varchar2 is + + /* + Get a suite items rows that matching our criteria like + path,object_name etc. + We need to consider also an wildcard character on our procedures and object + names. + Were the path is populated we need to make sure we dont return duplicates + as the wildcard can produce multiple results from same path and + parents and child for each can be same resulting in duplicates + */ + function get_suite_items ( + a_schema_paths ut_path_items + ) return ut_suite_cache_rows is + l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); begin - return case when a_procedure_name is not null - then ' c.name = :a_procedure_name' - else ' :a_procedure_name is null' end; + select obj bulk collect into l_suite_items + from ( + select /*+ cardinality(c 500) */ value(c) as obj,row_number() over ( partition by path,object_owner order by path,object_owner asc) as r_num + from ut_suite_cache c, + table(a_schema_paths) sp + where c.object_owner = upper(sp.schema_name) + and ((sp.suite_path is not null and sp.suite_path||'.' like c.path||'.%' /*all parents and self*/ + or + ( + c.path||'.' like sp.suite_path||'.%' /*all children and self*/ + and c.object_name like nvl(upper(sp.object_name),c.object_name) + and c.name like nvl(upper(sp.procedure_name),c.name) + )) + or + ( sp.suite_path is null + and c.object_name = nvl(upper(sp.object_name),c.object_name) + and c.name = nvl(upper(sp.procedure_name),c.name)))) where r_num =1; + return l_suite_items; end; - - function get_tags_sql(a_tags_count in integer) return varchar2 is + + /* + Having a base set of suites we will do a further filter down if there are + any tags defined. + */ + function get_tags_suites ( + a_suite_items ut_suite_cache_rows, + a_tags ut_varchar2_rows + ) return ut_suite_cache_rows is + l_suite_tags ut_suite_cache_rows := ut_suite_cache_rows(); + l_include_tags ut_varchar2_rows; + l_exclude_tags ut_varchar2_rows; begin - return case when a_tags_count > 0 then - q'[included_tags as ( - select c.obj.path as path - from suite_items c - where c.obj.tags multiset intersect :a_include_tag_list is not empty or :a_include_tag_list is empty + + select /*+ no_parallel */ column_value + bulk collect into l_include_tags + from table(a_tags) + where column_value not like '-%'; + + select /*+ no_parallel */ ltrim(column_value,'-') + bulk collect into l_exclude_tags + from table(a_tags) + where column_value like '-%'; + + with included_tags as ( + select c.path as path + from table(a_suite_items) c + where c.tags multiset intersect l_include_tags is not empty or l_include_tags is empty ), excluded_tags as ( - select c.obj.path as path - from suite_items c - where c.obj.tags multiset intersect :a_exclude_tag_list is not empty - ), - suite_items_tags as ( - select c.* - from suite_items c + select c.path as path + from table(a_suite_items) c + where c.tags multiset intersect l_exclude_tags is not empty + ) + select value(c) as obj + bulk collect into l_suite_tags + from table(a_suite_items) c where exists ( select 1 from included_tags t - where t.path||'.' like c.obj.path || '.%' /*all parents and self*/ - or c.obj.path||'.' like t.path || '.%' /*all children and self*/ + where t.path||'.' like c.path || '.%' /*all ancestors and self*/ + or c.path||'.' like t.path || '.%' /*all descendants and self*/ ) and not exists ( select 1 from excluded_tags t - where c.obj.path||'.' like t.path || '.%' /*all children and self*/ - ) - ),]' - else - q'[dummy as (select 'x' from dual where :a_include_tag_list is null and :a_include_tag_list is null and :a_exclude_tag_list is null),]' - end; + where c.path||'.' like t.path || '.%' /*all descendants and self*/ + ); + return l_suite_tags; end; - - function get_random_seed_sql(a_random_seed positive) return varchar2 is + + /* + We will sort a suites in hierarchical structure. + Sorting from bottom to top so when we consolidate + we will go in proper order. + For random seed we will add an extra sort that can be null. + The object owner is irrelevant on joing via path as we already + resolved a list of test we want to use so as long they share a suitepath + they are correct. + */ + procedure sort_and_randomize_tests( + a_suite_rows in out ut_suite_cache_rows, + a_random_seed positive := null) + is + l_suite_rows ut_suite_cache_rows; begin - return case - when a_random_seed is null then q'[ - nlssort( - replace( - /*suite path until objects name (excluding contexts and test path) with trailing dot (full stop)*/ - substr( c.obj.path, 1, instr( c.obj.path, lower(c.obj.object_name), -1 ) + length(c.obj.object_name) ), - '.', - /*'.' replaced with chr(0) to assure that child elements come before parent when sorting in descending order*/ - chr(0) - ), - 'nls_sort=binary' - )desc nulls last, - case when c.obj.self_type = 'UT_SUITE_CONTEXT' then - ( select /*+ no_parallel */ max( x.line_no ) + 1 - from ut_suite_cache x - where c.obj.object_owner = x.object_owner - and c.obj.object_name = x.object_name - and x.path like c.obj.path || '.%' - ) - else - c.obj.line_no - end, - /*assures that child contexts come before parent contexts*/ - regexp_count(c.obj.path,'\.') desc, - :a_random_seed]' - else - ' ut_runner.hash_suite_path( - c.obj.path, :a_random_seed - ) desc nulls last' - end; + with + extract_parent_child as ( + select s.path, substr(s.path,1,instr(s.path,'.',-1,1)-1) as parent_path,s.object_owner, + case when a_random_seed is null then s.line_no end line_no, + case when a_random_seed is not null then ut_utils.hash_suite_path(s.path, a_random_seed) end random_seed + from table(a_suite_rows) s), + t1(path,parent_path,object_owner,line_no,random_seed) as ( + --Anchor member + select s.path, parent_path,s.object_owner,s.line_no,random_seed + from extract_parent_child s + where parent_path is null + union all + --Recursive member + select t2.path, t2.parent_path,t2.object_owner,t2.line_no,t2.random_seed + from t1,extract_parent_child t2 + where t2.parent_path = t1.path + and t2.object_owner = t1.object_owner) + search depth first by line_no desc,random_seed desc nulls last set order1 + select value(i) as obj + bulk collect into l_suite_rows + from t1 c + join table(a_suite_rows) i on i.object_owner = c.object_owner and i.path = c.path + order by order1 desc; + + a_suite_rows := l_suite_rows; end; - - - + /* * Public code */ + + function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items is + begin + return expand_paths(group_paths_by_schema(a_paths)); + end; + function get_cached_suite_rows( - a_object_owner varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, + a_schema_paths ut_path_items, a_random_seed positive := null, a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows is - l_path varchar2(4000); l_results ut_suite_cache_rows := ut_suite_cache_rows(); - l_sql varchar2(32767); - l_suite_item_name varchar2(20); + l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); + l_schema_paths ut_path_items; l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); - l_include_tags ut_varchar2_rows; - l_exclude_tags ut_varchar2_rows; - l_object_owner varchar2(250) := ut_utils.qualified_sql_name(a_object_owner); - l_object_name varchar2(250) := ut_utils.qualified_sql_name(a_object_name); - l_procedure_name varchar2(250) := ut_utils.qualified_sql_name(a_procedure_name); - begin - - select /*+ no_parallel */ column_value - bulk collect into l_include_tags - from table(l_tags) - where column_value not like '-%'; - - select /*+ no_parallel */ ltrim(column_value,'-') - bulk collect into l_exclude_tags - from table(l_tags) - where column_value like '-%'; - - if a_path is null and a_object_name is not null then - select /*+ no_parallel */ min(c.path) - into l_path - from ut_suite_cache c - where c.object_owner = upper(l_object_owner) - and c.object_name = upper(l_object_name) - and c.name = nvl(upper(l_procedure_name), c.name); - else - l_path := lower(ut_utils.qualified_sql_name(a_path)); - end if; - l_suite_item_name := case when l_tags.count > 0 then 'suite_items_tags' else 'suite_items' end; - - l_sql := gc_get_cache_suite_sql; - l_sql := replace(l_sql,'{:suite_item_name:}',l_suite_item_name); - l_sql := replace(l_sql,'{:object_owner:}',upper(l_object_owner)); - l_sql := replace(l_sql,'{:path:}',get_path_sql(l_path)); - l_sql := replace(l_sql,'{:object_name:}',get_object_name_sql(l_object_name)); - l_sql := replace(l_sql,'{:procedure_name:}',get_procedure_name_sql(l_procedure_name)); - l_sql := replace(l_sql,'{:tags:}',get_tags_sql(l_tags.count)); - l_sql := replace(l_sql,'{:random_seed:}',get_random_seed_sql(a_random_seed)); - - ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); + begin - execute immediate l_sql - bulk collect into l_results - using upper(l_object_owner), l_path, l_path, upper(a_object_name), upper(a_procedure_name), l_include_tags, l_include_tags, l_exclude_tags, a_random_seed; + l_schema_paths := a_schema_paths; + l_suite_items := get_suite_items(a_schema_paths); + if l_tags.count > 0 then + l_suite_items := get_tags_suites(l_suite_items,l_tags); + end if; + + open c_get_bulk_cache_suite(l_suite_items); + fetch c_get_bulk_cache_suite bulk collect into l_results; + close c_get_bulk_cache_suite; + return l_results; end; + + function get_schema_parse_time(a_schema_name varchar2) return timestamp result_cache is l_cache_parse_time timestamp; @@ -398,22 +489,25 @@ create or replace package body ut_suite_cache_manager is end; function get_cached_suite_info( - a_object_owner varchar2, - a_object_name varchar2 + a_schema_paths ut_path_items + ) return ut_suite_cache_rows is + begin + return get_cached_suite_rows( a_schema_paths ); + end; + + function get_suite_items_info( + a_suite_cache_items ut_suite_cache_rows ) return ut_suite_items_info is - l_cache_rows ut_suite_cache_rows; l_results ut_suite_items_info; begin - l_cache_rows := get_cached_suite_rows( a_object_owner => a_object_owner, a_object_name =>a_object_name ); select /*+ no_parallel */ ut_suite_item_info( c.object_owner, c.object_name, c.name, c.description, c.self_type, c.line_no, c.path, c.disabled_flag, c.disabled_reason, c.tags ) bulk collect into l_results - from table(l_cache_rows) c; - - return l_results; + from table(a_suite_cache_items) c; + return l_results; end; function get_cached_packages( diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 0a38851fe..974babca5 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -40,30 +40,41 @@ create or replace package ut_suite_cache_manager authid definer is */ procedure remove_missing_objs_from_cache(a_schema_name varchar2); + /* + * We will sort a suites in hierarchical structure. + * Sorting from bottom to top so when we consolidate + * we will go in proper order. + */ + procedure sort_and_randomize_tests( + a_suite_rows in out ut_suite_cache_rows, + a_random_seed positive := null); + /* * Retrieves suite items data from cache. * Returned data is not filtered by user access rights. * Not to be used publicly. Used internally for building suites at runtime. */ function get_cached_suite_rows( - a_object_owner varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, + a_schema_paths ut_path_items, a_random_seed positive := null, a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows; - + + function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items; + /* * Retrieves suite item info rows from cache. * Returned data is not filtered by user access rights. * Not to be used publicly. Used internally for building suites info. */ function get_cached_suite_info( - a_object_owner varchar2, - a_object_name varchar2 + a_schema_paths ut_path_items + ) return ut_suite_cache_rows; + + function get_suite_items_info( + a_suite_cache_items ut_suite_cache_rows ) return ut_suite_items_info; - + /* * Retrieves list of cached suite packages. * Returned data is not filtered by user access rights. diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index a11b0249c..805fd608b 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -17,19 +17,9 @@ create or replace package body ut_suite_manager is */ gc_suitpath_error_message constant varchar2(100) := 'Suitepath exceeds 1000 CHAR on: '; - - type t_path_item is record ( - object_name varchar2(250), - procedure_name varchar2(250), - suite_path varchar2(4000) - ); - type t_path_items is table of t_path_item; - type t_schema_paths is table of t_path_items index by varchar2(250 char); - cursor c_cached_suites_cursor is select * from table(ut_suite_cache_rows()); type tt_cached_suites is table of c_cached_suites_cursor%rowtype; type t_cached_suites_cursor is ref cursor return c_cached_suites_cursor%rowtype; - type t_item_levels is table of ut_suite_items index by binary_integer; ------------------ @@ -41,7 +31,8 @@ create or replace package body ut_suite_manager is else for i in 1 .. a_paths.count loop l_path := a_paths(i); - if l_path is null or not (regexp_like(l_path, '^[A-Za-z0-9$#_]+(\.[A-Za-z0-9$#_]+){0,2}$') or regexp_like(l_path, '^([A-Za-z0-9$#_]+)?:[A-Za-z0-9$#_]+(\.[A-Za-z0-9$#_]+)*$')) then + if l_path is null or not ( + regexp_like(l_path, '^[A-Za-z0-9$#_\*]+(\.[A-Za-z0-9$#_\*]+){0,2}$') or regexp_like(l_path, '^([A-Za-z0-9$#_]+)?:[A-Za-z0-9$#_\*]+(\.[A-Za-z0-9$#_\*]+)*$')) then raise_application_error(ut_utils.gc_invalid_path_format, 'Invalid path format: ' || nvl(l_path, 'NULL')); end if; end loop; @@ -84,12 +75,14 @@ create or replace package body ut_suite_manager is -- get schema name / object.[procedure] name -- When path is one of: schema or schema.package[.object] or package[.object] -- transform it back to schema[.package[.object]] + -- Object name or procedure is allowed to have filter char + -- However this is not allowed on schema begin - l_object := regexp_substr(a_paths(i), '^[A-Za-z0-9$#_]+'); + l_object := regexp_substr(a_paths(i), '^[A-Za-z0-9$#_\*]+'); l_schema := sys.dbms_assert.schema_name(upper(l_object)); exception when sys.dbms_assert.invalid_schema_name then - if ut_metadata.package_exists_in_cur_schema(upper(l_object)) then + if l_object like '%*%' or ut_metadata.package_exists_in_cur_schema(upper(l_object)) then a_paths(i) := c_current_schema || '.' || a_paths(i); l_schema := c_current_schema; else @@ -110,34 +103,6 @@ create or replace package body ut_suite_manager is l_schema_names := resolve_schema_names(a_paths); end; - function group_paths_by_schema(a_paths ut_varchar2_list) return t_schema_paths is - c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_]+))?(\.([A-Za-z0-9$#_]+))?$'; - l_schema varchar2(4000); - l_empty_result t_path_item; - l_result t_path_item; - l_results t_schema_paths; - begin - for i in 1 .. a_paths.count loop - l_result := l_empty_result; - if a_paths(i) like '%:%' then - l_schema := upper(regexp_substr(a_paths(i),'^[^.:]+')); - l_result.suite_path := ltrim(regexp_substr(a_paths(i),'[.:].*$'),':'); - else - l_schema := regexp_substr(a_paths(i), c_package_path_regex, subexpression => 1); - l_result.object_name := regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3); - l_result.procedure_name := regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5); - end if; - if l_results.exists(l_schema) then - l_results(l_schema).extend; - l_results(l_schema)(l_results(l_schema).last) := l_result; - else - l_results(l_schema) := t_path_items(l_result); - end if; - end loop; - return l_results; - end; - - function sort_by_seq_no( a_list ut_executables ) return ut_executables is @@ -331,42 +296,82 @@ create or replace package body ut_suite_manager is close a_suite_data_cursor; end reconstruct_from_cache; + function get_filtered_cursor( + a_unfiltered_rows in ut_suite_cache_rows, + a_skip_all_objects boolean := false + ) + return ut_suite_cache_rows is + l_result ut_suite_cache_rows := ut_suite_cache_rows(); + begin + if ut_metadata.user_has_execute_any_proc() or a_skip_all_objects then + l_result := a_unfiltered_rows; + else + select obj bulk collect into l_result + from ( + select /*+ no_parallel */ value(c) as obj from table(a_unfiltered_rows) c + where sys_context( 'userenv', 'current_user' ) = upper(c.object_owner) + union all + select /*+ no_parallel */ value(c) as obj from table(a_unfiltered_rows) c + where sys_context( 'userenv', 'current_user' ) != upper(c.object_owner) + and ( exists + ( select 1 + from all_objects a + where a.object_name = c.object_name + and a.owner = c.object_owner + and a.object_type = 'PACKAGE' + ) + or c.self_type = 'UT_LOGICAL_SUITE')); + end if; + return l_result; + end; + + procedure reconcile_paths_and_suites( + a_schema_paths ut_path_items, + a_filtered_rows ut_suite_cache_rows + ) is + begin + for i in ( select /*+ no_parallel */ sp.schema_name,sp.object_name,sp.procedure_name, + sp.suite_path,sc.path + from table(a_schema_paths) sp left outer join + table(a_filtered_rows) sc on + (( upper(sp.schema_name) = upper(sc.object_owner) and upper(sp.object_name) = upper(sc.object_name) + and nvl(upper(sp.procedure_name),sc.name) = sc.name ) + or (sc.path = sp.suite_path)) + where sc.path is null) + loop + if i.suite_path is not null then + raise_application_error(ut_utils.gc_suite_package_not_found,'No suite packages found for path '||i.schema_name||':'||i.suite_path|| '.'); + elsif i.procedure_name is not null then + raise_application_error(ut_utils.gc_suite_package_not_found,'Suite test '||i.schema_name||'.'||i.object_name|| '.'||i.procedure_name||' does not exist'); + elsif i.object_name is not null then + raise_application_error(ut_utils.gc_suite_package_not_found,'Suite package '||i.schema_name||'.'||i.object_name|| ' does not exist'); + end if; + end loop; + end; + function get_cached_suite_data( - a_object_owner varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, - a_skip_all_objects boolean := false, + a_schema_paths ut_path_items, a_random_seed positive, - a_tags ut_varchar2_rows := null + a_tags ut_varchar2_rows := null, + a_skip_all_objects boolean := false ) return t_cached_suites_cursor is l_unfiltered_rows ut_suite_cache_rows; + l_filtered_rows ut_suite_cache_rows; l_result t_cached_suites_cursor; begin l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( - a_object_owner, - a_path, - a_object_name, - a_procedure_name, + a_schema_paths, a_random_seed, a_tags ); - if a_skip_all_objects then - open l_result for - select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c; - else - open l_result for - select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c - where exists - ( select 1 - from all_objects a - where a.object_name = c.object_name - and a.owner = c.object_owner - and a.object_type = 'PACKAGE' - ) - or c.self_type = 'UT_LOGICAL_SUITE'; - end if; + l_filtered_rows := get_filtered_cursor(l_unfiltered_rows,a_skip_all_objects); + reconcile_paths_and_suites(a_schema_paths,l_filtered_rows); + + ut_suite_cache_manager.sort_and_randomize_tests(l_filtered_rows,a_random_seed); + + open l_result for + select * from table(l_filtered_rows); return l_result; end; @@ -442,31 +447,21 @@ create or replace package body ut_suite_manager is ut_event_manager.trigger_event('refresh_cache - end'); end; - procedure add_suites_for_path( - a_owner_name varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, + procedure add_suites_for_paths( + a_schema_paths ut_path_items, a_suites in out nocopy ut_suite_items, a_random_seed positive, a_tags ut_varchar2_rows := null ) is begin - refresh_cache(a_owner_name); - reconstruct_from_cache( a_suites, get_cached_suite_data( - a_owner_name, - a_path, - a_object_name, - a_procedure_name, - can_skip_all_objects_scan(a_owner_name), + a_schema_paths, a_random_seed, a_tags ) ); - end; ----------------------------------------------- @@ -482,19 +477,17 @@ create or replace package body ut_suite_manager is a_skip_all_objects boolean := false ) return ut_suite_items is l_suites ut_suite_items := ut_suite_items(); + l_schema_paths ut_path_items; begin build_and_cache_suites(a_owner_name, a_annotated_objects); - + l_schema_paths := ut_path_items(ut_path_item(a_owner_name,a_object_name,a_procedure_name,a_path)); reconstruct_from_cache( l_suites, get_cached_suite_data( - a_owner_name, - a_path, - a_object_name, - a_procedure_name, - a_skip_all_objects, + l_schema_paths, null, - null + null, + a_skip_all_objects ) ); return l_suites; @@ -530,49 +523,32 @@ create or replace package body ut_suite_manager is a_tags ut_varchar2_rows := ut_varchar2_rows() ) is l_paths ut_varchar2_list := a_paths; - l_path_items t_path_items; - l_path_item t_path_item; + l_schema_names ut_varchar2_rows; + l_schema_paths ut_path_items; l_schema varchar2(4000); - l_suites_count pls_integer := 0; - l_index varchar2(4000 char); - l_schema_paths t_schema_paths; begin ut_event_manager.trigger_event('configure_execution_by_path - start'); a_suites := ut_suite_items(); --resolve schema names from paths and group paths by schema name - resolve_schema_names(l_paths); - - l_schema_paths := group_paths_by_schema(l_paths); + l_schema_names := resolve_schema_names(l_paths); - l_schema := l_schema_paths.first; + --refresh cache + l_schema := l_schema_names.first; while l_schema is not null loop - l_path_items := l_schema_paths(l_schema); - for i in 1 .. l_path_items.count loop - l_path_item := l_path_items(i); - add_suites_for_path( - upper(l_schema), - l_path_item.suite_path, - l_path_item.object_name, - l_path_item.procedure_name, - a_suites, - a_random_seed, - a_tags - ); - if a_suites.count = l_suites_count then - if l_path_item.suite_path is not null then - raise_application_error(ut_utils.gc_suite_package_not_found,'No suite packages found for path '||l_schema||':'||l_path_item.suite_path|| '.'); - elsif l_path_item.procedure_name is not null then - raise_application_error(ut_utils.gc_suite_package_not_found,'Suite test '||l_schema||'.'||l_path_item.object_name|| '.'||l_path_item.procedure_name||' does not exist'); - elsif l_path_item.object_name is not null then - raise_application_error(ut_utils.gc_suite_package_not_found,'Suite package '||l_schema||'.'||l_path_item.object_name|| ' does not exist'); - end if; - end if; - l_index := a_suites.first; - l_suites_count := a_suites.count; - end loop; - l_schema := l_schema_paths.next(l_schema); + refresh_cache(upper(l_schema_names(l_schema))); + l_schema := l_schema_names.next(l_schema); end loop; + l_schema_paths := ut_suite_cache_manager.get_schema_paths(l_paths); + + --We will get a single list of paths rather than loop by loop. + add_suites_for_paths( + l_schema_paths, + a_suites, + a_random_seed, + a_tags + ); + --propagate rollback type to suite items after organizing suites into hierarchy for i in 1 .. a_suites.count loop a_suites(i).set_rollback_type( a_suites(i).get_rollback_type() ); @@ -582,37 +558,34 @@ create or replace package body ut_suite_manager is end configure_execution_by_path; function get_suites_info( - a_owner_name varchar2, - a_package_name varchar2 := null + a_paths ut_varchar2_list ) return sys_refcursor is - l_result sys_refcursor; - l_all_suite_info ut_suite_items_info; - l_owner_name varchar2(250) := ut_utils.qualified_sql_name(a_owner_name); - l_package_name varchar2(250) := ut_utils.qualified_sql_name(a_package_name); - begin + l_result sys_refcursor; + l_all_suite_info ut_suite_items_info; + l_schema_names ut_varchar2_rows; + l_schema_paths ut_path_items; + l_paths ut_varchar2_list := a_paths; + l_schema varchar2(4000); + l_unfiltered_rows ut_suite_cache_rows; + l_filtered_rows ut_suite_cache_rows; - refresh_cache(l_owner_name); + begin + l_schema_names := resolve_schema_names(l_paths); + --refresh cache + l_schema := l_schema_names.first; + while l_schema is not null loop + refresh_cache(upper(l_schema_names(l_schema))); + l_schema := l_schema_names.next(l_schema); + end loop; + l_schema_paths := ut_suite_cache_manager.get_schema_paths(l_paths); + l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_info(l_schema_paths); + l_filtered_rows := get_filtered_cursor(l_unfiltered_rows); + l_all_suite_info := ut_suite_cache_manager.get_suite_items_info(l_filtered_rows); + open l_result for + select /*+ no_parallel */ value(c) + from table(l_all_suite_info) c + order by c.object_owner, c.object_name, c.item_line_no; - l_all_suite_info := ut_suite_cache_manager.get_cached_suite_info( l_owner_name, l_package_name ); - if can_skip_all_objects_scan( l_owner_name ) then - open l_result for - select /*+ no_parallel */ value(c) - from table(l_all_suite_info) c - order by c.object_owner, c.object_name, c.item_line_no; - else - open l_result for - select /*+ no_parallel */ value(c) - from table(l_all_suite_info) c - where exists - ( select 1 - from all_objects a - where a.object_name = c.object_name - and a.owner = c.object_owner - and a.object_type = 'PACKAGE' - ) - or c.item_type = 'UT_LOGICAL_SUITE' - order by c.object_owner, c.object_name, c.item_line_no; - end if; return l_result; end; diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index 5ae98d72a..170b83f05 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -39,6 +39,7 @@ create or replace package ut_suite_manager authid current_user is * @return array containing root suites-ready to be executed * */ + --TODO:Zerknij czy mozna wywalic function configure_execution_by_path(a_paths ut_varchar2_list, a_random_seed positive := null) return ut_suite_items; /** @@ -79,15 +80,11 @@ create or replace package ut_suite_manager authid current_user is /** * Returns a ref cursor containing information about unit test suites and the tests contained in them * - * @param a_owner owner of unit tests to retrieve - * @param a_package_name name of test package (optional) - * @param a_procedure_name name of test procedure (optional) - * @return ut_suite_items_info table of objects + * @param a_paths list of paths to be resolved and return a suites. */ function get_suites_info( - a_owner_name varchar2, - a_package_name varchar2 := null - ) return sys_refcursor; + a_paths ut_varchar2_list + ) return sys_refcursor; /** * Returns true if given suite item exists diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 3675e834d..162e50f8f 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -892,6 +892,37 @@ create or replace package body ut_utils is return case when a_data is null then null else dbms_crypto.hash(a_data, a_hash_type) end; end; + function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2 is + l_start_pos pls_integer := 1; + l_end_pos pls_integer := 1; + l_result varchar2(4000); + l_item varchar2(4000); + l_at_end boolean := false; + begin + if a_random_seed is null then + l_result := a_path; + end if; + if a_path is not null then + loop + l_end_pos := instr(a_path,'.',l_start_pos); + if l_end_pos = 0 then + l_end_pos := length(a_path)+1; + l_at_end := true; + end if; + l_item := substr(a_path,l_start_pos,l_end_pos-l_start_pos); + if l_item is not null then + l_result := + l_result || + ut_utils.get_hash( to_char( dbms_utility.get_hash_value( l_item, 1, a_random_seed ) ) ); + end if; + exit when l_at_end; + l_result := l_result || chr(0); + l_start_pos := l_end_pos + 1; + end loop; + end if; + return l_result; + end; + function qualified_sql_name(a_name varchar2) return varchar2 is begin return diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 3635bccad..995d83c10 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -452,6 +452,11 @@ create or replace package ut_utils authid definer is */ function get_hash(a_data clob, a_hash_type binary_integer := dbms_crypto.hash_sh1) return t_hash; + /* + * Returns a hash value of suitepath based on input path and random seed + */ + function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2; + /* * Verifies that the input string is a qualified SQL name using sys.dbms_assert.qualified_sql_name * If null value passed returns null diff --git a/source/create_grants.sql b/source/create_grants.sql index 6401b1522..8a44ab371 100644 --- a/source/create_grants.sql +++ b/source/create_grants.sql @@ -60,6 +60,7 @@ grant execute on &&ut3_owner..ut_file_mapping to &ut3_user; grant execute on &&ut3_owner..ut_file_mapper to &ut3_user; grant execute on &&ut3_owner..ut_suite_items_info to &ut3_user; grant execute on &&ut3_owner..ut_suite_item_info to &ut3_user; +grant execute on &&ut3_owner..ut_suite_cache_rows to &ut3_user; grant execute on &&ut3_owner..ut_run_info to &ut3_user; grant execute on &&ut3_owner..ut_coverage_options to &ut3_user; diff --git a/source/install.sql b/source/install.sql index cda057bdf..6f3c16801 100644 --- a/source/install.sql +++ b/source/install.sql @@ -89,7 +89,8 @@ create or replace context &&ut3_owner._info using &&ut3_owner..ut_session_contex @@install_component.sql 'core/types/ut_run.tps' @@install_component.sql 'core/types/ut_reporter_base.tps' @@install_component.sql 'core/types/ut_reporters.tps' - +@@install_component.sql 'core/types/ut_path_item.tps' +@@install_component.sql 'core/types/ut_path_items.tps' @@install_component.sql 'expectations/json_objects_specs.sql' @@install_component.sql 'expectations/matchers/ut_matcher_options_items.tps' @@ -207,6 +208,7 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@install_component.sql 'core/types/ut_executable_test.tpb' @@install_component.sql 'core/types/ut_console_reporter_base.tps' @@install_component.sql 'core/types/ut_console_reporter_base.tpb' +@@install_component.sql 'core/types/ut_path_item.tpb' --expectations and matchers @@install_component.sql 'expectations/data_values/ut_compound_data_tmp.sql' diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index 4d77d9993..ab4069497 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -88,6 +88,10 @@ drop type ut_suite_items_info force; drop type ut_suite_item_info force; +drop type ut_path_items force; + +drop type ut_path_item force; + drop package ut_suite_manager; drop package ut_suite_builder; diff --git a/test/ut3_tester/core/test_suite_manager.pkb b/test/ut3_tester/core/test_suite_manager.pkb index c8b4a9453..fbac0f3f5 100644 --- a/test/ut3_tester/core/test_suite_manager.pkb +++ b/test/ut3_tester/core/test_suite_manager.pkb @@ -278,8 +278,167 @@ end test_package_with_ctx;]'; end; end test_package_with_ctx;]'; + + execute immediate q'[create or replace package test1_frontwildcard is + + --%suite + --%displayname(test1_frontwildcard) + --%suitepath(front_wildcard) + --%rollback(manual) + + --%test + --%displayname(Test1 from test test1_frontwildcard) + procedure first_test; + + --%test + --%displayname(Test2 from test test1_frontwildcard) + procedure second_test; + +end test1_frontwildcard;]'; + + execute immediate q'[create or replace package body test1_frontwildcard is + + procedure first_test is + begin + ut.expect(1).to_equal(1); + end; + + procedure second_test is + begin + ut.expect(1).to_equal(2); + end; + +end test1_frontwildcard;]'; + + execute immediate q'[create or replace package test2_frontwildcard is + + --%suite + --%displayname(test2_frontwildcard) + --%suitepath(front_wildcard) + --%rollback(manual) + + --%test + --%displayname(Test1 from test package test2_frontwildcard) + procedure first_test; + +end test2_frontwildcard;]'; + + execute immediate q'[create or replace package body test2_frontwildcard is + + procedure first_test is + begin + ut.expect(1).to_equal(1); + end; + +end test2_frontwildcard;]'; + + execute immediate q'[create or replace package middle_test1_wildcard is + + --%suite + --%displayname(middle_test1_wildcard) + --%suitepath(wild_middle_card) + --%rollback(manual) + + --%test + --%displayname(Test1 from test middle_test1_wildcard) + procedure middle_first_test; + + --%test + --%displayname(Test2 from test middle_test1_wildcard) + procedure middle_second_test; + +end middle_test1_wildcard;]'; + + execute immediate q'[create or replace package body middle_test1_wildcard is + + procedure middle_first_test is + begin + ut.expect(1).to_equal(1); + end; + + procedure middle_second_test is + begin + ut.expect(1).to_equal(2); + end; + +end middle_test1_wildcard;]'; + + execute immediate q'[create or replace package middle_test2_wildcard is + + --%suite + --%displayname(middle_test2_wildcard) + --%suitepath(wild_middle_card) + --%rollback(manual) + + --%test + --%displayname(Test1 from test package middle_test2_wildcard) + procedure middle_first_test; + +end middle_test2_wildcard;]'; + + execute immediate q'[create or replace package body middle_test2_wildcard is + + procedure middle_first_test is + begin + ut.expect(1).to_equal(1); + end; + +end middle_test2_wildcard;]'; + + execute immediate q'[create or replace package test1_multi_wildcard is + + --%suite + --%displayname(test1_multi_wildcard) + --%suitepath(wildcard_multi_asterisks) + --%rollback(manual) + + --%test + --%displayname(Test1 from test test1_multi_wildcard) + procedure first_multi_test1; + + --%test + --%displayname(Test2 from test test1_multi_wildcard) + procedure second_multi_test2; + +end test1_multi_wildcard;]'; + + execute immediate q'[create or replace package body test1_multi_wildcard is + + procedure first_multi_test1 is + begin + ut.expect(1).to_equal(1); end; + procedure second_multi_test2 is + begin + ut.expect(1).to_equal(2); + end; + +end test1_multi_wildcard;]'; + + execute immediate q'[create or replace package test2_multi_wildcard is + + --%suite + --%displayname(test2_multi_wildcard) + --%suitepath(wildcard_multi_asterisks) + --%rollback(manual) + + --%test + --%displayname(Test1 from test package test2_multi_wildcard) + procedure first_multi_test1; + +end test2_multi_wildcard;]'; + + execute immediate q'[create or replace package body test2_multi_wildcard is + + procedure first_multi_test1 is + begin + ut.expect(1).to_equal(1); + end; + +end test2_multi_wildcard;]'; + + end; procedure drop_dummy_packages is pragma autonomous_transaction; @@ -288,6 +447,12 @@ end test_package_with_ctx;]'; execute immediate 'drop package test_package_2'; execute immediate 'drop package test_package_3'; execute immediate 'drop package test_package_with_ctx'; + execute immediate 'drop package test1_frontwildcard'; + execute immediate 'drop package test2_frontwildcard'; + execute immediate 'drop package middle_test1_wildcard'; + execute immediate 'drop package middle_test2_wildcard'; + execute immediate 'drop package test1_multi_wildcard'; + execute immediate 'drop package test2_multi_wildcard'; end; procedure test_schema_run is @@ -945,6 +1110,36 @@ end;]'; ut.expect(sqlerrm).to_be_like('%failing_non_existing%'); end; + procedure test_search_nonex_pck_wild is + l_objects_to_run ut3_develop.ut_suite_items; + begin + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_develop.failing_non_*')); + ut.fail('Non existing package did not raise exception'); + exception + when others then + ut.expect(sqlerrm).to_be_like('%failing_non_*%'); + end; + + procedure test_search_nonex_prc_wild is + l_objects_to_run ut3_develop.ut_suite_items; + begin + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_tester.test_package_1.nonexist*')); + ut.fail('Non existing package did not raise exception'); + exception + when others then + ut.expect(sqlerrm).to_be_like('%nonexist*%'); + end; + + procedure test_search_nonex_path_wild is + l_objects_to_run ut3_develop.ut_suite_items; + begin + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_develop:failing_non_*')); + ut.fail('Non existing path did not raise exception'); + exception + when others then + ut.expect(sqlerrm).to_be_like('%:failing_non_*%'); + end; + procedure test_search_nonexist_sch_pck is l_objects_to_run ut3_develop.ut_suite_items; begin @@ -1560,5 +1755,467 @@ end;]'; end; + procedure test_wild_card_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test_package_*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test2_suite ut3_develop.ut_logical_suite; + l_ctx_suite ut3_develop.ut_logical_suite; + l_test_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(3); + + + for i in 1 .. 3 loop + l_test_suite := treat(l_objects_to_run(i) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name in ('test_package_with_ctx','tests', 'tests2')).to_be_true; + + case l_test_suite.name + when 'test_package_with_ctx' then + ut.expect(l_test_suite.items.count).to_equal(1); + l_ctx_suite:= treat(l_test_suite.items(1) as ut3_develop.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_develop.ut_test); + ut.expect(l_test_proc.name).to_equal('test1'); + when 'tests' then + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_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.rollback_type).to_equal(ut3_develop.ut_utils.gc_rollback_manual); + l_test2_suite := treat(l_test1_suite.items(1) as ut3_develop.ut_logical_suite); + + ut.expect(l_test2_suite.name).to_equal('test_package_2'); + ut.expect(l_test2_suite.items.count).to_equal(3); + ut.expect(l_test2_suite.rollback_type).to_equal(ut3_develop.ut_utils.gc_rollback_manual); + when 'tests2' then + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_3'); + ut.expect(l_test1_suite.items.count).to_equal(3); + end case; + + end loop; + + end; + + procedure test_wild_card_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test_package_1.test*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('tests'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_1'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('test1'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('test2'); + end; + + procedure test_wild_card_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':tests*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test2_suite ut3_develop.ut_logical_suite; + l_ctx_suite ut3_develop.ut_logical_suite; + l_test_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(2); + + + for i in 1 .. 2 loop + l_test_suite := treat(l_objects_to_run(i) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name in ('tests', 'tests2')).to_be_true; + + case l_test_suite.name + when 'tests' then + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_1'); + ut.expect(l_test1_suite.items.count).to_equal(3); + + for i in 1 ..3 loop + case l_test1_suite.items(i).self_type + when 'UT_SUITE' then + l_test2_suite := treat(l_test1_suite.items(i) as ut3_develop.ut_logical_suite); + ut.expect(l_test2_suite.name).to_equal('test_package_2'); + ut.expect(l_test2_suite.items.count).to_equal(3); + + l_test_proc := treat(l_test2_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','context_test')).to_be_true; + + l_test_proc := treat(l_test2_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','context_test')).to_be_true; + + l_test_proc := treat(l_test2_suite.items(3) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','context_test')).to_be_true; + + when 'UT_TEST' then + l_test_proc := treat(l_test1_suite.items(i) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2')).to_be_true; + end case; + end loop; + when 'tests2' then + ut.expect(l_test_suite.items.count).to_equal(1); + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_3'); + ut.expect(l_test1_suite.items.count).to_equal(3); + for i in 1 .. 3 loop + l_test_proc := treat(l_test1_suite.items(i) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','disabled_test')).to_be_true; + end loop; + end case; + + end loop; + + end; + + procedure test_wild_card_front_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.*_frontwildcard'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('front_wildcard'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_test'); + when 'test2_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_front_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test1_frontwildcard.*_test'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('front_wildcard'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test1_frontwildcard'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_test'); + end; + + procedure test_wild_card_front_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':*_wildcard'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('front_wildcard'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_test'); + when 'test2_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_mid_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.middle_*_wildcard'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wild_middle_card'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'middle_test1_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('middle_second_test'); + when 'middle_test2_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_mid_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.middle_test1_wildcard.middle_*_test'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wild_middle_card'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('middle_test1_wildcard'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('middle_second_test'); + end; + + procedure test_wild_card_mid_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':wild_*card'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wild_middle_card'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'middle_test1_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('middle_second_test'); + when 'middle_test2_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_mul_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.*_multi_*card'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_multi_test2'); + when 'test2_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + end case; + + end loop; + end; + + procedure test_wild_card_mul_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test1_multi_wildcard.*_multi_*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test1_multi_wildcard'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_multi_test2'); + end; + + procedure test_wild_card_mul_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':wild*_multi_*risks'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_multi_test2'); + when 'test2_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + end case; + + end loop; + end; + + procedure tst_wild_card_mul_lv_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':wild*_multi_*risks.*_multi_wildcard.*_multi_test1'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.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_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + when 'test2_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + end case; + + end loop; + end; + end test_suite_manager; / diff --git a/test/ut3_tester/core/test_suite_manager.pks b/test/ut3_tester/core/test_suite_manager.pks index 154df9ca6..d9d4efc09 100644 --- a/test/ut3_tester/core/test_suite_manager.pks +++ b/test/ut3_tester/core/test_suite_manager.pks @@ -75,8 +75,17 @@ create or replace package test_suite_manager is --%test(Prepare runner for nonexisting package with schema) procedure test_search_nonexisting_pck; - - --%test(Prepare runner for nonexisting package without schema) + + --%test(Prepare runner for nonexisting package using wildcard filter) + procedure test_search_nonex_pck_wild; + + --%test(Prepare runner for nonexisting procedure using wildcard filter) + procedure test_search_nonex_prc_wild; + + --%test(Prepare runner for nonexisting path using wildcard filter) + procedure test_search_nonex_path_wild; + + --%test(Prepare runner for nonexisting package without schema) procedure test_search_nonexist_sch_pck; --%test(Test description with comma) @@ -185,6 +194,48 @@ create or replace package test_suite_manager is --%aftertest(clean_remove_annot_test) procedure test_rem_cache_on_crt_anno; + --%context(wildcard_filters) + + --%test(Execute test_packages using a object_name with wildcard at the end ) + procedure test_wild_card_obj_name; + + --%test(Execute test_packages using a procedure name with wildcard at the end) + procedure test_wild_card_prc_name; + + --%test(Execute test_packages using a path name with wildcard at the end) + procedure test_wild_card_path_name; + + --%test(Execute test_packages using a object_name with wildcard in the front) + procedure test_wild_card_front_obj_name; + + --%test(Execute test_packages using a procedure name with wildcard in the front) + procedure test_wild_card_front_prc_name; + + -- %test(Execute test_packages using a path name with wildcard in the front) + procedure test_wild_card_front_path_name; + + --%test(Execute test_packages using a object_name with wildcard in the middle) + procedure test_wild_card_mid_obj_name; + + --%test(Execute test_packages using a procedure name with wildcard in the middle) + procedure test_wild_card_mid_prc_name; + + -- %test(Execute test_packages using a path name with wildcard in the middle) + procedure test_wild_card_mid_path_name; + + --%test(Execute test_packages using a object_name with multiple wildcards) + procedure test_wild_card_mul_obj_name; + + --%test(Execute test_packages using a procedure name with multiple wildcards) + procedure test_wild_card_mul_prc_name; + + -- %test(Execute test_packages using a path name with multiple wildcards) + procedure test_wild_card_mul_path_name; + + -- %test(Execute test_packages using a path name with multiple wildcards on different level) + procedure tst_wild_card_mul_lv_path_name; + + --%endcontext end test_suite_manager; / diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 492efcba2..41b969359 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -854,7 +854,7 @@ Failures:% l_results ut3_develop.ut_varchar2_list; begin select * bulk collect into l_random_results - from table ( ut3_develop.ut.run( 'ut3_tester_helper.test_package_1', a_random_test_order_seed => 3 ) ) + from table ( ut3_develop.ut.run( 'ut3_tester_helper.test_package_1', a_random_test_order_seed => 6 ) ) where trim(column_value) is not null and column_value not like 'Finished in %' and column_value not like '%Tests were executed with random order %'; diff --git a/test/ut3_user/api/test_ut_runner.pkb b/test/ut3_user/api/test_ut_runner.pkb index 80b1cd60b..b6b7c67e7 100644 --- a/test/ut3_user/api/test_ut_runner.pkb +++ b/test/ut3_user/api/test_ut_runner.pkb @@ -344,6 +344,38 @@ end;'; ut.expect(l_actual).to_equal(l_expected); end; + procedure test_get_suites_info_by_path is + l_expected sys_refcursor; + l_actual sys_refcursor; + begin + --Arrange + open l_expected for + select + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, + 'dummy_test_suite' item_description, 'UT_SUITE' item_type, 2 item_line_no, + 'some.path.dummy_test_package' path, 0 disabled_flag, null disabled_reason,null tags + from dual union all + select + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, + 'dummy_test' item_description, 'UT_TEST' item_type, 6 item_line_no, + 'some.path.dummy_test_package.some_dummy_test_procedure' path, 0 disabled_flag, null disabled_reason,null tags + from dual union all + select + 'UT3_USER' object_owner, 'PATH' object_name, 'PATH' item_name, + null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, + 'some.path' path, 0 disabled_flag, null disabled_reason, null tags + from dual union all + select + 'UT3_USER' object_owner, 'SOME' object_name, 'SOME' item_name, + null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, + 'some' path, 0 disabled_flag, null disabled_reason, null tags + from dual; + --Act + open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('ut3_user:some.path.dummy_test_package')); + --Assert + ut.expect(l_actual).to_equal(l_expected); + end; + procedure test_get_reporters_list is l_expected sys_refcursor; l_actual sys_refcursor; diff --git a/test/ut3_user/api/test_ut_runner.pks b/test/ut3_user/api/test_ut_runner.pks index 08282e997..e003ba852 100644 --- a/test/ut3_user/api/test_ut_runner.pks +++ b/test/ut3_user/api/test_ut_runner.pks @@ -65,6 +65,11 @@ create or replace package test_ut_runner is --%aftertest(cleanup_cache) procedure test_get_suites_info_twotag; + --%test(get_suites_info returns a cursor containing records for a newly created test with passed path) + --%beforetest(setup_cache_objects) + --%aftertest(cleanup_cache) + procedure test_get_suites_info_by_path; + --%test(get_reporters_list returns a cursor containing all built-in reporters and information about output-reporter) --%beforetest(setup_cache_objects) --%aftertest(cleanup_cache)
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: