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

Skip to content

Commit 66dde90

Browse files
authored
Merge pull request #1008 from utPLSQL/feature/exclude_paths
Added ability to exclude items by tags.
2 parents 68e625f + 2caa749 commit 66dde90

File tree

9 files changed

+389
-213
lines changed

9 files changed

+389
-213
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ env:
4646
#utPLSQL released version directory
4747
- UTPLSQL_DIR="utPLSQL_latest_release"
4848
- SELFTESTING_BRANCH=${TRAVIS_BRANCH}
49-
- UTPLSQL_CLI_VERSION="3.1.7"
49+
- UTPLSQL_CLI_VERSION="3.1.8"
5050
# Maven
5151
- MAVEN_HOME=/usr/local/maven
5252
- MAVEN_CFG=$HOME/.m2

docs/userguide/annotations.md

+46-27
Original file line numberDiff line numberDiff line change
@@ -1225,11 +1225,11 @@ Finished in .035261 seconds
12251225

12261226
### Tags
12271227

1228-
Tag is a label attached to the test or a suite path. It is used for identification and execution a group of tests / suites that share same tag.
1228+
Tag is a label attached to the test or a suite. It is used for identification and execution of a group of tests / suites that share the same tag.
12291229

1230-
It allows us to group a tests / suites using a various categorization and place a test / suite in multiple buckets. Same tests can be group with other tests based on the functionality , frequency, type of output etc.
1230+
It allows for grouping of tests / suites using various categorization and place tests / suites in multiple buckets. Same tests can be grouped with other tests based on the functionality , frequency, type of output etc.
12311231

1232-
e.q.
1232+
e.g.
12331233

12341234
```sql
12351235
--%tags(batch,daily,csv)
@@ -1238,29 +1238,31 @@ e.q.
12381238
or
12391239

12401240
```sql
1241-
--%tags(api,online,json)
1241+
--%tags(online,json)
1242+
--%tags(api)
12421243
```
12431244

1245+
Tags are defined as a comma separated list within the `--%tags` annotation.
12441246

1247+
When executing a test run with tag filter applied, the framework will find all tests associated with the given tags and execute them.
1248+
The framework applies `OR` logic to all specified tags so any test / suite that matches at least one tag will be included in the test run.
12451249

1246-
Tags are defined as a coma separated list. When executing a test run with tag filter applied, framework will find all tests associated with given tags and execute them. Framework applies `OR` logic when resolving a tags so any tests / suites that match at least one tag will be included in the test run.
1250+
When a suite/context is tagged, all of its children will automatically inherit the tag and get executed along with the parent. Parent suite tests are not executed, but a suitepath hierarchy is kept.
12471251

1248-
When a suite gets tagged all of its children will automatically inherit a tag and get executed along the parent. Parent suit tests are not executed. but a suitepath hierarchy is kept.
1249-
1250-
Sample tag package.
12511252

1253+
Sample test suite package with tags.
12521254
```sql
1253-
create or replace package ut_sample_test IS
1255+
create or replace package ut_sample_test is
12541256

12551257
--%suite(Sample Test Suite)
1256-
--%tag(suite1)
1258+
--%tags(api)
12571259

12581260
--%test(Compare Ref Cursors)
1259-
--%tag(test1,sample)
1261+
--%tags(complex,fast)
12601262
procedure ut_refcursors1;
12611263

12621264
--%test(Run equality test)
1263-
--%tag(test2,sample)
1265+
--%tags(simple,fast)
12641266
procedure ut_test;
12651267

12661268
end ut_sample_test;
@@ -1287,30 +1289,47 @@ end ut_sample_test;
12871289
/
12881290
```
12891291

1290-
Execution of the test is done by using a parameter `a_tags`
1292+
Execution of the test is done by using the parameter `a_tags`
12911293

12921294
```sql
1293-
select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'suite1'));
1294-
select * from table(ut.run(a_tags => 'test1,test2'));
1295-
select * from table(ut.run(a_tags => 'sample'));
1295+
select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'api'));
1296+
```
1297+
The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api`
12961298

1297-
begin
1298-
ut.run(a_path => 'ut_sample_test',a_tags => 'suite1');
1299-
end;
1300-
/
1299+
```sql
1300+
select * from table(ut.run(a_tags => 'complex'));
1301+
```
1302+
The above call will execute only the `ut_sample_test.ut_refcursors1` test, as only the test `ut_refcursors1` is tagged with `complex`
13011303

