8000 Merge pull request #1076 from utPLSQL/feature/rework_matcher · utPLSQL/utPLSQL@b0a2aab · GitHub
[go: up one dir, main page]

Skip to content

Commit b0a2aab

Browse files
authored
Merge pull request #1076 from utPLSQL/feature/rework_matcher
Feature/rework matcher
2 parents f091985 + fd7ef9c commit b0a2aab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1672
-267
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292

9393
- name: Download utPLSQL release for testing
9494
# For PR build - test using target branch as framework, for branch build use self as testing framework
95-
run: git clone --depth=1 --branch=${CI_HEAD_REF:-$CI_REF_NAME} https://github.com/utPLSQL/utPLSQL.git $UTPLSQL_DIR
95+
run: git clone --depth=1 --branch=${CI_BASE_REF:-$CI_REF_NAME} https://github.com/utPLSQL/utPLSQL.git $UTPLSQL_DIR
9696

9797
- name: Update privileges on sources
9898
run: chmod -R go+w ./{source,test,examples,${UTPLSQL_DIR}/source}

docs/userguide/expectations.md

Lines changed: 124 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -316,24 +316,25 @@ Since NULL is neither *true* nor *false*, both expectations will report failure.
316316

317317
The matrix below illustrates the data types supported by different matchers.
318318

319-
| Matcher | blob | boolean | clob | date | number | timestamp | timestamp<br>with<br>timezone | timestamp<br>with<br>local<br>timezone | varchar2 | interval<br>year<br>to<br>month | interval<br>day<br>to<br>second | cursor | nested<br>table<br>/ varray | object | json |
320-
| :---------------------: | :--: | :-----: | :--: | :--: | :----: | :-------: | :---------------------------: | :------------------------------------: | :------: | :-----------------------------: | :-----------------------------: | :----: | :-------------------------: | :----: | :--: |
321-
| **be_not_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
322-
| **be_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
323-
| **be_false** | | X | | | | | | | | | | | | | |
324-
| **be_true** | | X | | | | | | | | | | | | | |
325-
| **be_greater_than** | | | | X | X | X | X | X | | X | X | | | | |
326-
| **be_greater_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
327-
| **be_less_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
328-
| **be_less_than** | | | | X | X | X | X | X | | X | X | | | | |
329-
| **be_between** | | | | X | X | X | X | X | X | X | X | | | | |
330-
| **equal** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
331-
| **contain** | | | | | | | | | | | | X | X | X | |
332-
| **match** | | | X | | | | | | X | | | | | | |
333-
| **be_like** | | | X | | | | | | X | | | | | | |
334-
| **be_empty** | X | | X | | | | | | | | | X | X | | X |
335-
| **have_count** | | | | | | | | | | | | X | X | | X |
336-
319+
| Matcher | blob | boolean | clob | date | number | timestamp | timestamp<br>with<br>timezone | timestamp<br>with<br>local<br>timezone | varchar2 | interval<br>year<br>to<br>month | interval<br>day<br>to<br>second | cursor | nested<br>table<br>/ varray | object | json |
320+
| :-----------------------: | :--: | :-----: | :--: | :--: | :----: | :-------: | :---------------------------: | :------------------------------------: | :------: | :-----------------------------: | :-----------------------------: | :----: | :-------------------------: | :----: | :--: |
321+
| **be_not_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
322+
| **be_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
323+
| **be_false** | | X | | | | | | | | | | | | | |
324+
| **be_true** | | X | | | | | | | | | | | | | |
325+
| **be_greater_than** | | | | X | X | X | X | X | | X | X | | | | |
326+
| **be_greater_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
327+
| **be_less_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
328+
| **be_less_than** | | | | X | X | X | X | X | | X | X | | | | |
329+
| **be_between** | | | | X | X | X | X | X | X | X | X | | | | |
330+
| **equal** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
331+
| **contain** | | | | | | | | | | | | X | X | X | |
332+
| **match** | | | X | | | | | | X | | | | | | |
333+
| **be_like** | | | X | | | | | | X | | | | | | |
334+
| **be_empty** | X | | X | | | | | | | | | X | X | | X |
335+
| **have_count** | | | | | | | | | | | | X | X | | X |
336+
| **be_within().of_()** | | | | X | X | X | X | X | | | | | | | |
337+
| **be_within_pct().of_()** | | | | | X | | | | | | | | | | |
337338

338339
# Expecting exceptions
339340

