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

Skip to content

Commit e1dfd05

Browse files
committed
Updated documentation.
Added validation of context name.
1 parent 837bd47 commit e1dfd05

4 files changed

Lines changed: 162 additions & 23 deletions

File tree

docs/userguide/annotations.md

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -997,9 +997,9 @@ In most of the cases, the code to be tested is consisting of PLSQL packages cont
997997
When creating test suites, it's quite common to maintain `one to one` relationship between test suite packages and tested code.
998998

999999
When it comes to test procedures themselves, it is best practice to have one test procedure for one tested behavior of the code that is tested.
1000-
The relationship between test procedure and tested procedure/function will be therefore `many to one` in most of the cases.
1000+
The relationship between test procedure and tested code will be therefore `many to one` or `many to many` in most of the cases.
10011001

1002-
With this comes a challenge. How to group tests, related to one tested procedure, so that it is obvious that they relate to the same code.
1002+
With this comes a challenge. How to group tests, related to one tested behavior, so that it is obvious that they relate to the same thing.
10031003

10041004
This is where utPLSQL contexts come handy.
10051005

@@ -1008,18 +1008,22 @@ Contexts allow for creating sub-suites within a suite package and they allow for
10081008
In essence, context behaves like a suite within a suite.
10091009

10101010
Context have following characteristics:
1011-
- start with the `--%context` annotation and ends with `--%endcontext`
1012-
- can have a name provided as parameter for example `--%context(remove_rooms_by_name)`
1013-
- when no name is provided for context, the context is names `context_N` where `N` is the number of the context in suite
1014-
- can have their own `--%beforeall`, `--%beforeeach`, `--%afterall` and `--%aftereach` procedures
1015-
- `--%beforeall`, `--%beforeeach`, `--%afterall` and `--%aftereach` procedures defined at suite level, propagate to context
1016-
- test suite package can have multiple contexts in it
1017-
- contexts cannot be nested
1018-
1011+
- context starts with the `--%context` annotation and ends with `--%endcontext`
1012+
- can have a name provided as parameter for example `--%context(remove_rooms_by_name)`. This is different than with `suite` and `test` annotations, where name is taken from test `package/procedure`
1013+
- when no name is provided for context, the context is named `context_N` where `N` is the number of the context in suite or parent context
1014+
- context name must be unique within it's parent (suite or parent context)
1015+
- if context name is not unique within it's parent, context and it's entire content is excluded from execution
1016+
- context name should not contain spaces or special characters
1017+
- context name cannot contain a `.` (hard stop) character
1018+
- contexts can be nested, so a context can be nested within another context
1019+
- suite/context can have multiple nested sibling contexts in it
1020+
- contexts can have their own `--%beforeall`, `--%beforeeach`, `--%afterall` and `--%aftereach` procedures
1021+
- `--%beforeall`, `--%beforeeach`, `--%afterall` and `--%aftereach` procedures defined at ancestor level, propagate to context
1022+
- if `--%endcontext` is missing for a context, the context spans to the end of package specification
10191023

10201024
The below example illustrates usage of `--%context` for separating tests for individual procedures of package.
10211025

1022-
Tested tables and code
1026+
Sample tables and code
10231027
```sql
10241028
create table rooms (
10251029
room_key number primary key,
@@ -1078,8 +1082,8 @@ end;
10781082

10791083
Below test suite defines:
10801084
- `--%beforeall` outside of context, that will be executed before all tests
1081-
- `--%context(remove_rooms_by_name)` to group tests for `remove_rooms_by_name` procedure
1082-
- `--%context(add_rooms_content)` to group tests for `add_rooms_content` procedure
1085+
- `--%context(remove_rooms_by_name)` to group tests related to `remove_rooms_by_name` functionality
1086+
- `--%context(add_rooms_content)` to group tests related to `add_rooms_content` functionality
10831087

10841088
```sql
10851089
create or replace package test_rooms_management is
@@ -1103,7 +1107,6 @@ create or replace package test_rooms_management is
11031107