1302-
exec ut.run('ut_sample_test', a_tags => 'sample');
1304+
```sql
1305+
select * from table(ut.run(a_tags => 'fast'));
13031306
```
1307+
The above call will execute both `ut_sample_test.ut_refcursors1` and `ut_sample_test.ut_test` tests, as both tests are tagged with `fast`
1308+
1309+
#### Tag naming convention
1310+
1311+
Tags must follow the below naming convention:
1312+
1313+
- tag is case sensitive
1314+
- tag can contain special characters like `$#/\?-!` etc.
1315+
- tag cannot be an empty string
1316+
- tag cannot start with a dash, e.g. `-some-stuff` is **not** a valid tag
1317+
- 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`
1318+
- leading and trailing spaces are ignored in tag name, e.g. `--%tags( tag1 , tag2 )` becomes `tag1` and `tag2` tag names
13041319

13051320

1321+
#### Excluding tests/suites by tags
13061322

1307-
Tags should adhere to following rules:
1323+
It is possible to exclude parts of test suites with tags.
1324+
In order to do so, prefix the tag name to exclude with a `-` (dash) sign when invoking the test run.
13081325

1309-
- tags are case sensitive
1310-
- tags cannot be an empty string
1311-
- tags cannot contain spaces e.g. to create a multi-word `tag` please use underscores,dashes, dots etc. e.g. `test_of_batch`
1312-
- tags with empty spaces will be ignored during execution
1313-
- tags can contain special characters
1326+
Examples (based on above sample test suite)
1327+
1328+
```sql
1329+
select * from table(ut.run(a_tags => 'api,fast,-complex'));
1330+
```
1331+
The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex`.
1332+
Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed.
13141333

13151334

13161335

