Skip to content

Commit 1551ea5

Browse files
committed
Adding any and none
1 parent ef1c02b commit 1551ea5

5 files changed

Lines changed: 271 additions & 5 deletions

File tree

docs/userguide/annotations.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,6 +1634,7 @@ Tags must follow the below naming convention:
16341634
- tag cannot start with a dash, e.g. `-some-stuff` is **not** a valid tag
16351635
- tag cannot contain spaces, e.g. `test of batch`. To create a multi-word tag use underscores or dashes, e.g. `test_of_batch`, `test-of-batch`
16361636
- leading and trailing spaces are ignored in tag name, e.g. `--%tags( tag1 , tag2 )` becomes `tag1` and `tag2` tag names
1637+
- tag cannot be one of two reserved words : `none` and `any`, any tags with that will not be considered.
16371638

16381639

16391640
### Suitepath

docs/userguide/running-unit-tests.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ Multiple tags are separated by comma.
325325

326326
Tag expressions are boolean expressions created by combining tags with the `!`, `&`, `|` operators. Tag expressions can be grouped using `(` and `)` braces. Grouping tag expressions affects operator precedence.
327327

328+
Two special expressions are supported, `any` and `none`, which select all tests with any tags at all, and all tests without any tags, respectively. These special expressions may be combined with other expressions just like normal tags. When using `none` be aware that if the suite is tagged it will exclude any tests and children belonging to that suite.
329+
328330
| Operator | Meaning |
329331
| -------- | --------|
330332
| ! | not |
@@ -450,6 +452,79 @@ The above calls will execute all suites/contexts/tests that are marked with any
450452
Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed.
451453

452454

455+
### Sample execution with `any` and `none`
456+
457+
Given a sample test package:
458+
459+
```sql linenums="1"
460+
create or replace package ut_sample_test is
461+
462+
--%suite(Sample Test Suite)
463+
464+
--%test(Compare Ref Cursors)
465+
--%tags(complex,fast)
466+
procedure ut_refcursors1;
467+
468+
--%test(Run equality test)
469+
--%tags(simple,fast)
470+
procedure ut_test;
471+
472+
--%test(Run equality test no tag)
473+
procedure ut_test_no_tag;
474+
475+
end ut_sample_test;
476+
/
477+
478+
create or replace package body ut_sample_test is
479+
480+
procedure ut_refcursors1 is
481+
v_actual sys_refcursor;
482+
v_expected sys_refcursor;
483+
begin
484+
open v_expected for select 1 as test from dual;
485+
open v_actual for select 2 as test from dual;
486+
487+
ut.expect(v_actual).to_equal(v_expected);
488+
end;
489+
490+
procedure ut_test is
491+
begin
492+
ut.expect(1).to_equal(0);
493+
end;
494+
495+
procedure ut_test_no_tag is
496+
begin
497+
ut.expect(1).to_equal(0);
498+
end;
499+
500+
end ut_sample_test;
501+
/
502+
```
503+
504+
```sql linenums="1"
505+
select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'none'));
506+
```
507+
508+
The above call will execute tests `ut_test_no_tag`
509+
510+
```sql linenums="1"
511+
select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'any'));
512+
```
513+
514+
The above call will execute tests `ut_test` and `ut_refcursors1`
515+
516+
```sql linenums="1"
517+
select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'none|simple'));
518+
```
519+
520+
The above call will execute tests `ut_test_no_tag` and `ut_test`
521+
522+
```sql linenums="1"
523+
select * from table(ut.run(a_tags => 'none|!simple'));
524+
```
525+
526+
The above call will execute tests `ut_test_no_tag` and `ut_refcursors1`
527+
453528
## Keeping uncommitted data after test-run
454529

455530
utPLSQL by default runs tests in autonomous transaction and performs automatic rollback to assure that tests do not impact one-another and do not have impact on the current session in your IDE.

source/core/ut_suite_tag_filter.pkb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ create or replace package body ut_suite_tag_filter is
2222
gc_operators constant ut_varchar2_list := ut_varchar2_list('|','&','!');
2323
gc_unary_operators constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator
2424
gc_binary_operators constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator
25+
gc_reserved_tag_words constant ut_varchar2_list := ut_varchar2_list('none','any');
2526
gc_tags_column_name constant varchar2(250) := 'tags';
2627
gc_exception_msg constant varchar2(200) := 'Invalid tag expression';
27-
28+
2829
type t_precedence_table is table of number index by varchar2(1);
2930
g_precedence t_precedence_table;
3031