11041108
--%endcontext
11051109

1106-
11071110
--%context(add_rooms_content)
11081111
--%displayname(Add content to a room)
11091112

@@ -1221,6 +1224,93 @@ Finished in .035261 seconds
12211224
5 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s)
12221225
```
12231226

1227+
Example of nested contexts test suite specification.
1228+
*Source - [slide 145](https://www.slideshare.net/Kevlin/structure-and-interpretation-of-test-cases/145?src=clipshare) of Structure and Interpretation of Test Cases by Kevlin Henney*
1229+
1230+
```sql
1231+
create or replace package queue_spec as
1232+
--%suite(Queue specification)
1233+
1234+
--%context(a_new_queue)
1235+
--%displayname(A new queue)
1236+
1237+
--%test(Is empty)
1238+
procedure is_empty;
1239+
--%test(Preserves positive bounding capacity)
1240+
procedure positive_bounding_capacity;
1241+
--%test(Cannot be created with non positive bounding capacity)
1242+
procedure non_positive_bounding_cap;
1243+
--%endcontext
1244+
--%context(an_empty_queue)
1245+
--%displayname(An empty queue)
1246+
1247+
--%test(Dequeues an empty value)
1248+
procedure deq_empty_value;
1249+
--%test(Remains empty when null enqueued)
1250+
procedure empty_with_null_enq;
1251+
--%test(Becomes non empty when non null value enqueued)
1252+
procedure non_empty_after_enq;
1253+
--%endcontext
1254+
--%context(a_non_empty_queue)
1255+
--%displayname(A non empty queue)
1256+
1257+
--%context(that_is_not_full)
1258+
--%displayname(that is not full)
1259+
1260+
--%test(Becomes longer when non null value enqueued)
1261+
procedure grow_on_enq_non_null;
1262+
--%test(Becomes full when enqueued up to capacity)
1263+
procedure full_on_enq_to_cap;
1264+
--%endcontext
1265+
--%context(that_is_full)
1266+
--%displayname(That is full)
1267+
1268+
--%test(Ignores further enqueued values)
1269+
procedure full_ignore_enq;
1270+
--%test(Becomes non full when dequeued)
1271+
procedure non_full_on_deq;
1272+
--%endcontext
1273+
1274+
--%test(Dequeues values in order enqueued)
1275+
procedure dequeue_ordered;
1276+
--%test(Remains unchanged when null enqueued)
1277+
procedure no_change_on_null_enq;
1278+
--%endcontext
1279+
end;
1280+
```
1281+
1282+
1283+
When such specification gets executed `ut.run('queue_spec'')` (without body created) you will see the nesting of tests within contexts.
1284+
```
1285+
Queue specification
1286+
An empty queue
1287+
Dequeues an empty value [.014 sec] (FAILED - 1)
1288+
Remains empty when null enqueued [.004 sec] (FAILED - 2)
1289+
Becomes non empty when non null value enqueued [.005 sec] (FAILED - 3)
1290+
A non empty queue
1291+
that is not full
1292+
Becomes longer when non null value enqueued [.005 sec] (FAILED - 4)
1293+
Becomes full when enqueued up to capacity [.005 sec] (FAILED - 5)
1294+
That is full
1295+
Ignores further enqueued values [.004 sec] (FAILED - 6)
1296+
Becomes non full when dequeued [.005 sec] (FAILED - 7)
1297+
Dequeues values in order enqueued [.006 sec] (FAILED - 8)
1298+
Remains unchanged when null enqueued [.004 sec] (FAILED - 9)
1299+
A new queue
1300+
Is empty [.007 sec] (FAILED - 10)
1301+
Preserves positive bounding capacity [.006 sec] (FAILED - 11)
1302+
Cannot be created with non positive bounding capacity [.005 sec] (FAILED - 12)
1303+
Failures:
1304+
1) deq_empty_value
1305+
ORA-04067: not executed, package body "UT3.QUEUE_SPEC" does not exist
1306+
ORA-06508: PL/SQL: could not find program unit being called: "UT3.QUEUE_SPEC"
1307+
ORA-06512: at line 6
1308+
...
1309+
Finished in .088573 seconds
1310+
12 tests, 0 failed, 12 errored, 0 disabled, 0 warning(s)
1311+
```
1312+
1313+
Suite nesting allows for organizing tests into human-readable specification of behavior.
12241314

12251315

12261316
### Tags

source/core/ut_suite_builder.pkb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,16 @@ create or replace package body ut_suite_builder is
774774
l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_name );
775775