docs/userguide/running-unit-tests.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,9 @@ select * from table(ut.run('hr.test_apply_bonus', a_random_test_order_seed => 30
284284
285285
# Run by Tags
286286

287-
In addition to the path, you can filter the tests to be run by specifying tags. Tags are defined in the test with the `--%tags`-annotation ([Read more](annotations.md#tags)).
288-
Multiple tags are separated by comma. If multiple tags are set, all tests with __any__ of them specified are run.
287+
In addition to the path, you can filter the tests to be run by specifying tags. Tags are defined in the test / context / suite with the `--%tags`-annotation ([Read more](annotations.md#tags)).
288+
Multiple tags are separated by comma.
289+
The framework applies `OR` logic to all specified tags so any test / suite that matches at least one tag will be included in the test run.
289290

290291
```sql
291292
begin
@@ -296,6 +297,11 @@ end;
296297
select * from table(ut.run('hr.test_apply_bonus', a_tags => 'suite1'))
297298
```
298299

300+
You can also exclude specific tags by adding a `-` (dash) in front of the tag
301+
302+
```sql
303+
select * from table(ut.run('hr.test_apply_bonus', a_tags => '-suite1'))
304+
```
299305

300306
# Keeping uncommitted data after test-run
301307

source/core/ut_suite_builder.pkb

+18-6
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,8 @@ create or replace package body ut_suite_builder is
321321
a_procedure_name t_object_name := null
322322
) is
323323
l_annotation_pos binary_integer;
324-
l_tag_list ut_varchar2_list := ut_varchar2_list();
324+
l_tags_list ut_varchar2_list := ut_varchar2_list();
325+
l_tag_items ut_varchar2_list;
325326
begin
326327
l_annotation_pos := a_tags_ann_text.first;
327328
while l_annotation_pos is not null loop
@@ -331,14 +332,25 @@ create or replace package body ut_suite_builder is
331332
|| get_object_reference( a_suite, a_procedure_name, l_annotation_pos )
332333
);
333334
else
334-
l_tag_list := l_tag_list multiset union distinct ut_utils.trim_list_elements(
335-
ut_utils.string_to_table(a_tags_ann_text(l_annotation_pos),',')
336-
);
335+
l_tag_items := ut_utils.trim_list_elements(ut_utils.string_to_table(a_tags_ann_text(l_annotation_pos),','));
336+
if l_tag_items is not empty then
337+
for i in 1 .. l_tag_items.count loop
338+
if regexp_like(l_tag_items(i),'^[^-](\S)+$') then
339+
l_tags_list.extend();
340+
l_tags_list(l_tags_list.last) := l_tag_items(i);
341+
else
342+
a_suite.put_warning(
343+
'Invalid value "'||l_tag_items(i)||'" for "--%tags" annotation. See documentation for details on valid tag values. Annotation value ignored.'
344+
|| get_object_reference( a_suite, a_procedure_name, l_annotation_pos )
345+
);
346+
end if;
347+
end loop;
348+
end if;
337349
end if;
338350
l_annotation_pos := a_tags_ann_text.next(l_annotation_pos);
339351
end loop;
340-
--remove empty strings from table list e.g. tag1,,tag2 and conver to rows
341-
a_list := ut_utils.convert_collection( ut_utils.filter_list(l_tag_list,ut_utils.gc_word_no_space) );
352+
--remove empty strings from table list e.g. tag1,,tag2 and convert to rows
353+
a_list := ut_utils.convert_collection( ut_utils.filter_list(set(l_tags_list),ut_utils.gc_word_no_space) );
342354
end;
343355

344356
procedure set_seq_no(

source/core/ut_suite_cache_manager.pkb

+33-11
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ create or replace package body ut_suite_cache_manager is
3030
and ( {:path:}
3131
and {:object_name:}
3232
and {:procedure_name:}
33+
)
3334
)
34-
)
3535
),
3636
{:tags:}
3737
suitepaths as (
@@ -106,8 +106,8 @@ create or replace package body ut_suite_cache_manager is
106106
function get_path_sql(a_path in varchar2) return varchar2 is
107107
begin
108108
return case when a_path is not null then q'[
109-
:l_path||'.' like c.path || '.%' /*all children and self*/
110-
or ( c.path||'.' like :l_path || '.%' --all parents
109+
:l_path||'.' like c.path || '.%' /*all parents and self*/
110+
or ( c.path||'.' like :l_path || '.%' /*all children and self*/
111111
]'
112112
else ' :l_path is null and ( :l_path is null ' end;
113113
end;
@@ -129,22 +129,31 @@ create or replace package body ut_suite_cache_manager is
129129
function get_tags_sql(a_tags_count in integer) return varchar2 is
130130
begin
131131
return case when a_tags_count > 0 then
132-
q'[filter_tags as (
132+
q'[included_tags as (
133133
select c.obj.path as path
134134
from suite_items c
135-
where c.obj.tags multiset intersect :a_tag_list is not empty
136-
),
135+
where c.obj.tags multiset intersect :a_include_tag_list is not empty or :a_include_tag_list is empty
136+
),
137+
excluded_tags as (
138+
select c.obj.path as path
139+
from suite_items c
140+
where c.obj.tags multiset intersect :a_exclude_tag_list is not empty
141+
),
137142
suite_items_tags as (
138143
select c.*
139144
from suite_items c
140145
where exists (
141-
select 1 from filter_tags t
142-
where t.path||'.' like c.obj.path || '.%' /*all children and self*/
143-
or c.obj.path||'.' like t.path || '.%' --all parents
146+
select 1 from included_tags t
147+
where t.path||'.' like c.obj.path || '.%' /*all parents and self*/
148+
or c.obj.path||'.' like t.path || '.%' /*all children and self*/
149+
)
150+
and not exists (
151+
select 1 from excluded_tags t
152+
where c.obj.path||'.' like t.path || '.%' /*all children and self*/
144153
)
145154
),]'
146155
else
147-
q'[dummy as (select 'x' from dual where :a_tag_list is null ),]'
156+
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),]'
148157
end;
149158
end;
150159

@@ -187,10 +196,23 @@ create or replace package body ut_suite_cache_manager is
187196
l_sql varchar2(32767);
188197
l_suite_item_name varchar2(20);
189198
l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows());
199+
l_include_tags ut_varchar2_rows;
200+
l_exclude_tags ut_varchar2_rows;
190201
l_object_owner varchar2(250) := ut_utils.qualified_sql_name(a_object_owner);
191202
l_object_name varchar2(250) := ut_utils.qualified_sql_name(a_object_name);
192203
l_procedure_name varchar2(250) := ut_utils.qualified_sql_name(a_procedure_name);
193204
begin
205+
206+
select column_value
207+
bulk collect into l_include_tags
208+
from table(l_tags)
209+
where column_value not like '-%';
210+
211+
select ltrim(column_value,'-')
212+
bulk collect into l_exclude_tags
213+
from table(l_tags)
214+
where column_value like '-%';
215+
194216
if a_path is null and a_object_name is not null then
195217
select min(c.path)
196218
into l_path
@@ -216,7 +238,7 @@ create or replace package body ut_suite_cache_manager is
216238

217239
execute immediate l_sql
218240
bulk collect into l_results
219-
using upper(l_object_owner), l_path, l_path, upper(a_object_name), upper(a_procedure_name), l_tags, a_random_seed;
241+
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;
220242
return l_results;
221243
end;
222244