@@ -1093,6 +1094,111 @@ SUCCESS
10931094
<ROW><UT_VARCHAR2_LIST>D</UT_VARCHAR2_LIST></ROW><ROW><UT_VARCHAR2_LIST>E</UT_VARCHAR2_LIST></ROW><ROW><UT_VARCHAR2_LIST>F</UT_VARCHAR2_LIST></ROW>
10941095
```
10951096
1097+
## to_be_within of
1098+
1099+
Determines wheter expected value is within range (tolerance) from another value.
1100+
1101+
The logical formual used for calcuating the matcher is:
1102+
```
1103+
result := ( abs( expected - actual ) <= distance )
1104+
```
1105+
The actual formula used for calculation is more complex to handle different data-types of expected/actual values as well as differnet types of distance value.
1106+
The matcher will fail if the `expected` and `actual` are more than `distance` apart from each other.
1107+
The matcher will fail if the dataypes of `expected` and `actual` are not the same.
1108+
1109+
The matcher works with data-types: `number`, `date`, `timestamp`, `timestamp with time zone`, `timestamp with local time zone`
1110+
The data-types of compared values must match exactly and if type does not match, the expectation will fail.
1111+
1112+
| expected/actual<br>data-type | distance data-type |
1113+
|:------------------------------:|:----------------------:|
1114+
| number | number |
1115+
| date | interval day to second |
1116+
| date | interval year to month |
1117+
| timestamp | interval day to second |
1118+
| timestamp | interval year to month |
1119+
| timestamp with time zone | interval day to second |
1120+
| timestamp with time zone | interval year to month |
1121+
| timestamp with local time zone | interval day to second |
1122+
| timestamp with local time zone | interval year to month |
1123+
1124+
1125+
The distance must be expressed as a non-negative number or non-negative interval.
1126+
1127+
>Note:
1128+
> Interval year-to-moth as a distance is giving sucess if the distance between the given dates/timestamps evaluates to value less or equal of the specified interval
1129+
> Keep in mind that a checking for distance of `interval '0-1' year to month` will actuall be successful if the distance is less than a month and 15 days.
1130+
> This is due to how oracle evaluates conversion between timestamp difference converted to `year to month interval`.
1131+
> The behavior is similar to a call to `months_between()` function with results rounded to full monts ie. round(months_between(date, date))
1132+
1133+
**Example 1.**
1134+
```sql
1135+
begin
1136+
ut.expect(3).to_be_within(1).of_(4);
1137+
end;
1138+
/
1139+
```
1140+
1141+
**Example 2.**
1142+
```sql
1143+
begin
1144+
ut.expect(3).to_be_within(1).of_(5);
1145+
end;
1146+
/
1147+
```
1148+
1149+
Returns following output via DBMS_OUTPUT:
1150+
```
1151+
Failures:
1152+
1153+
1) wihtin_test
1154+
Actual: 3 (number) was expected to be within 1 of 5 (number)
1155+
at "UT3_DEVELOP.UT_BE_WITHIN.OF_", line 48 l_result.expectation.to_(l_result );
1156+
at "UT3_DEVELOP.TEST_BETWNSTR.WIHTIN_TEST", line 5
1157+
```
1158+
1159+
**Example 3.**
1160+
```sql
1161+
begin
1162+
ut.expect(sysdate).to_be_within(interval '1' day).of_(sysdate+2);
1163+
end;
1164+
/
1165+
```
1166+
1167+
Returns following output via DBMS_OUTPUT:
1168+
```
1169+
Failures:
1170+
1171+
1) wihtin_test
1172+
Actual: 2020-06-07T13:32:58 (date) was expected to be within 1 day of 2020-06-09T13:32:58 (date)
1173+
at "UT3_DEVELOP.UT_BE_WITHIN.OF_", line 55 l_result.expectation.to_(l_result );
1174+
at "UT3_DEVELOP.TEST_BETWNSTR.WIHTIN_TEST", line 5
1175+
```
1176+
1177+
1178+
## to_be_within_pct of
1179+
1180+
Determines wheter actual value is within percentage range of expected value.
1181+
The matcher only works with `number` data-type.
1182+
1183+
The percentage deviation (distance) must be expressed as a non-negative number.
1184+
The formula used for calcuation of expectation is:
1185+
```
1186+
result := ( ( distance ) * expected >= abs( expected - actual ) * 100 )
1187+
```
1188+
1189+
**Example 1.**
1190+
```sql
1191+
begin
1192+
ut.expect(9).to_be_within_pct(10).of_(10);
1193+
end;
1194+
/
1195+
```
1196+
1197+
```
1198+
SUCCESS
1199+
Actual: 9 (number) was expected to be within 10 % of 10 (number)
1200+
```
1201+
10961202
10971203
## Comparing cursors, object types, nested tables and varrays
10981204

source/api/be_within.syn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
create synonym be_within for ut_be_within;

source/api/be_within_pct.syn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
create synonym be_within_pct for ut_be_within_pct;

source/core/ut_expectation_processor.pkb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ create or replace package body ut_expectation_processor as
159159
-- when 11g and 12c reports only package name
160160
function cut_header_and_expectations( a_stack varchar2 ) return varchar2 is
161161
begin
162-
return regexp_substr( a_stack, '(.*\.(UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+((.|\s)*)', 1, 1, 'm', 4);
162+
return regexp_substr( a_stack, '(.*\.(UT_EQUAL|UT_BE_WITHIN[A-Z0-9#_$]*|UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+((.|\s)*)', 1, 1, 'm', 4);
163163
end;
164164
function cut_address_columns( a_stack varchar2 ) return varchar2 is
165165
begin

source/core/ut_utils.pkb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,5 +901,63 @@ create or replace package body ut_utils is
901901
end;
902902
end;
903903

904+
function interval_to_text(a_interval dsinterval_unconstrained) return varchar2 is
905+
l_day varchar2(100) := extract(day from a_interval);
906+
l_hour varchar2(100) := extract(hour from a_interval);
907+
l_minute varchar2(100) := extract(minute from a_interval);
908+
l_second varchar2(100) := extract(second from a_interval);
909+
l_result varchar2(32767);
910+
begin
911+
l_result := case
912+
when l_day = 1 then l_day ||' day'
913+
when l_day > 1 then l_day ||' days'
914+
end ||
915+
case
916+
when l_hour = 1 then ' '|| l_hour ||' hour'
917+
when l_hour > 1 then ' '|| l_hour ||' hours'
918+
end ||
919+
case
920+
when l_minute = 1 then ' '||l_minute ||' minute'
921+
when l_minute > 1 then ' '||l_minute ||' minutes'
922+
end ||
923+
case
924+
when l_second > 1 then ' '||l_second ||' seconds'
925+
when l_second = 1 then ' '||l_second ||' second'
926+
when l_second > 0 then ' '||l_second ||' seconds'
927+
end;
928+
l_result :=
929+
case
930+
when a_interval is null then 'NULL'
931+
when l_result is null then '0 seconds'
932+
else ltrim(l_result,' ')
933+
end;
934+
935+
return l_result;
936+
end;
937+
938+
function interval_to_text(a_interval yminterval_unconstrained) return varchar2 is
939+
l_year varchar2(4) := extract(year from a_interval);
940+
l_month varchar2(20) := extract(month from a_interval);
941+
l_result varchar2(32767);
942+
begin
943+
l_result := case
944+
when l_year = 1 then l_year ||' year'
945+
when l_year > 1 then l_year ||' years'
946+
end ||
947+
case
948+
when l_month > 1 then ' '||l_month ||' months'
949+
when l_month = 1 then ' '||l_month ||' month'
950+
end;
951+
l_result :=
952+
case
953+
when a_interval is null then 'NULL'
954+
when l_result is null then '0 months'
955+
else ltrim(l_result,' ')
956+
end;
957+
958+
return l_result;
959+
end;
960+
961+
904962
end ut_utils;
905963
/

source/core/ut_utils.pks

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,9 @@ create or replace package ut_utils authid definer is
127127
gc_more_data_string constant varchar2(5) := '[...]';
128128
gc_more_data_string_len constant integer := length( gc_more_data_string );
129129
gc_number_format constant varchar2(100) := 'TM9';
130-
gc_date_format constant varchar2(100) := 'yyyy-mm-dd"T"hh24:mi:ss';
131-
gc_timestamp_format constant varchar2(100) := 'yyyy-mm-dd"T"hh24:mi:ssxff';
132-
gc_timestamp_tz_format constant varchar2(100) := 'yyyy-mm-dd"T"hh24:mi:ssxff tzh:tzm';
130+
gc_date_format constant varchar2(100) := 'syyyy-mm-dd"T"hh24:mi:ss';
131+
gc_timestamp_format constant varchar2(100) := 'syyyy-mm-dd"T"hh24:mi:ssxff';
132+
gc_timestamp_tz_format constant varchar2(100) := 'syyyy-mm-dd"T"hh24:mi:ssxff tzh:tzm';
133133
gc_null_string constant varchar2(4) := 'NULL';
134134
gc_empty_string constant varchar2(5) := 'EMPTY';
135135

@@ -457,6 +457,16 @@ create or replace package ut_utils authid definer is
457457
* If null value passed returns null
458458
*/
459459
function qualified_sql_name(a_name varchar2) return varchar2;
460-
460+
461+
/*
462+
* Return value of interval in plain english
463+
*/
464+
function interval_to_text(a_interval dsinterval_unconstrained) return varchar2;
465+
466+
/*
467+
* Return value of interval in plain english
468+
*/
469+
function interval_to_text(a_interval yminterval_unconstrained) return varchar2;
470+
461471
end ut_utils;
462472
/

source/create_grants.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ grant execute on &&ut3_owner..ut_be_like to &ut3_user;
8888
grant execute on &&ut3_owner..ut_be_not_null to &ut3_user;
8989
grant execute on &&ut3_owner..ut_be_null to &ut3_user;
9090
grant execute on &&ut3_owner..ut_be_true to &ut3_user;
91+
grant execute on &&ut3_owner..ut_be_within to &ut3_user;
92+
grant execute on &&ut3_owner..ut_be_within_pct to &ut3_user;
9193
grant execute on &&ut3_owner..ut_contain to &ut3_user;
9294
grant execute on &&ut3_owner..ut_equal to &ut3_user;
9395
grant execute on &&ut3_owner..ut_have_count to &ut3_user;

0 commit comments

Comments
 (0)
0