@@ -172,8 +173,17 @@ create or replace package body ut_suite_tag_filter is
172173
begin
173174
l_idx := a_postfix_exp.first;
174175
while ( l_idx is not null) loop
176+
--If the token we got is a none or any keyword
177+
if a_postfix_exp(l_idx) member of gc_reserved_tag_words then
178+
179+
l_infix_stack.push(
180+
case
181+
when a_postfix_exp(l_idx) = 'none' then '('||a_tags_column_name||' is empty or '||a_tags_column_name||' is null)'
182+
else a_tags_column_name||' is not empty'
183+
end
184+
);
175185
--If token is operand but also single tag
176-
if regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then
186+
elsif regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then
177187
l_infix_stack.push(q'[']'||a_postfix_exp(l_idx)||q'[']'||l_member_token);
178188
--If token is unary operator not
179189
elsif a_postfix_exp(l_idx) member of gc_unary_operators then
@@ -256,7 +266,6 @@ with
256266
where ]'||l_tags||q'[
257267
)
258268
) t where c.id = t.id and r_num = 1 ]';
259-
260269
execute immediate l_sql bulk collect into l_suite_tags using a_suite_items;
261270
return l_suite_tags;
262271
end;

test/ut3_tester_helper/run_helper.pkb

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,12 +431,162 @@ create or replace package body run_helper is
431431
end test_tag_pkg_3;
432432
]';
433433

434+
execute immediate q'[create or replace package suite1_level1_pkg is
435+
436+
--%suite(suite1_level1)
437+
--%suitepath(any_none)
438+
--%rollback(manual)
439+
440+
--%test(Test 1 from Suite1 on level 1)
441+
--%tags(suite1,level1,test1,test1_level1)
442+
procedure test1_level1;
443+
444+
--%test(Test 2 from Suite1 on level 1)
445+
procedure test2_level1;
446+
447+
end suite1_level1_pkg;
448+
]';
449+
450+
execute immediate q'[create or replace package body suite1_level1_pkg is
451+
procedure test1_level1 is
452+
begin
453+
dbms_output.put_line('suite1_level1_pkg.test1_level1 executed');
454+
end;
455+
procedure test2_level1 is
456+
begin
457+
dbms_output.put_line('suite1_level1_pkg.test2_level1 executed');
458+
end;
459+
end suite1_level1_pkg;
460+
]';
461+
462+
execute immediate q'[create or replace package suite1_1_level2_pkg is
463+
464+
--%suite(suite1_1_level2)
465+
--%suitepath(any_none.suite1_level1)
466+
--%rollback(manual)
467+
468+
--%test(Test 1 from Suite1_2 on level 2)
469+
--%tags(level2,test1,test1_level2)
470+
procedure suite1_1_test1_level2;
471+
472+
--%test(Test 2 from Suite1_2 on level 2)
473+
procedure suite1_1_test2_level2;
474+
475+
end suite1_1_level2_pkg;
476+
]';
477+
478+
execute immediate q'[create or replace package body suite1_1_level2_pkg is
479+
procedure suite1_1_test1_level2 is
480+
begin
481+
dbms_output.put_line('suite1_1_level2_pkg.suite1_1_test1_level2 executed');
482+
end;
483+
procedure suite1_1_test2_level2 is
484+
begin
485+
dbms_output.put_line('suite1_1_level2_pkg.suite1_1_test2_level2 executed');
486+
end;
487+
end suite1_1_level2_pkg;
488+
]';
489+
490+
execute immediate q'[create or replace package suite1_2_level2_pkg is
491+
492+
--%suite(suite1_2_level2)
493+
--%tags(level2,suite1_2,suites)
494+
--%suitepath(any_none.suite1_level1)
495+
--%rollback(manual)
496+
497+
--%test(Test 1 from Suite1_2 on level 2)
498+
procedure suite1_2_test1_level2;
499+
500+
--%test(Test 2 from Suite1_2 on level 2)
501+
--%tags(level2,test2,test2_level2)
502+
procedure suite1_2_test2_level1;
503+
504+
end suite1_2_level2_pkg;
505+
]';
506+
507+
execute immediate q'[create or replace package body suite1_2_level2_pkg is
508+
procedure suite1_2_test1_level2 is
509+
begin
510+
dbms_output.put_line('suite1_2_level2_pkg.suite1_2_test1_level2 executed');
511+
end;
512+
procedure suite1_2_test2_level1 is
513+
begin
514+
dbms_output.put_line('suite1_2_level2_pkg.suite1_2_test2_level1 executed');
515+
end;
516+
end suite1_2_level2_pkg;
517+
]';
518+
519+
execute immediate q'[create or replace package suite2_level1_pkg is
520+
521+
--%suite(suite2_level1)
522+
--%tags(level1,suite2,suites)
523+
--%suitepath(any_none)
524+
--%rollback(manual)
525+
526+
--%test(Test 1 from Suite1 on level 1)
527+
--%tags(suite2,level1,test1,test1_level1)
528+
procedure test1_level1;
529+
530+
--%test(Test 2 from Suite1 on level 1)
531+
procedure test2_level1;
532+
533+
end suite2_level1_pkg;
534+
]';
535+
536+
execute immediate q'[create or replace package body suite2_level1_pkg is
537+
procedure test1_level1 is
538+
begin
539+
dbms_output.put_line('suite2_level1_pkg.test1_level1 executed');
540+
end;
541+
procedure test2_level1 is
542+
begin
543+
dbms_output.put_line('suite2_level1_pkg.test2_level1 executed');
544+
end;
545+
end suite2_level1_pkg;
546+
]';
547+
548+
execute immediate q'[create or replace package suite2_2_level2_pkg is
549+
550+
--%suite(suite2_2_level2)
551+
--%tags(level2,suite2_2,suites)
552+
--%suitepath(any_none.suite2_level1)
553+
--%rollback(manual)
554+
555+
--%test(Test 1 from Suite2_2 on level 2)
556+
procedure suite2_2_test1_level2;
557+
558+
--%test(Test 2 from Suite2_2 on level 2)
559+
--%tags(level2,test2,test2_level2)
560+
procedure suite2_2_test2_level2;
561+
562+
end suite2_2_level2_pkg;
563+
]';
564+
565+
execute immediate q'[create or replace package body suite2_2_level2_pkg is
566+
procedure suite2_2_test1_level2 is
567+
begin
568+
dbms_output.put_line('suite2_2_level2_pkg.suite2_2_test1_level2 executed');
569+
end;
570+
procedure suite2_2_test2_level2 is
571+
begin
572+
dbms_output.put_line('suite2_2_level2_pkg.suite2_2_test2_level2 executed');
573+
end;
574+
end suite2_2_level2_pkg;
575+
]';
576+
577+
434578
execute immediate q'[grant execute on test_package_1 to public]';
435579
execute immediate q'[grant execute on test_package_2 to public]';
436580
execute immediate q'[grant execute on test_package_3 to public]';
437581
execute immediate q'[grant execute on test_tag_pkg_1 to public]';
438582
execute immediate q'[grant execute on test_tag_pkg_2 to public]';
439-
execute immediate q'[grant execute on test_tag_pkg_3 to public]';
583+
execute immediate q'[grant execute on test_tag_pkg_3 to public]';
584+
585+
execute immediate q'[grant execute on suite1_level1_pkg to public]';
586+
execute immediate q'[grant execute on suite1_1_level2_pkg to public]';
587+
execute immediate q'[grant execute on suite1_2_level2_pkg to public]';
588+
execute immediate q'[grant execute on suite2_level1_pkg to public]';
589+
execute immediate q'[grant execute on suite2_2_level2_pkg to public]';
440590
end;
441591