test/ut3_tester/core/test_suite_builder.pkb

+61-1
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,67 @@ create or replace package body test_suite_builder is
14311431
'%</UT_LOGICAL_SUITE>%'
14321432
);
14331433

1434-
end;
1434+
end;
1435+
1436+
procedure test_spaces_in_tag is
1437+
l_actual clob;
1438+
l_annotations ut3.ut_annotations;
1439+
begin
1440+
--Arrange
1441+
l_annotations := ut3.ut_annotations(
1442+
ut3.ut_annotation(2, 'suite','testsuite', null),
1443+
ut3.ut_annotation(3, 'tags',' good_tag , bad tag , good-tag ', null),
1444+
ut3.ut_annotation(8, 'test','Some test', 'test_procedure'),
1445+
ut3.ut_annotation(9, 'tags',' good_tag , bad tag , good-tag ', 'test_procedure')
1446+
);
1447+
--Act
1448+
l_actual := invoke_builder_for_annotations(l_annotations, 'SOME_PACKAGE');
1449+
--Assert
1450+
ut.expect(l_actual).to_be_like(
1451+
'%<TAGS><VARCHAR2>good_tag</VARCHAR2><VARCHAR2>good-tag</VARCHAR2></TAGS>%'||
1452+
'<TAGS><VARCHAR2>good_tag</VARCHAR2><VARCHAR2>good-tag</VARCHAR2></TAGS>%'
1453+
);
1454+
ut.expect(l_actual).to_be_like(
1455+
'%<WARNINGS><VARCHAR2>Invalid value &quot;bad tag&quot; for &quot;--%tags&quot; annotation.'||
1456+
' See documentation for details on valid tag values. Annotation value ignored.
1457+
at package &quot;UT3_TESTER.SOME_PACKAGE&quot;, line 3</VARCHAR2><VARCHAR2>%'
1458+
);
1459+
ut.expect(l_actual).to_be_like(
1460+
'%<VARCHAR2>Invalid value &quot;bad tag&quot; for &quot;--%tags&quot; annotation.'||
1461+
' See documentation for details on valid tag values. Annotation value ignored.
1462+
at package &quot;UT3_TESTER.SOME_PACKAGE.TEST_PROCEDURE&quot;, line 9</VARCHAR2></WARNINGS>%'
1463+
);
1464+
end;
1465+
1466+
procedure test_minus_in_tag is
1467+
l_actual clob;
1468+
l_annotations ut3.ut_annotations;
1469+
begin
1470+
--Arrange
1471+
l_annotations := ut3.ut_annotations(
1472+
ut3.ut_annotation(2, 'suite','testsuite', null),
1473+
ut3.ut_annotation(3, 'tags',' good_tag , -invalid_tag , good-tag ', null),
1474+
ut3.ut_annotation(8, 'test','Some test', 'test_procedure'),
1475+
ut3.ut_annotation(9, 'tags',' good_tag , -invalid_tag , good-tag ', 'test_procedure')
1476+
);
1477+
--Act
1478+
l_actual := invoke_builder_for_annotations(l_annotations, 'SOME_PACKAGE');
1479+
--Assert
1480+
ut.expect(l_actual).to_be_like(
1481+
'%<TAGS><VARCHAR2>good_tag</VARCHAR2><VARCHAR2>good-tag</VARCHAR2></TAGS>%'||
1482+
'<TAGS><VARCHAR2>good_tag</VARCHAR2><VARCHAR2>good-tag</VARCHAR2></TAGS>%'
1483+
);
1484+
ut.expect(l_actual).to_be_like(
1485+
'%<WARNINGS><VARCHAR2>Invalid value &quot;-invalid_tag&quot; for &quot;--%tags&quot; annotation.'||
1486+
' See documentation for details on valid tag values. Annotation value ignored.
1487+
at package &quot;UT3_TESTER.SOME_PACKAGE&quot;, line 3</VARCHAR2><VARCHAR2>%'
1488+
);
1489+
ut.expect(l_actual).to_be_like(
1490+
'%<VARCHAR2>Invalid value &quot;-invalid_tag&quot; for &quot;--%tags&quot; annotation.'||
1491+
' See documentation for details on valid tag values. Annotation value ignored.
1492+
at package &quot;UT3_TESTER.SOME_PACKAGE.TEST_PROCEDURE&quot;, line 9</VARCHAR2></WARNINGS>%'
1493+
);
1494+
end;
14351495

14361496
end test_suite_builder;
14371497
/

0 commit comments

Comments
 (0)