776776
l_context_name := coalesce( a_annotations.by_line( l_context_pos ).text, gc_context||'_'||l_context_no );
777+
if regexp_like( l_context_name, '\.' ) or l_context_name is null then
778+
if regexp_like( l_context_name, '\.' ) then
779+
a_suite.put_warning(
780+
'Invalid value "'||l_context_name||'" for context name. The name cannot contain "." (hard stop) character.' ||
781+
' Context name ignored and fallback to auto-name "'||gc_context||'_'||l_context_no||'" ' ||
782+
get_object_reference( a_suite, null, l_context_pos )
783+
);
784+
end if;
785+
l_context_name := gc_context||'_'||l_context_no;
786+
end if;
777787
l_context := ut_suite_context(a_suite.object_owner, a_suite.object_name, l_context_name, l_context_pos );
778788
l_context.path := a_suite.path||'.'||l_context_name;
779789
l_context.description := a_annotations.by_line( l_context_pos ).text;

test/ut3_tester/core/test_suite_builder.pkb

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,6 @@ create or replace package body test_suite_builder is
965965
);
966966
end;
967967

968-
--%test(Gives warning when two contexts have the same name)
969968
procedure duplicate_context_name is
970969
l_actual clob;
971970
l_annotations ut3.ut_annotations;
@@ -1022,6 +1021,43 @@ create or replace package body test_suite_builder is
10221021
);
10231022
end;
10241023

1024+
procedure hard_stop_in_ctx_name is
1025+
l_actual clob;
1026+
l_annotations ut3.ut_annotations;
1027+
l_bad_name varchar2(100);
1028+
begin
1029+
--Arrange
1030+
l_bad_name := 'Context with invalid name. Should fail';
1031+
l_annotations := ut3.ut_annotations(
1032+
ut3.ut_annotation(1, 'suite','Cool', null),
1033+
ut3.ut_annotation(4, 'context','Context with invalid name. Should fail', null),
1034+
ut3.ut_annotation(7, 'test', 'In context', 'test_in_a_context'),
1035+
ut3.ut_annotation(13, 'endcontext',null, null)
1036+
);
1037+
--Act
1038+
l_actual := invoke_builder_for_annotations(l_annotations, 'SOME_PACKAGE');
1039+
--Assert
1040+
ut.expect(l_actual).to_be_like(
1041+
'%Invalid value "'||l_bad_name||'" for context name. The name cannot contain "." (hard stop) character. Context name ignored and fallback to auto-name "context_1"%'
1042+
);
1043+
ut.expect(l_actual).to_be_like(
1044+
'<ROWSET><ROW>'||
1045+
'<UT_LOGICAL_SUITE>' ||
1046+
'%<ITEMS>' ||
1047+
'<UT_SUITE_ITEM>' ||
1048+
'%<NAME>context_1</NAME><DESCRIPTION>Context with invalid name. Should fail</DESCRIPTION><PATH>some_package.context_1</PATH>' ||
1049+
'%<ITEMS>' ||
1050+
'<UT_SUITE_ITEM>' ||
1051+
'%<NAME>test_in_a_context</NAME><DESCRIPTION>In context</DESCRIPTION><PATH>some_package.context_1.test_in_a_context</PATH>' ||
1052+
'%</UT_SUITE_ITEM>' ||
1053+
'</ITEMS>%' ||
1054+
'</UT_SUITE_ITEM>%' ||
1055+
'</ITEMS>%' ||
1056+
'</UT_LOGICAL_SUITE>'||
1057+
'</ROW></ROWSET>'
1058+
);
1059+
end;
1060+
10251061
procedure throws_value_empty is
10261062
l_actual clob;
10271063
l_annotations ut3.ut_annotations;
@@ -1551,13 +1587,13 @@ create or replace package body test_suite_builder is
15511587
);
15521588
ut.expect(l_actual).to_be_like(
15531589
'%<WARNINGS><VARCHAR2>Invalid value &quot;bad tag&quot; for &quot;--%tags&quot; annotation.'||
1554-
' See documentation for details on valid tag values. Annotation value ignored.
1555-
at package &quot;UT3_TESTER.SOME_PACKAGE&quot;, line 3</VARCHAR2><VARCHAR2>%'
1590+
' See documentation for details on valid tag values. Annotation value ignored.' ||
1591+
'%at package &quot;UT3_TESTER.SOME_PACKAGE&quot;, line 3</VARCHAR2><VARCHAR2>%'
15561592
);
15571593
ut.expect(l_actual).to_be_like(
15581594
'%<VARCHAR2>Invalid value &quot;bad tag&quot; for &quot;--%tags&quot; annotation.'||
1559-
' See documentation for details on valid tag values. Annotation value ignored.
1560-
at package &quot;UT3_TESTER.SOME_PACKAGE.TEST_PROCEDURE&quot;, line 9</VARCHAR2></WARNINGS>%'
1595+
' See documentation for details on valid tag values. Annotation value ignored.' ||
1596+
'%at package &quot;UT3_TESTER.SOME_PACKAGE.TEST_PROCEDURE&quot;, line 9</VARCHAR2></WARNINGS>%'
15611597
);
15621598
end;
15631599