442592
procedure drop_ut3_user_tests is
@@ -447,7 +597,13 @@ create or replace package body run_helper is
447597
execute immediate q'[drop package test_package_3]';
448598
execute immediate q'[drop package test_tag_pkg_1]';
449599
execute immediate q'[drop package test_tag_pkg_2]';
450-
execute immediate q'[drop package test_tag_pkg_3]';
600+
execute immediate q'[drop package test_tag_pkg_3]';
601+
602+
execute immediate q'[drop package suite2_2_level2_pkg]';
603+
execute immediate q'[drop package suite2_level1_pkg]';
604+
execute immediate q'[drop package suite1_2_level2_pkg]';
605+
execute immediate q'[drop package suite1_level1_pkg]';
606+
execute immediate q'[drop package suite1_1_level2_pkg]';
451607
end;
452608

453609
procedure create_test_suite is

test/ut3_user/api/test_ut_run.pkb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,31 @@ procedure tag_exclude_run_fun_pth_lst_lg is
12441244
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test3%executed%' );
12451245
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test4%executed%' );
12461246
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3.test6%executed%' );
1247+
1248+
l_results := ut3_tester_helper.run_helper.run(a_tags => 'any');
1249+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_level1_pkg.test1_level1 executed%' );
1250+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_level1_pkg.test2_level1 executed%' );
1251+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_level1_pkg.test1_level1 executed%' );
1252+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_2_level2_pkg.suite2_2_test1_level2 executed%' );
1253+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_2_level2_pkg.suite2_2_test2_level2 executed%' );
1254+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_2_level2_pkg.suite1_2_test1_level2 executed%' );
1255+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_2_level2_pkg.suite1_2_test2_level1 executed%' );
1256+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_1_level2_pkg.suite1_1_test1_level2 executed%' );
1257+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_level1_pkg.test2_level1 executed%' );
1258+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_1_level2_pkg.suite1_1_test2_level2 executed%' );
1259+
1260+
l_results := ut3_tester_helper.run_helper.run(a_tags => 'none');
1261+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_level1_pkg.test2_level1 executed%' );
1262+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_1_level2_pkg.suite1_1_test2_level2 executed%' );
1263+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_level1_pkg.test1_level1 executed%' );
1264+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_level1_pkg.test2_level1 executed%' );
1265+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_level1_pkg.test1_level1 executed%' );
1266+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_2_level2_pkg.suite2_2_test1_level2 executed%' );
1267+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_2_level2_pkg.suite2_2_test2_level2 executed%' );
1268+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_2_level2_pkg.suite1_2_test1_level2 executed%' );
1269+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_2_level2_pkg.suite1_2_test2_level1 executed%' );
1270+
ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_1_level2_pkg.suite1_1_test1_level2 executed%' );
1271+
12471272

12481273
end;
12491274

0 commit comments

Comments
 (0)