@@ -1581,13 +1617,13 @@ at package &quot;UT3_TESTER.SOME_PACKAGE.TEST_PROCEDURE&quot;, line 9</VARCHAR2>
15811617
);
15821618
ut.expect(l_actual).to_be_like(
15831619
'%<WARNINGS><VARCHAR2>Invalid value &quot;-invalid_tag&quot; for &quot;--%tags&quot; annotation.'||
1584-
' See documentation for details on valid tag values. Annotation value ignored.
1585-
at package &quot;UT3_TESTER.SOME_PACKAGE&quot;, line 3</VARCHAR2><VARCHAR2>%'
1620+
' See documentation for details on valid tag values. Annotation value ignored.' ||
1621+
'%at package &quot;UT3_TESTER.SOME_PACKAGE&quot;, line 3</VARCHAR2><VARCHAR2>%'
15861622
);
15871623
ut.expect(l_actual).to_be_like(
15881624
'%<VARCHAR2>Invalid value &quot;-invalid_tag&quot; for &quot;--%tags&quot; annotation.'||
1589-
' See documentation for details on valid tag values. Annotation value ignored.
1590-
at package &quot;UT3_TESTER.SOME_PACKAGE.TEST_PROCEDURE&quot;, line 9</VARCHAR2></WARNINGS>%'
1625+
' See documentation for details on valid tag values. Annotation value ignored.' ||
1626+
'%at package &quot;UT3_TESTER.SOME_PACKAGE.TEST_PROCEDURE&quot;, line 9</VARCHAR2></WARNINGS>%'
15911627
);
15921628
end;
15931629

test/ut3_tester/core/test_suite_builder.pks

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ create or replace package test_suite_builder is
134134
--%test(Gives warning when two contexts have the same name and ignores duplicated context)
135135
procedure duplicate_context_name;
136136

137+
--%test(Fallback to default naming and gives warning when context name contains "." character)
138+
procedure hard_stop_in_ctx_name;
139+
137140
--%endcontext
138141

139142
--%context(throws)

0 commit comments

Comments
 (0)