diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 87d577554..8703e24d9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -92,7 +92,7 @@ jobs:
- name: Download utPLSQL release for testing
# For PR build - test using target branch as framework, for branch build use self as testing framework
- run: git clone --depth=1 --branch=${CI_HEAD_REF:-$CI_REF_NAME} https://github.com/utPLSQL/utPLSQL.git $UTPLSQL_DIR
+ run: git clone --depth=1 --branch=${CI_BASE_REF:-$CI_REF_NAME} https://github.com/utPLSQL/utPLSQL.git $UTPLSQL_DIR
- name: Update privileges on sources
run: chmod -R go+w ./{source,test,examples,${UTPLSQL_DIR}/source}
diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md
index c07f3782e..a74e2576e 100644
--- a/docs/userguide/expectations.md
+++ b/docs/userguide/expectations.md
@@ -316,24 +316,25 @@ Since NULL is neither *true* nor *false*, both expectations will report failure.
The matrix below illustrates the data types supported by different matchers.
-| Matcher | blob | boolean | clob | date | number | timestamp | timestamp
with
timezone | timestamp
with
local
timezone | varchar2 | interval
year
to
month | interval
day
to
second | cursor | nested
table
/ varray | object | json |
-| :---------------------: | :--: | :-----: | :--: | :--: | :----: | :-------: | :---------------------------: | :------------------------------------: | :------: | :-----------------------------: | :-----------------------------: | :----: | :-------------------------: | :----: | :--: |
-| **be_not_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
-| **be_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
-| **be_false** | | X | | | | | | | | | | | | | |
-| **be_true** | | X | | | | | | | | | | | | | |
-| **be_greater_than** | | | | X | X | X | X | X | | X | X | | | | |
-| **be_greater_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
-| **be_less_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
-| **be_less_than** | | | | X | X | X | X | X | | X | X | | | | |
-| **be_between** | | | | X | X | X | X | X | X | X | X | | | | |
-| **equal** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
-| **contain** | | | | | | | | | | | | X | X | X | |
-| **match** | | | X | | | | | | X | | | | | | |
-| **be_like** | | | X | | | | | | X | | | | | | |
-| **be_empty** | X | | X | | | | | | | | | X | X | | X |
-| **have_count** | | | | | | | | | | | | X | X | | X |
-
+| Matcher | blob | boolean | clob | date | number | timestamp | timestamp
with
timezone | timestamp
with
local
timezone | varchar2 | interval
year
to
month | interval
day
to
second | cursor | nested
table
/ varray | object | json |
+| :-----------------------: | :--: | :-----: | :--: | :--: | :----: | :-------: | :---------------------------: | :------------------------------------: | :------: | :-----------------------------: | :-----------------------------: | :----: | :-------------------------: | :----: | :--: |
+| **be_not_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
+| **be_null** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
+| **be_false** | | X | | | | | | | | | | | | | |
+| **be_true** | | X | | | | | | | | | | | | | |
+| **be_greater_than** | | | | X | X | X | X | X | | X | X | | | | |
+| **be_greater_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
+| **be_less_or_equal** | | | | X | X | X | X | X | | X | X | | | | |
+| **be_less_than** | | | | X | X | X | X | X | | X | X | | | | |
+| **be_between** | | | | X | X | X | X | X | X | X | X | | | | |
+| **equal** | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
+| **contain** | | | | | | | | | | | | X | X | X | |
+| **match** | | | X | | | | | | X | | | | | | |
+| **be_like** | | | X | | | | | | X | | | | | | |
+| **be_empty** | X | | X | | | | | | | | | X | X | | X |
+| **have_count** | | | | | | | | | | | | X | X | | X |
+| **be_within().of_()** | | | | X | X | X | X | X | | | | | | | |
+| **be_within_pct().of_()** | | | | | X | | | | | | | | | | |
# Expecting exceptions
@@ -1093,6 +1094,111 @@ SUCCESS
D
E
F
```
+## to_be_within of
+
+Determines wheter expected value is within range (tolerance) from another value.
+
+The logical formual used for calcuating the matcher is:
+```
+ result := ( abs( expected - actual ) <= distance )
+```
+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.
+The matcher will fail if the `expected` and `actual` are more than `distance` apart from each other.
+The matcher will fail if the dataypes of `expected` and `actual` are not the same.
+
+The matcher works with data-types: `number`, `date`, `timestamp`, `timestamp with time zone`, `timestamp with local time zone`
+The data-types of compared values must match exactly and if type does not match, the expectation will fail.
+
+| expected/actual
data-type | distance data-type |
+|:------------------------------:|:----------------------:|
+| number | number |
+| date | interval day to second |
+| date | interval year to month |
+| timestamp | interval day to second |
+| timestamp | interval year to month |
+| timestamp with time zone | interval day to second |
+| timestamp with time zone | interval year to month |
+| timestamp with local time zone | interval day to second |
+| timestamp with local time zone | interval year to month |
+
+
+The distance must be expressed as a non-negative number or non-negative interval.
+
+>Note:
+> 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
+> 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.
+> This is due to how oracle evaluates conversion between timestamp difference converted to `year to month interval`.
+> The behavior is similar to a call to `months_between()` function with results rounded to full monts ie. round(months_between(date, date))
+
+**Example 1.**
+```sql
+begin
+ ut.expect(3).to_be_within(1).of_(4);
+end;
+/
+```
+
+**Example 2.**
+```sql
+begin
+ ut.expect(3).to_be_within(1).of_(5);
+end;
+/
+```
+
+Returns following output via DBMS_OUTPUT:
+```
+Failures:
+
+ 1) wihtin_test
+ Actual: 3 (number) was expected to be within 1 of 5 (number)
+ at "UT3_DEVELOP.UT_BE_WITHIN.OF_", line 48 l_result.expectation.to_(l_result );
+ at "UT3_DEVELOP.TEST_BETWNSTR.WIHTIN_TEST", line 5
+```
+
+**Example 3.**
+```sql
+begin
+ ut.expect(sysdate).to_be_within(interval '1' day).of_(sysdate+2);
+end;
+/
+```
+
+Returns following output via DBMS_OUTPUT:
+```
+Failures:
+
+ 1) wihtin_test
+ Actual: 2020-06-07T13:32:58 (date) was expected to be within 1 day of 2020-06-09T13:32:58 (date)
+ at "UT3_DEVELOP.UT_BE_WITHIN.OF_", line 55 l_result.expectation.to_(l_result );
+ at "UT3_DEVELOP.TEST_BETWNSTR.WIHTIN_TEST", line 5
+```
+
+
+## to_be_within_pct of
+
+Determines wheter actual value is within percentage range of expected value.
+The matcher only works with `number` data-type.
+
+The percentage deviation (distance) must be expressed as a non-negative number.
+The formula used for calcuation of expectation is:
+```
+ result := ( ( distance ) * expected >= abs( expected - actual ) * 100 )
+```
+
+**Example 1.**
+```sql
+begin
+ ut.expect(9).to_be_within_pct(10).of_(10);
+end;
+/
+```
+
+```
+SUCCESS
+ Actual: 9 (number) was expected to be within 10 % of 10 (number)
+```
+
## Comparing cursors, object types, nested tables and varrays
diff --git a/source/api/be_within.syn b/source/api/be_within.syn
new file mode 100644
index 000000000..e00005bb7
--- /dev/null
+++ b/source/api/be_within.syn
@@ -0,0 +1 @@
+create synonym be_within for ut_be_within;
diff --git a/source/api/be_within_pct.syn b/source/api/be_within_pct.syn
new file mode 100644
index 000000000..40e3fb8b9
--- /dev/null
+++ b/source/api/be_within_pct.syn
@@ -0,0 +1 @@
+create synonym be_within_pct for ut_be_within_pct;
diff --git a/source/core/ut_expectation_processor.pkb b/source/core/ut_expectation_processor.pkb
index a03a28965..77b734b30 100644
--- a/source/core/ut_expectation_processor.pkb
+++ b/source/core/ut_expectation_processor.pkb
@@ -159,7 +159,7 @@ create or replace package body ut_expectation_processor as
-- when 11g and 12c reports only package name
function cut_header_and_expectations( a_stack varchar2 ) return varchar2 is
begin
- return regexp_substr( a_stack, '(.*\.(UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+((.|\s)*)', 1, 1, 'm', 4);
+ 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);
end;
function cut_address_columns( a_stack varchar2 ) return varchar2 is
begin
diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb
index 81a610a0c..655b20d3d 100644
--- a/source/core/ut_utils.pkb
+++ b/source/core/ut_utils.pkb
@@ -899,5 +899,63 @@ create or replace package body ut_utils is
end;
end;
+ function interval_to_text(a_interval dsinterval_unconstrained) return varchar2 is
+ l_day varchar2(100) := extract(day from a_interval);
+ l_hour varchar2(100) := extract(hour from a_interval);
+ l_minute varchar2(100) := extract(minute from a_interval);
+ l_second varchar2(100) := extract(second from a_interval);
+ l_result varchar2(32767);
+ begin
+ l_result := case
+ when l_day = 1 then l_day ||' day'
+ when l_day > 1 then l_day ||' days'
+ end ||
+ case
+ when l_hour = 1 then ' '|| l_hour ||' hour'
+ when l_hour > 1 then ' '|| l_hour ||' hours'
+ end ||
+ case
+ when l_minute = 1 then ' '||l_minute ||' minute'
+ when l_minute > 1 then ' '||l_minute ||' minutes'
+ end ||
+ case
+ when l_second > 1 then ' '||l_second ||' seconds'
+ when l_second = 1 then ' '||l_second ||' second'
+ when l_second > 0 then ' '||l_second ||' seconds'
+ end;
+ l_result :=
+ case
+ when a_interval is null then 'NULL'
+ when l_result is null then '0 seconds'
+ else ltrim(l_result,' ')
+ end;
+
+ return l_result;
+ end;
+
+ function interval_to_text(a_interval yminterval_unconstrained) return varchar2 is
+ l_year varchar2(4) := extract(year from a_interval);
+ l_month varchar2(20) := extract(month from a_interval);
+ l_result varchar2(32767);
+ begin
+ l_result := case
+ when l_year = 1 then l_year ||' year'
+ when l_year > 1 then l_year ||' years'
+ end ||
+ case
+ when l_month > 1 then ' '||l_month ||' months'
+ when l_month = 1 then ' '||l_month ||' month'
+ end;
+ l_result :=
+ case
+ when a_interval is null then 'NULL'
+ when l_result is null then '0 months'
+ else ltrim(l_result,' ')
+ end;
+
+ return l_result;
+ end;
+
+
end ut_utils;
/
diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks
index c7d20ad0c..4c8b14e3d 100644
--- a/source/core/ut_utils.pks
+++ b/source/core/ut_utils.pks
@@ -127,9 +127,9 @@ create or replace package ut_utils authid definer is
gc_more_data_string constant varchar2(5) := '[...]';
gc_more_data_string_len constant integer := length( gc_more_data_string );
gc_number_format constant varchar2(100) := 'TM9';
- gc_date_format constant varchar2(100) := 'yyyy-mm-dd"T"hh24:mi:ss';
- gc_timestamp_format constant varchar2(100) := 'yyyy-mm-dd"T"hh24:mi:ssxff';
- gc_timestamp_tz_format constant varchar2(100) := 'yyyy-mm-dd"T"hh24:mi:ssxff tzh:tzm';
+ gc_date_format constant varchar2(100) := 'syyyy-mm-dd"T"hh24:mi:ss';
+ gc_timestamp_format constant varchar2(100) := 'syyyy-mm-dd"T"hh24:mi:ssxff';
+ gc_timestamp_tz_format constant varchar2(100) := 'syyyy-mm-dd"T"hh24:mi:ssxff tzh:tzm';
gc_null_string constant varchar2(4) := 'NULL';
gc_empty_string constant varchar2(5) := 'EMPTY';
@@ -457,6 +457,16 @@ create or replace package ut_utils authid definer is
* If null value passed returns null
*/
function qualified_sql_name(a_name varchar2) return varchar2;
-
+
+ /*
+ * Return value of interval in plain english
+ */
+ function interval_to_text(a_interval dsinterval_unconstrained) return varchar2;
+
+ /*
+ * Return value of interval in plain english
+ */
+ function interval_to_text(a_interval yminterval_unconstrained) return varchar2;
+
end ut_utils;
/
diff --git a/source/create_grants.sql b/source/create_grants.sql
index f7f37a662..6401b1522 100644
--- a/source/create_grants.sql
+++ b/source/create_grants.sql
@@ -88,6 +88,8 @@ grant execute on &&ut3_owner..ut_be_like to &ut3_user;
grant execute on &&ut3_owner..ut_be_not_null to &ut3_user;
grant execute on &&ut3_owner..ut_be_null to &ut3_user;
grant execute on &&ut3_owner..ut_be_true to &ut3_user;
+grant execute on &&ut3_owner..ut_be_within to &ut3_user;
+grant execute on &&ut3_owner..ut_be_within_pct to &ut3_user;
grant execute on &&ut3_owner..ut_contain to &ut3_user;
grant execute on &&ut3_owner..ut_equal to &ut3_user;
grant execute on &&ut3_owner..ut_have_count to &ut3_user;
diff --git a/source/create_synonyms.sql b/source/create_synonyms.sql
index a4f06c228..fa1c1dc45 100644
--- a/source/create_synonyms.sql
+++ b/source/create_synonyms.sql
@@ -104,6 +104,8 @@ create &action_type. synonym &ut3_user.be_like for &&ut3_owner..be_like;
create &action_type. synonym &ut3_user.be_not_null for &&ut3_owner..be_not_null;
create &action_type. synonym &ut3_user.be_null for &&ut3_owner..be_null;
create &action_type. synonym &ut3_user.be_true for &&ut3_owner..be_true;
+create &action_type. synonym &ut3_user.be_within for &&ut3_owner..be_within;
+create &action_type. synonym &ut3_user.be_within_pct for &&ut3_owner..be_within_pct;
create &action_type. synonym &ut3_user.contain for &&ut3_owner..contain;
create &action_type. synonym &ut3_user.equal for &&ut3_owner..equal;
create &action_type. synonym &ut3_user.have_count for &&ut3_owner..have_count;
diff --git a/source/expectations/data_values/ut_data_value.tps b/source/expectations/data_values/ut_data_value.tps
index 6864bc52e..beda3d911 100644
--- a/source/expectations/data_values/ut_data_value.tps
+++ b/source/expectations/data_values/ut_data_value.tps
@@ -16,6 +16,7 @@ create or replace type ut_data_value force authid current_user as object (
limitations under the License.
*/
data_type varchar2(250 char),
+ data_type_plsql varchar2(250 char),
self_type varchar2(250 char),
not instantiable member function is_null return boolean,
not instantiable member function to_string return varchar2,
diff --git a/source/expectations/data_values/ut_data_value_blob.tpb b/source/expectations/data_values/ut_data_value_blob.tpb
index a7b5fbeca..e145a8d4f 100644
--- a/source/expectations/data_values/ut_data_value_blob.tpb
+++ b/source/expectations/data_values/ut_data_value_blob.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_blob as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'blob';
+ self.data_type_plsql := 'blob';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_boolean.tpb b/source/expectations/data_values/ut_data_value_boolean.tpb
index 798222e30..867c3c19c 100644
--- a/source/expectations/data_values/ut_data_value_boolean.tpb
+++ b/source/expectations/data_values/ut_data_value_boolean.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_boolean as
self.data_value := ut_utils.boolean_to_int(a_value);
self.self_type := $$plsql_unit;
self.data_type := 'boolean';
+ self.data_type_plsql := 'boolean';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_clob.tpb b/source/expectations/data_values/ut_data_value_clob.tpb
index 9cfe9b283..f8a53a035 100644
--- a/source/expectations/data_values/ut_data_value_clob.tpb
+++ b/source/expectations/data_values/ut_data_value_clob.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_clob as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'clob';
+ self.data_type_plsql := 'clob';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_date.tpb b/source/expectations/data_values/ut_data_value_date.tpb
index 5b5b1d387..20424d193 100644
--- a/source/expectations/data_values/ut_data_value_date.tpb
+++ b/source/expectations/data_values/ut_data_value_date.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_date as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'date';
+ self.data_type_plsql := 'date';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_dsinterval.tpb b/source/expectations/data_values/ut_data_value_dsinterval.tpb
index f81f35974..026d4970f 100644
--- a/source/expectations/data_values/ut_data_value_dsinterval.tpb
+++ b/source/expectations/data_values/ut_data_value_dsinterval.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_dsinterval as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'interval day to second';
+ self.data_type_plsql := 'dsinterval_unconstrained';
return;
end;
@@ -31,7 +32,7 @@ create or replace type body ut_data_value_dsinterval as
overriding member function to_string return varchar2 is
begin
- return ut_utils.to_string(self.data_value);
+ return ut_utils.interval_to_text(self.data_value);
end;
overriding member function compare_implementation(a_other ut_data_value) return integer is
diff --git a/source/expectations/data_values/ut_data_value_dsinterval.tps b/source/expectations/data_values/ut_data_value_dsinterval.tps
index a047ead48..6f5cb708c 100644
--- a/source/expectations/data_values/ut_data_value_dsinterval.tps
+++ b/source/expectations/data_values/ut_data_value_dsinterval.tps
@@ -15,7 +15,7 @@ create or replace type ut_data_value_dsinterval under ut_data_value(
See the License for the specific language governing permissions and
limitations under the License.
*/
- data_value dsinterval_unconstrained,
+ data_value interval day(9) to second(9),
constructor function ut_data_value_dsinterval(self in out nocopy ut_data_value_dsinterval, a_value dsinterval_unconstrained) return self as result,
overriding member function is_null return boolean,
overriding member function to_string return varchar2,
diff --git a/source/expectations/data_values/ut_data_value_number.tpb b/source/expectations/data_values/ut_data_value_number.tpb
index c5c4fe2c3..382e6e9aa 100644
--- a/source/expectations/data_values/ut_data_value_number.tpb
+++ b/source/expectations/data_values/ut_data_value_number.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_number as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'number';
+ self.data_type_plsql := 'number';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_refcursor.tpb b/source/expectations/data_values/ut_data_value_refcursor.tpb
index 2715614c4..a4f0cf7a0 100644
--- a/source/expectations/data_values/ut_data_value_refcursor.tpb
+++ b/source/expectations/data_values/ut_data_value_refcursor.tpb
@@ -81,6 +81,7 @@ create or replace type body ut_data_value_refcursor as
self.self_type := $$plsql_unit;
self.data_id := sys_guid();
self.data_type := 'refcursor';
+ self.data_type_plsql := 'sys_refcursor';
self.compound_type := 'refcursor';
self.extract_path := '/*';
ut_compound_data_helper.cleanup_diff;
diff --git a/source/expectations/data_values/ut_data_value_timestamp.tpb b/source/expectations/data_values/ut_data_value_timestamp.tpb
index 79facae4a..318f799a3 100644
--- a/source/expectations/data_values/ut_data_value_timestamp.tpb
+++ b/source/expectations/data_values/ut_data_value_timestamp.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_timestamp as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'timestamp';
+ self.data_type_plsql := 'timestamp_unconstrained';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_timestamp_ltz.tpb b/source/expectations/data_values/ut_data_value_timestamp_ltz.tpb
index f2c5cddbd..6127de5f1 100644
--- a/source/expectations/data_values/ut_data_value_timestamp_ltz.tpb
+++ b/source/expectations/data_values/ut_data_value_timestamp_ltz.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_timestamp_ltz as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'timestamp with local time zone';
+ self.data_type_plsql := 'timestamp_ltz_unconstrained';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_timestamp_tz.tpb b/source/expectations/data_values/ut_data_value_timestamp_tz.tpb
index 0991e9e9f..d5d5cdd13 100644
--- a/source/expectations/data_values/ut_data_value_timestamp_tz.tpb
+++ b/source/expectations/data_values/ut_data_value_timestamp_tz.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_timestamp_tz as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'timestamp with time zone';
+ self.data_type_plsql := 'timestamp_tz_unconstrained';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_varchar2.tpb b/source/expectations/data_values/ut_data_value_varchar2.tpb
index 307ca583d..d04398697 100644
--- a/source/expectations/data_values/ut_data_value_varchar2.tpb
+++ b/source/expectations/data_values/ut_data_value_varchar2.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_varchar2 as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'varchar2';
+ self.data_type_plsql := 'varchar2(32767)';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_xmltype.tpb b/source/expectations/data_values/ut_data_value_xmltype.tpb
index d17896492..4b21a8937 100644
--- a/source/expectations/data_values/ut_data_value_xmltype.tpb
+++ b/source/expectations/data_values/ut_data_value_xmltype.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_xmltype as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'xmltype';
+ self.data_type_plsql := 'xmltype';
return;
end;
diff --git a/source/expectations/data_values/ut_data_value_yminterval.tpb b/source/expectations/data_values/ut_data_value_yminterval.tpb
index 7de3e58cd..a3a1e7a2f 100644
--- a/source/expectations/data_values/ut_data_value_yminterval.tpb
+++ b/source/expectations/data_values/ut_data_value_yminterval.tpb
@@ -21,6 +21,7 @@ create or replace type body ut_data_value_yminterval as
self.data_value := a_value;
self.self_type := $$plsql_unit;
self.data_type := 'interval year to month';
+ self.data_type_plsql := 'yminterval_unconstrained';
return;
end;
@@ -31,7 +32,7 @@ create or replace type body ut_data_value_yminterval as
overriding member function to_string return varchar2 is
begin
- return ut_utils.to_string(self.data_value);
+ return ut_utils.interval_to_text(self.data_value);
end;
overriding member function compare_implementation(a_other ut_data_value) return integer is
diff --git a/source/expectations/data_values/ut_data_value_yminterval.tps b/source/expectations/data_values/ut_data_value_yminterval.tps
index 278a2f803..c9ad2e776 100644
--- a/source/expectations/data_values/ut_data_value_yminterval.tps
+++ b/source/expectations/data_values/ut_data_value_yminterval.tps
@@ -15,7 +15,7 @@ create or replace type ut_data_value_yminterval under ut_data_value(
See the License for the specific language governing permissions and
limitations under the License.
*/
- data_value yminterval_unconstrained,
+ data_value interval year(9) to month,
constructor function ut_data_value_yminterval(self in out nocopy ut_data_value_yminterval, a_value yminterval_unconstrained) return self as result,
overriding member function is_null return boolean,
overriding member function to_string return varchar2,
diff --git a/source/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb
new file mode 100644
index 000000000..e2aa792d0
--- /dev/null
+++ b/source/expectations/matchers/ut_be_within.tpb
@@ -0,0 +1,137 @@
+create or replace type body ut_be_within as
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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_be_within(self in out nocopy ut_be_within, a_distance_from_expected number) return self as result is
+ begin
+ self.init(ut_data_value_number(a_distance_from_expected), $$plsql_unit);
+ return;
+ end;
+
+ constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected dsinterval_unconstrained) return self as result is
+ begin
+ self.init(ut_data_value_dsinterval(a_distance_from_expected), $$plsql_unit);
+ return;
+ end;
+
+ constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected yminterval_unconstrained) return self as result is
+ begin
+ self.init(ut_data_value_yminterval(a_distance_from_expected), $$plsql_unit);
+ return;
+ end;
+
+ member procedure of_(self in ut_be_within, a_expected date) is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_date(a_expected);
+ if l_result.is_negated_flag = 1 then
+ l_result.expectation.not_to(l_result);
+ else
+ l_result.expectation.to_(l_result);
+ end if;
+ end;
+
+ member function of_(self in ut_be_within, a_expected date) return ut_be_within is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_date(a_expected);
+ return l_result;
+ end;
+
+ member procedure of_(self in ut_be_within, a_expected timestamp_unconstrained) is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_timestamp(a_expected);
+ if l_result.is_negated_flag = 1 then
+ l_result.expectation.not_to(l_result);
+ else
+ l_result.expectation.to_(l_result);
+ end if;
+ end;
+
+ member function of_(self in ut_be_within, a_expected timestamp_unconstrained) return ut_be_within is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_timestamp(a_expected);
+ return l_result;
+ end;
+
+ member procedure of_(self in ut_be_within, a_expected timestamp_tz_unconstrained) is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_timestamp_tz(a_expected);
+ if l_result.is_negated_flag = 1 then
+ l_result.expectation.not_to(l_result);
+ else
+ l_result.expectation.to_(l_result);
+ end if;
+ end;
+
+ member function of_(self in ut_be_within, a_expected timestamp_tz_unconstrained) return ut_be_within is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_timestamp_tz(a_expected);
+ return l_result;
+ end;
+
+ member procedure of_(self in ut_be_within, a_expected timestamp_ltz_unconstrained) is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_timestamp_ltz(a_expected);
+ if l_result.is_negated_flag = 1 then
+ l_result.expectation.not_to(l_result);
+ else
+ l_result.expectation.to_(l_result);
+ end if;
+ end;
+
+ member function of_(self in ut_be_within, a_expected timestamp_ltz_unconstrained) return ut_be_within is
+ l_result ut_be_within := self;
+ begin
+ l_result.expected := ut_data_value_timestamp_ltz(a_expected);
+ return l_result;
+ end;
+
+ overriding member function run_matcher(self in out nocopy ut_be_within, a_actual ut_data_value) return boolean is
+ l_result boolean;
+ begin
+ if self.expected.data_type = a_actual.data_type
+ and (
+ self.expected is of (ut_data_value_date, ut_data_value_timestamp, ut_data_value_timestamp_tz, ut_data_value_timestamp_ltz)
+ and self.distance_from_expected is of (ut_data_value_yminterval, ut_data_value_dsinterval)
+ or self.expected is of (ut_data_value_number) and self.distance_from_expected is of (ut_data_value_number)
+ )
+ then
+ l_result := ut_be_within_helper.values_within_abs_distance( a_actual, self.expected, self.distance_from_expected) ;
+ else
+ l_result := (self as ut_matcher).run_matcher(a_actual);
+ end if;
+ return l_result;
+ end;
+
+ overriding member function failure_message(a_actual ut_data_value) return varchar2 is
+ begin
+ return (self as ut_matcher).failure_message(a_actual) || ' '||self.distance_from_expected.to_string ||' of '|| expected.to_string_report();
+ end;
+
+ overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2 is
+ begin
+ return (self as ut_matcher).failure_message_when_negated(a_actual) || ' '||self.distance_from_expected.to_string ||' of '|| expected.to_string_report();
+ end;
+
+end;
+/
diff --git a/source/expectations/matchers/ut_be_within.tps b/source/expectations/matchers/ut_be_within.tps
new file mode 100644
index 000000000..576f9ff37
--- /dev/null
+++ b/source/expectations/matchers/ut_be_within.tps
@@ -0,0 +1,36 @@
+create or replace type ut_be_within force under ut_be_within_pct(
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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_be_within(self in out nocopy ut_be_within, a_distance_from_expected number) return self as result,
+ constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected dsinterval_unconstrained) return self as result,
+ constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected yminterval_unconstrained) return self as result,
+ member procedure of_(self in ut_be_within, a_expected date),
+ member function of_(self in ut_be_within, a_expected date) return ut_be_within,
+ member procedure of_(self in ut_be_within, a_expected timestamp_unconstrained),
+ member function of_(self in ut_be_within, a_expected timestamp_unconstrained) return ut_be_within,
+ member procedure of_(self in ut_be_within, a_expected timestamp_tz_unconstrained ),
+ member function of_(self in ut_be_within, a_expected timestamp_tz_unconstrained) return ut_be_within,
+ member procedure of_(self in ut_be_within, a_expected timestamp_ltz_unconstrained),
+ member function of_(self in ut_be_within, a_expected timestamp_ltz_unconstrained) return ut_be_within,
+ overriding member function run_matcher(self in out nocopy ut_be_within, a_actual ut_data_value) return boolean,
+ overriding member function failure_message(a_actual ut_data_value) return varchar2,
+ overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2
+)
+not final
+/
diff --git a/source/expectations/matchers/ut_be_within_helper.pkb b/source/expectations/matchers/ut_be_within_helper.pkb
new file mode 100644
index 000000000..5dd82baa2
--- /dev/null
+++ b/source/expectations/matchers/ut_be_within_helper.pkb
@@ -0,0 +1,55 @@
+create or replace package body ut_be_within_helper as
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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.
+ */
+
+ function values_within_abs_distance(
+ a_actual ut_data_value, a_expected ut_data_value, a_distance ut_data_value
+ ) return boolean is
+ l_result integer;
+ l_YM_conversion varchar2(50) := case when a_distance is of (ut_data_value_yminterval) then ' year to month ' end;
+ l_formula varchar2(4000);
+ l_code varchar2(4000);
+ begin
+ l_formula :=
+ case
+ when a_actual is of (ut_data_value_date)
+ then '( cast(greatest(l_actual, l_expected) as timestamp) - cast(least(l_actual, l_expected) as timestamp) ) '||l_YM_conversion||' <= l_distance'
+ else '( greatest(l_actual, l_expected) - least(l_actual, l_expected) ) '||l_YM_conversion||' <= l_distance'
+ end;
+ l_code :=
+ q'[
+ declare
+ l_actual ]'||dbms_assert.simple_sql_name(a_actual.data_type_plsql)|| q'[ := treat(:a_actual as ]'||dbms_assert.simple_sql_name(a_actual.self_type)||q'[).data_value;
+ l_expected ]'||dbms_assert.simple_sql_name(a_expected.data_type_plsql)||q'[ := treat(:a_expected as ]'||dbms_assert.simple_sql_name(a_expected.self_type)||q'[).data_value;
+ l_distance ]'||dbms_assert.simple_sql_name(a_distance.data_type_plsql)||q'[ := treat(:a_distance as ]'||dbms_assert.simple_sql_name(a_distance.self_type)||q'[).data_value;
+ begin
+ :result :=
+ case
+ when
+ ]'||l_formula||q'[
+ then 1
+ else 0
+ end;
+ end;
+ ]';
+ execute immediate l_code
+ using a_actual, a_expected, a_distance, out l_result;
+ return l_result > 0;
+ end;
+
+end;
+/
diff --git a/source/expectations/matchers/ut_be_within_helper.pks b/source/expectations/matchers/ut_be_within_helper.pks
new file mode 100644
index 000000000..41737cc8f
--- /dev/null
+++ b/source/expectations/matchers/ut_be_within_helper.pks
@@ -0,0 +1,24 @@
+create or replace package ut_be_within_helper authid definer as
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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.
+ */
+
+ function values_within_abs_distance(
+ a_actual ut_data_value, a_expected ut_data_value, a_distance ut_data_value
+ ) return boolean;
+
+end;
+/
diff --git a/source/expectations/matchers/ut_be_within_pct.tpb b/source/expectations/matchers/ut_be_within_pct.tpb
new file mode 100644
index 000000000..8b280ffff
--- /dev/null
+++ b/source/expectations/matchers/ut_be_within_pct.tpb
@@ -0,0 +1,84 @@
+create or replace type body ut_be_within_pct as
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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_be_within_pct(self in out nocopy ut_be_within_pct, a_pct_of_expected number) return self as result is
+ begin
+ self.init(ut_data_value_number(a_pct_of_expected), $$plsql_unit);
+ return;
+ end;
+
+ member procedure init(self in out nocopy ut_be_within_pct, a_distance_from_expected ut_data_value, self_type varchar2) is
+ begin
+ self.distance_from_expected := a_distance_from_expected;
+ self.self_type := self_type;
+ end;
+
+ member procedure of_(self in ut_be_within_pct, a_expected number) is
+ l_result ut_be_within_pct := self;
+ begin
+ l_result.expected := ut_data_value_number(a_expected);
+ if l_result.is_negated_flag = 1 then
+ l_result.expectation.not_to(l_result);
+ else
+ l_result.expectation.to_(l_result);
+ end if;
+ end;
+
+ member function of_(self in ut_be_within_pct, a_expected number) return ut_be_within_pct is
+ l_result ut_be_within_pct := self;
+ begin
+ l_result.expected := ut_data_value_number(a_expected);
+ return l_result;
+ end;
+
+ overriding member function run_matcher(self in out nocopy ut_be_within_pct, a_actual ut_data_value) return boolean is
+ l_result boolean;
+ begin
+ if self.expected.data_type = a_actual.data_type then
+ if self.expected is of (ut_data_value_number) then
+ l_result :=
+ abs(treat(self.distance_from_expected as ut_data_value_number).data_value) * treat(self.expected as ut_data_value_number).data_value
+ >= abs( ( treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 );
+ end if;
+ else
+ l_result := (self as ut_matcher).run_matcher(a_actual);
+ end if;
+ return l_result;
+ end;
+
+ overriding member function failure_message(a_actual ut_data_value) return varchar2 is
+ begin
+ return rtrim( (self as ut_matcher).failure_message(a_actual), 'pct' ) || self.distance_from_expected.to_string ||' % of '|| expected.to_string_report();
+ end;
+
+ overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2 is
+ begin
+ return rtrim( (self as ut_matcher).failure_message_when_negated(a_actual), 'pct' ) || self.distance_from_expected.to_string ||' % of '|| expected.to_string_report();
+ end;
+
+ overriding member function error_message(a_actual ut_data_value) return varchar2 is
+ l_result varchar2(32767);
+ begin
+ if ut_utils.int_to_boolean(self.is_errored) then
+ l_result := 'Matcher '''||self.name()||''' cannot be used to compare Actual ('||a_actual.data_type||') with Expected ('||expected.data_type||') using distance ('||self.distance_from_expected.data_type||').';
+ end if;
+ return l_result;
+ end;
+
+end;
+/
diff --git a/source/expectations/matchers/ut_be_within_pct.tps b/source/expectations/matchers/ut_be_within_pct.tps
new file mode 100644
index 000000000..499e9a2d8
--- /dev/null
+++ b/source/expectations/matchers/ut_be_within_pct.tps
@@ -0,0 +1,35 @@
+create or replace type ut_be_within_pct force under ut_comparison_matcher(
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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.
+ */
+
+
+ /**
+ * Holds information about mather options
+ */
+ distance_from_expected ut_data_value,
+
+ constructor function ut_be_within_pct(self in out nocopy ut_be_within_pct, a_pct_of_expected number) return self as result,
+ member procedure init(self in out nocopy ut_be_within_pct, a_distance_from_expected ut_data_value, self_type varchar2),
+ member procedure of_(self in ut_be_within_pct, a_expected number),
+ member function of_(self in ut_be_within_pct, a_expected number) return ut_be_within_pct,
+ overriding member function run_matcher(self in out nocopy ut_be_within_pct, a_actual ut_data_value) return boolean,
+ overriding member function failure_message(a_actual ut_data_value) return varchar2,
+ overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2,
+ overriding member function error_message(a_actual ut_data_value) return varchar2
+)
+not final
+/
diff --git a/source/expectations/matchers/ut_equal.tpb b/source/expectations/matchers/ut_equal.tpb
index 05caf3b09..b08e8af75 100644
--- a/source/expectations/matchers/ut_equal.tpb
+++ b/source/expectations/matchers/ut_equal.tpb
@@ -172,6 +172,18 @@ create or replace type body ut_equal as
return l_result;
end;
+ member procedure include(self in ut_equal, a_items varchar2) is
+ begin
+ include( ut_varchar2_list( a_items ) );
+ end;
+
+ member procedure include(self in ut_equal, a_items ut_varchar2_list) is
+ l_result ut_equal := self;
+ begin
+ l_result.options.include.add_items(a_items);
+ l_result.expectation.to_(l_result );
+ end;
+
member function exclude(a_items varchar2) return ut_equal is
l_result ut_equal := self;
begin
@@ -186,6 +198,18 @@ create or replace type body ut_equal as
return l_result;
end;
+ member procedure exclude(self in ut_equal, a_items varchar2) is
+ begin
+ exclude( ut_varchar2_list( a_items ) );
+ end;
+
+ member procedure exclude(self in ut_equal, a_items ut_varchar2_list) is
+ l_result ut_equal := self;
+ begin
+ l_result.options.exclude.add_items(a_items);
+ l_result.expectation.to_(l_result );
+ end;
+
member function unordered return ut_equal is
l_result ut_equal := self;
begin
@@ -193,6 +217,13 @@ create or replace type body ut_equal as
return l_result;
end;
+ member procedure unordered(self in ut_equal) is
+ l_result ut_equal := self;
+ begin
+ l_result.options.unordered();
+ l_result.expectation.to_(l_result );
+ end;
+
member function join_by(a_columns varchar2) return ut_equal is
l_result ut_equal := self;
begin
@@ -209,18 +240,43 @@ create or replace type body ut_equal as
return l_result;
end;
- member function uc return ut_equal is
+ member procedure join_by(self in ut_equal, a_columns varchar2) is
begin
- return unordered_columns;
+ join_by( ut_varchar2_list( a_columns ) );
end;
+ member procedure join_by(self in ut_equal, a_columns ut_varchar2_list) is
+ l_result ut_equal := self;
+ begin
+ l_result.options.unordered();
+ l_result.options.join_by.add_items(a_columns);
+ l_result.expectation.to_(l_result );
+ end;
+
member function unordered_columns return ut_equal is
l_result ut_equal := self;
begin
l_result.options.unordered_columns();
return l_result;
end;
+
+ member procedure unordered_columns(self in ut_equal) is
+ l_result ut_equal := self;
+ begin
+ l_result.options.unordered_columns();
+ l_result.expectation.to_(l_result );
+ end;
+
+ member function uc return ut_equal is
+ begin
+ return unordered_columns;
+ end;
+ member procedure uc(self in ut_equal) is
+ begin
+ unordered_columns;
+ end;
+
overriding member function run_matcher(self in out nocopy ut_equal, a_actual ut_data_value) return boolean is
l_result boolean;
begin
diff --git a/source/expectations/matchers/ut_equal.tps b/source/expectations/matchers/ut_equal.tps
index eecbe8c1d..6ae03226e 100644
--- a/source/expectations/matchers/ut_equal.tps
+++ b/source/expectations/matchers/ut_equal.tps
@@ -43,17 +43,26 @@ create or replace type ut_equal force under ut_comparison_matcher(
constructor function ut_equal(self in out nocopy ut_equal, a_expected dsinterval_unconstrained, a_nulls_are_equal boolean := null) return self as result,
constructor function ut_equal(self in out nocopy ut_equal, a_expected json_element_t, a_nulls_are_equal boolean := null) return self as result,
member function include(a_items varchar2) return ut_equal,
- member function include(a_items ut_varchar2_list) return ut_equal,
+ member function include(a_items ut_varchar2_list) return ut_equal,
+ member procedure include(self in ut_equal, a_items varchar2),
+ member procedure include(self in ut_equal, a_items ut_varchar2_list),
member function exclude(a_items varchar2) return ut_equal,
member function exclude(a_items ut_varchar2_list) return ut_equal,
+ member procedure exclude(self in ut_equal, a_items varchar2),
+ member procedure exclude(self in ut_equal, a_items ut_varchar2_list),
member function unordered return ut_equal,
+ member procedure unordered(self in ut_equal),
member function join_by(a_columns varchar2) return ut_equal,
member function join_by(a_columns ut_varchar2_list) return ut_equal,
+ member procedure join_by(self in ut_equal, a_columns varchar2),
+ member procedure join_by(self in ut_equal, a_columns ut_varchar2_list),
overriding member function run_matcher(self in out nocopy ut_equal, a_actual ut_data_value) return boolean,
overriding member function failure_message(a_actual ut_data_value) return varchar2,
overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2,
member function unordered_columns return ut_equal,
- member function uc return ut_equal
+ member procedure unordered_columns(self in ut_equal),
+ member function uc return ut_equal,
+ member procedure uc(self in ut_equal)
)
not final
/
diff --git a/source/expectations/matchers/ut_matcher.tpb b/source/expectations/matchers/ut_matcher.tpb
index c64b6d246..6b5b98465 100644
--- a/source/expectations/matchers/ut_matcher.tpb
+++ b/source/expectations/matchers/ut_matcher.tpb
@@ -20,11 +20,6 @@ create or replace type body ut_matcher as
begin
ut_utils.debug_log('Failure - ut_matcher.run_matcher'||'(a_actual '||a_actual.data_type||')');
self.is_errored := ut_utils.boolean_to_int(true);
--- self.error_message := 'The matcher '''||name()||''' cannot be used';
--- if self.expected is not null then
--- self.error_message := self.error_message ||' for comparison of data type ('||self.expected.data_type||')';
--- end if;
--- self.error_message := self.error_message ||' with data type ('||a_actual.data_type||').';
return null;
end;
diff --git a/source/expectations/matchers/ut_matcher.tps b/source/expectations/matchers/ut_matcher.tps
index ba8bb7e85..a034e4ed2 100644
--- a/source/expectations/matchers/ut_matcher.tps
+++ b/source/expectations/matchers/ut_matcher.tps
@@ -1,4 +1,4 @@
-create or replace type ut_matcher authid current_user as object(
+create or replace type ut_matcher under ut_matcher_base(
/*
utPLSQL - Version 3
Copyright 2016 - 2021 utPLSQL Project
@@ -15,10 +15,9 @@ create or replace type ut_matcher authid current_user as object(
See the License for the specific language governing permissions and
limitations under the License.
*/
- self_type varchar2(250),
is_errored integer,
is_negated_flag number(1,0),
-
+ expectation ut_expectation_base,
/*
function: run_matcher
diff --git a/source/expectations/matchers/ut_matcher_base.tps b/source/expectations/matchers/ut_matcher_base.tps
new file mode 100644
index 000000000..ef7fd98a2
--- /dev/null
+++ b/source/expectations/matchers/ut_matcher_base.tps
@@ -0,0 +1,5 @@
+create or replace type ut_matcher_base force authid current_user as object(
+ self_type varchar2(250)
+)
+not final not instantiable
+/
diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb
index dfad630a6..dabe8fbff 100644
--- a/source/expectations/ut_expectation.tpb
+++ b/source/expectations/ut_expectation.tpb
@@ -15,31 +15,6 @@ create or replace type body ut_expectation as
See the License for the specific language governing permissions and
limitations under the License.
*/
- member procedure to_(self in ut_expectation, a_matcher ut_matcher) is
- l_expectation_result boolean;
- l_matcher ut_matcher := a_matcher;
- l_message varchar2(32767);
- begin
- if a_matcher.is_negated() then
- self.not_to( a_matcher );
- else
- l_expectation_result := l_matcher.run_matcher( self.actual_data );
- l_expectation_result := coalesce(l_expectation_result,false);
- l_message := coalesce( l_matcher.error_message( self.actual_data ), l_matcher.failure_message( self.actual_data ) );
- ut_expectation_processor.add_expectation_result( ut_expectation_result( ut_utils.to_test_result( l_expectation_result ), self.description, l_message ) );
- end if;
- end;
-
- member procedure not_to(self in ut_expectation, a_matcher ut_matcher) is
- l_expectation_result boolean;
- l_matcher ut_matcher := a_matcher;
- l_message varchar2(32767);
- begin
- l_expectation_result := coalesce( l_matcher.run_matcher_negated( self.actual_data ), false );
-
- l_message := coalesce( l_matcher.error_message( self.actual_data ), l_matcher.failure_message_when_negated( self.actual_data ) );
- ut_expectation_processor.add_expectation_result( ut_expectation_result( ut_utils.to_test_result( l_expectation_result ), self.description, l_message ) );
- end;
member procedure to_be_null(self in ut_expectation) is
begin
@@ -719,5 +694,70 @@ create or replace type body ut_expectation as
self.not_to( ut_contain(a_expected).negated() );
end;
+ member function to_be_within(a_dist number) return ut_be_within is
+ l_result ut_be_within;
+ begin
+ l_result := ut_be_within(a_dist);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
+ member function to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is
+ l_result ut_be_within;
+ begin
+ l_result := ut_be_within(a_dist);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
+ member function to_be_within(a_dist yminterval_unconstrained) return ut_be_within is
+ l_result ut_be_within;
+ begin
+ l_result := ut_be_within(a_dist);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
+ member function to_be_within_pct(a_dist number) return ut_be_within_pct is
+ l_result ut_be_within_pct;
+ begin
+ l_result := ut_be_within_pct(a_dist);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
+ member function not_to_be_within(a_dist number) return ut_be_within is
+ l_result ut_be_within;
+ begin
+ l_result := treat( ut_be_within(a_dist).negated() as ut_be_within);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
+ member function not_to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is
+ l_result ut_be_within;
+ begin
+ l_result := treat( ut_be_within(a_dist).negated() as ut_be_within);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
+ member function not_to_be_within(a_dist yminterval_unconstrained) return ut_be_within is
+ l_result ut_be_within;
+ begin
+ l_result := treat( ut_be_within(a_dist).negated() as ut_be_within);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
+ member function not_to_be_within_pct(a_dist number) return ut_be_within_pct is
+ l_result ut_be_within_pct;
+ begin
+ l_result := treat( ut_be_within_pct(a_dist).negated() as ut_be_within_pct);
+ l_result.expectation := self;
+ return l_result;
+ end;
+
end;
/
+
diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps
index 45d768200..86edc9cee 100644
--- a/source/expectations/ut_expectation.tps
+++ b/source/expectations/ut_expectation.tps
@@ -1,4 +1,4 @@
-create or replace type ut_expectation authid current_user as object(
+create or replace type ut_expectation force under ut_expectation_base(
/*
utPLSQL - Version 3
Copyright 2016 - 2021 utPLSQL Project
@@ -15,13 +15,7 @@ create or replace type ut_expectation authid current_user as object(
See the License for the specific language governing permissions and
limitations under the License.
*/
- actual_data ut_data_value,
- description varchar2(4000 char),
-
- --base matcher executors
- member procedure to_(self in ut_expectation, a_matcher ut_matcher),
- member procedure not_to(self in ut_expectation, a_matcher ut_matcher),
-
+
--shortcuts
member procedure to_be_null(self in ut_expectation),
member procedure to_be_not_null(self in ut_expectation),
@@ -168,8 +162,16 @@ create or replace type ut_expectation authid current_user as object(
member procedure to_contain(self in ut_expectation, a_expected sys_refcursor),
member procedure not_to_contain(self in ut_expectation, a_expected sys_refcursor),
member procedure to_contain(self in ut_expectation, a_expected anydata),
- member procedure not_to_contain(self in ut_expectation, a_expected anydata)
+ member procedure not_to_contain(self in ut_expectation, a_expected anydata),
+ member function to_be_within(a_dist number) return ut_be_within,
+ member function to_be_within(a_dist dsinterval_unconstrained) return ut_be_within,
+ member function to_be_within(a_dist yminterval_unconstrained) return ut_be_within,
+ member function to_be_within_pct(a_dist number) return ut_be_within_pct,
+ member function not_to_be_within(a_dist number) return ut_be_within,
+ member function not_to_be_within(a_dist dsinterval_unconstrained) return ut_be_within,
+ member function not_to_be_within(a_dist yminterval_unconstrained) return ut_be_within,
+ member function not_to_be_within_pct(a_dist number) return ut_be_within_pct
)
not final
/
diff --git a/source/expectations/ut_expectation_base.tpb b/source/expectations/ut_expectation_base.tpb
new file mode 100644
index 000000000..20b3e7a95
--- /dev/null
+++ b/source/expectations/ut_expectation_base.tpb
@@ -0,0 +1,44 @@
+create or replace type body ut_expectation_base as
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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.
+ */
+ member procedure to_(self in ut_expectation_base, a_matcher ut_matcher_base) is
+ l_expectation_result boolean;
+ l_matcher ut_matcher := treat(a_matcher as ut_matcher);
+ l_message varchar2(32767);
+ begin
+ if l_matcher.is_negated() then
+ self.not_to( a_matcher );
+ else
+ l_expectation_result := l_matcher.run_matcher( self.actual_data );
+ l_expectation_result := coalesce(l_expectation_result,false);
+ l_message := coalesce( l_matcher.error_message( self.actual_data ), l_matcher.failure_message( self.actual_data ) );
+ ut_expectation_processor.add_expectation_result( ut_expectation_result( ut_utils.to_test_result( l_expectation_result ), self.description, l_message ) );
+ end if;
+ end;
+
+ member procedure not_to(self in ut_expectation_base, a_matcher ut_matcher_base) is
+ l_expectation_result boolean;
+ l_matcher ut_matcher := treat(a_matcher as ut_matcher);
+ l_message varchar2(32767);
+ begin
+ l_expectation_result := coalesce( l_matcher.run_matcher_negated( self.actual_data ), false );
+
+ l_message := coalesce( l_matcher.error_message( self.actual_data ), l_matcher.failure_message_when_negated( self.actual_data ) );
+ ut_expectation_processor.add_expectation_result( ut_expectation_result( ut_utils.to_test_result( l_expectation_result ), self.description, l_message ) );
+ end;
+end;
+/
diff --git a/source/expectations/ut_expectation_base.tps b/source/expectations/ut_expectation_base.tps
new file mode 100644
index 000000000..a542d26ea
--- /dev/null
+++ b/source/expectations/ut_expectation_base.tps
@@ -0,0 +1,25 @@
+create or replace type ut_expectation_base authid current_user as object(
+ /*
+ utPLSQL - Version 3
+ Copyright 2016 - 2019 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.
+ */
+ actual_data ut_data_value,
+ description varchar2(4000 char),
+
+ --base matcher executors
+ member procedure to_(self in ut_expectation_base, a_matcher ut_matcher_base),
+ member procedure not_to(self in ut_expectation_base, a_matcher ut_matcher_base)
+) not final not instantiable
+/
diff --git a/source/expectations/ut_expectation_compound.tpb b/source/expectations/ut_expectation_compound.tpb
index 9dfd78e3e..6fc2e2647 100644
--- a/source/expectations/ut_expectation_compound.tpb
+++ b/source/expectations/ut_expectation_compound.tpb
@@ -34,162 +34,68 @@ create or replace type body ut_expectation_compound as
end;
- member function to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
+ member function to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_equal is
+ l_result ut_equal;
begin
- l_result.matcher := ut_equal(a_expected, a_nulls_are_equal);
+ l_result := ut_equal(a_expected, a_nulls_are_equal);
+ l_result.expectation := self;
return l_result;
end;
- member function not_to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
+ member function not_to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_equal is
+ l_result ut_matcher;
begin
- l_result.matcher := ut_equal(a_expected, a_nulls_are_equal).negated();
- return l_result;
- end;
-
- member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
- begin
- l_result.matcher := ut_equal(a_expected, a_nulls_are_equal);
- return l_result;
- end;
-
- member function not_to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
- begin
- l_result.matcher := ut_equal(a_expected, a_nulls_are_equal).negated();
- return l_result;
- end;
-
- member function to_contain(a_expected sys_refcursor) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
- begin
- l_result.matcher := ut_contain(a_expected);
- return l_result;
- end;
-
- member function not_to_contain(a_expected sys_refcursor) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
- begin
- l_result.matcher := ut_contain(a_expected).negated();
- return l_result;
- end;
-
- member function to_contain(a_expected anydata) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
- begin
- l_result.matcher := ut_contain(a_expected);
- return l_result;
+ l_result := ut_equal(a_expected, a_nulls_are_equal).negated();
+ l_result.expectation := self;
+ return treat(l_result as ut_equal);
end;
- member function not_to_contain(a_expected anydata) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
+ member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal is
+ l_result ut_equal;
begin
- l_result.matcher := ut_contain(a_expected).negated();
+ l_result := ut_equal(a_expected, a_nulls_are_equal);
+ l_result.expectation := self;
return l_result;
end;
- member function include(a_items varchar2) return ut_expectation_compound is
+ member function not_to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal is
+ l_result ut_matcher;
begin
- return include( ut_varchar2_list( a_items ) );
+ l_result := ut_equal(a_expected, a_nulls_are_equal).negated();
+ l_result.expectation := self;
+ return treat(l_result as ut_equal);
end;
- member function include(a_items ut_varchar2_list) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
+ member function to_contain(a_expected sys_refcursor) return ut_contain is
+ l_result ut_contain;
begin
- l_result.matcher := treat(l_result.matcher as ut_equal).include(a_items);
+ l_result := ut_contain(a_expected);
+ l_result.expectation := self;
return l_result;
end;
- member procedure include(self in ut_expectation_compound, a_items varchar2) is
- begin
- include( ut_varchar2_list( a_items ) );
- end;
-
- member procedure include(self in ut_expectation_compound, a_items ut_varchar2_list) is
+ member function not_to_contain(a_expected sys_refcursor) return ut_contain is
+ l_result ut_matcher;
begin
- self.to_( treat(matcher as ut_equal).include(a_items) );
+ l_result := ut_contain(a_expected).negated();
+ l_result.expectation := self;
+ return treat(l_result as ut_contain);
end;
-
- member function exclude(a_items varchar2) return ut_expectation_compound is
- begin
- return exclude( ut_varchar2_list( a_items ) );
- end;
-
- member function exclude(a_items ut_varchar2_list) return ut_expectation_compound is
- l_result ut_expectation_compound := self;
+
+ member function to_contain(a_expected anydata) return ut_contain is
+ l_result ut_contain;
begin
- l_result.matcher := treat(l_result.matcher as ut_equal).exclude(a_items);
+ l_result := ut_contain(a_expected);
+ l_result.expectation := self;
return l_result;
end;
- member procedure exclude(self in ut_expectation_compound, a_items varchar2) is
- begin
- exclude( ut_varchar2_list( a_items ) );
- end;
-
- member procedure exclude(self in ut_expectation_compound, a_items ut_varchar2_list) is
- begin
- self.to_( treat(matcher as ut_equal).exclude(a_items) );
- end;
-
- member function unordered return ut_expectation_compound is
- l_result ut_expectation_compound := self;
- begin
- l_result.matcher := treat(l_result.matcher as ut_equal).unordered();
- return l_result;
- end;
-
- member procedure unordered(self in ut_expectation_compound) is
- begin
- self.to_( treat(matcher as ut_equal).unordered() );
- end;
-
- member function join_by(a_columns varchar2) return ut_expectation_compound is
- begin
- return join_by( ut_varchar2_list( a_columns ) );
- end;
-
- member function join_by(a_columns ut_varchar2_list) return ut_expectation_compound is
- l_result ut_expectation_compound;
- begin
- l_result := self;
- l_result.matcher := treat(l_result.matcher as ut_equal).join_by(a_columns);
- return l_result;
- end;
-
- member procedure join_by(self in ut_expectation_compound, a_columns varchar2) is
- begin
- join_by( ut_varchar2_list( a_columns ) );
- end;
-
- member procedure join_by(self in ut_expectation_compound, a_columns ut_varchar2_list) is
- begin
- self.to_( treat(matcher as ut_equal).join_by(a_columns) );
- end;
-
- member function unordered_columns return ut_expectation_compound is
- l_result ut_expectation_compound;
- begin
- l_result := self;
- l_result.matcher := treat(l_result.matcher as ut_equal).unordered_columns;
- return l_result;
- end;
-
- member procedure unordered_columns(self in ut_expectation_compound) is
- begin
- self.to_( treat(matcher as ut_equal).unordered_columns );
- end;
-
- member function uc return ut_expectation_compound is
- begin
- return unordered_columns;
- end;
-
- member procedure uc(self in ut_expectation_compound) is
+ member function not_to_contain(a_expected anydata) return ut_contain is
+ l_result ut_matcher;
begin
- unordered_columns;
+ l_result := ut_contain(a_expected).negated();
+ l_result.expectation := self;
+ return treat(l_result as ut_contain);
end;
end;
diff --git a/source/expectations/ut_expectation_compound.tps b/source/expectations/ut_expectation_compound.tps
index ab320cae0..46da23fea 100644
--- a/source/expectations/ut_expectation_compound.tps
+++ b/source/expectations/ut_expectation_compound.tps
@@ -1,4 +1,4 @@
-create or replace type ut_expectation_compound force under ut_expectation(
+create or replace type ut_expectation_compound under ut_expectation(
/*
utPLSQL - Version 3
Copyright 2016 - 2021 utPLSQL Project
@@ -22,33 +22,15 @@ create or replace type ut_expectation_compound force under ut_expectation(
member procedure to_have_count(self in ut_expectation_compound, a_expected integer),
member procedure not_to_have_count(self in ut_expectation_compound, a_expected integer),
- member function to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_expectation_compound,
- member function not_to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_expectation_compound,
- member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_expectation_compound,
- member function not_to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_expectation_compound,
- member function to_contain(a_expected sys_refcursor) return ut_expectation_compound,
- member function not_to_contain(a_expected sys_refcursor) return ut_expectation_compound,
- member function to_contain(a_expected anydata) return ut_expectation_compound,
- member function not_to_contain(a_expected anydata) return ut_expectation_compound,
-
- member function include(a_items varchar2) return ut_expectation_compound,
- member function include(a_items ut_varchar2_list) return ut_expectation_compound,
- member procedure include(self in ut_expectation_compound, a_items varchar2),
- member procedure include(self in ut_expectation_compound, a_items ut_varchar2_list),
- member function exclude(a_items varchar2) return ut_expectation_compound,
- member function exclude(a_items ut_varchar2_list) return ut_expectation_compound,
- member procedure exclude(self in ut_expectation_compound, a_items varchar2),
- member procedure exclude(self in ut_expectation_compound, a_items ut_varchar2_list),
- member function unordered return ut_expectation_compound,
- member procedure unordered(self in ut_expectation_compound),
- member function join_by(a_columns varchar2) return ut_expectation_compound,
- member function join_by(a_columns ut_varchar2_list) return ut_expectation_compound,
- member procedure join_by(self in ut_expectation_compound, a_columns varchar2),
- member procedure join_by(self in ut_expectation_compound, a_columns ut_varchar2_list),
-
- member function unordered_columns return ut_expectation_compound,
- member procedure unordered_columns(self in ut_expectation_compound),
- member function uc return ut_expectation_compound,
- member procedure uc(self in ut_expectation_compound)
+ member function to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_equal,
+ member function not_to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_equal,
+ member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal,
+ member function not_to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal,
+ member function to_contain(a_expected sys_refcursor) return ut_contain,
+ member function not_to_contain(a_expected sys_refcursor) return ut_contain,
+ member function to_contain(a_expected anydata) return ut_contain,
+ member function not_to_contain(a_expected anydata) return ut_contain
)
/
+
+
diff --git a/source/install.sql b/source/install.sql
index 9f91297b2..cda057bdf 100644
--- a/source/install.sql
+++ b/source/install.sql
@@ -235,8 +235,14 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema
@@install_component.sql 'expectations/data_values/ut_data_value_xmltype.tps'
@@install_component.sql 'expectations/data_values/ut_compound_data_helper.pks'
@@install_component.sql 'expectations/data_values/ut_data_value_json.tps'
+@@install_component.sql 'expectations/matchers/ut_matcher_base.tps'
+@@install_component.sql 'expectations/ut_expectation_base.tps'
@@install_component.sql 'expectations/matchers/ut_matcher.tps'
@@install_component.sql 'expectations/matchers/ut_comparison_matcher.tps'
+@@install_component.sql 'expectations/matchers/ut_be_within_pct.tps'
+@@install_component.sql 'expectations/matchers/ut_be_within.tps'
+@@install_component.sql 'expectations/matchers/ut_be_within_helper.pks'
+@@install_component.sql 'expectations/ut_expectation.tps'
@@install_component.sql 'expectations/matchers/ut_be_false.tps'
@@install_component.sql 'expectations/matchers/ut_be_greater_or_equal.tps'
@@install_component.sql 'expectations/matchers/ut_be_greater_than.tps'
@@ -252,7 +258,6 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema
@@install_component.sql 'expectations/matchers/ut_be_between.tps'
@@install_component.sql 'expectations/matchers/ut_be_empty.tps'
@@install_component.sql 'expectations/matchers/ut_match.tps'
-@@install_component.sql 'expectations/ut_expectation.tps'
@@install_component.sql 'expectations/data_values/ut_json_leaf.tpb'
@@install_component.sql 'expectations/data_values/ut_json_tree_details.tpb'
@@install_component.sql 'expectations/data_values/ut_cursor_column.tpb'
@@ -292,11 +297,15 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema
@@install_component.sql 'expectations/matchers/ut_be_null.tpb'
@@install_component.sql 'expectations/matchers/ut_be_true.tpb'
@@install_component.sql 'expectations/matchers/ut_equal.tpb'
+@@install_component.sql 'expectations/matchers/ut_be_within_pct.tpb'
+@@install_component.sql 'expectations/matchers/ut_be_within.tpb'
+@@install_component.sql 'expectations/matchers/ut_be_within_helper.pkb'
@@install_component.sql 'expectations/matchers/ut_contain.tpb'
@@install_component.sql 'expectations/matchers/ut_have_count.tpb'
@@install_component.sql 'expectations/matchers/ut_be_between.tpb'
@@install_component.sql 'expectations/matchers/ut_be_empty.tpb'
@@install_component.sql 'expectations/matchers/ut_match.tpb'
+@@install_component.sql 'expectations/ut_expectation_base.tpb'
@@install_component.sql 'expectations/ut_expectation.tpb'
@@install_component.sql 'expectations/ut_expectation_compound.tpb'
@@install_component.sql 'expectations/ut_expectation_json.tpb'
@@ -354,6 +363,8 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema
@@install_component.sql 'api/be_not_null.syn'
@@install_component.sql 'api/be_null.syn'
@@install_component.sql 'api/be_true.syn'
+@@install_component.sql 'api/be_within_pct.syn'
+@@install_component.sql 'api/be_within.syn'
@@install_component.sql 'api/equal.syn'
@@install_component.sql 'api/have_count.syn'
@@install_component.sql 'api/match.syn'
diff --git a/source/reporters/ut_documentation_reporter.tpb b/source/reporters/ut_documentation_reporter.tpb
index 8b92d447f..30ab8f856 100644
--- a/source/reporters/ut_documentation_reporter.tpb
+++ b/source/reporters/ut_documentation_reporter.tpb
@@ -198,7 +198,7 @@ create or replace type body ut_documentation_reporter is
begin
print_failures_details(a_run);
print_warnings(a_run);
- self.print_text('Finished in ' || a_run.execution_time || ' seconds');
+ self.print_text('Finished in ' || ut_utils.interval_to_text(numtodsinterval(a_run.execution_time,'second')) );
l_summary_text :=
a_run.results_count.total_count || ' tests, '
diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql
index 230e394ee..bc41cb63a 100644
--- a/source/uninstall_objects.sql
+++ b/source/uninstall_objects.sql
@@ -54,6 +54,10 @@ drop synonym be_true;
drop synonym equal;
+drop synonym be_within;
+
+drop synonym be_within_pct;
+
drop type ut_coveralls_reporter force;
drop type ut_coverage_sonar_reporter force;
@@ -142,6 +146,12 @@ drop type ut_be_less_than force;
drop type ut_be_false force;
+drop type ut_be_within_pct force;
+
+drop type ut_be_within force;
+
+drop package ut_be_within_helper;
+
drop type ut_comparison_matcher force;
drop type ut_matcher force;
diff --git a/test/install_ut3_user_tests.sql b/test/install_ut3_user_tests.sql
index e790293c8..ad7f014bc 100644
--- a/test/install_ut3_user_tests.sql
+++ b/test/install_ut3_user_tests.sql
@@ -25,6 +25,8 @@ prompt Install user tests
@@ut3_user/expectations/binary/test_be_less_or_equal.pks
@@ut3_user/expectations/binary/test_be_greater_or_equal.pks
@@ut3_user/expectations/binary/test_be_greater_than.pks
+@@ut3_user/expectations/binary/test_to_be_within.pks
+@@ut3_user/expectations/binary/test_to_be_within_pct.pks
@@ut3_user/expectations/test_matchers.pks
@@ut3_user/expectations/test_expectation_anydata.pks
@@ut3_user/expectations/test_expectations_cursor.pks
@@ -66,6 +68,8 @@ set define off
@@ut3_user/expectations/binary/test_be_less_or_equal.pkb
@@ut3_user/expectations/binary/test_be_greater_or_equal.pkb
@@ut3_user/expectations/binary/test_be_greater_than.pkb
+@@ut3_user/expectations/binary/test_to_be_within.pkb
+@@ut3_user/expectations/binary/test_to_be_within_pct.pkb
@@ut3_user/expectations/test_matchers.pkb
@@ut3_user/expectations/test_expectation_anydata.pkb
@@ut3_user/expectations/test_expectations_cursor.pkb
diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb
index a3ed605f9..4ed718777 100644
--- a/test/ut3_tester/core/test_ut_utils.pkb
+++ b/test/ut3_tester/core/test_ut_utils.pkb
@@ -159,28 +159,28 @@ end;]' using p_expected_list;
procedure to_string_date is
l_value date := to_date('2016-12-31 23:59:59', 'yyyy-mm-dd hh24:mi:ss');
- l_expected varchar2(100) := '2016-12-31T23:59:59';
+ l_expected varchar2(100) := ' 2016-12-31T23:59:59';
begin
ut.expect(ut3_develop.ut_data_value_date(l_value).to_string()).to_equal(l_expected);
end;
procedure to_string_timestamp is
l_value timestamp(9) := to_timestamp('2016-12-31 23:59:59.123456789', 'yyyy-mm-dd hh24:mi:ss.ff');
- l_expected varchar2(100) := '2016-12-31T23:59:59'||gc_delimiter||'123456789';
+ l_expected varchar2(100) := ' 2016-12-31T23:59:59'||gc_delimiter||'123456789';
begin
ut.expect(ut3_develop.ut_data_value_timestamp(l_value).to_string()).to_equal(l_expected);
end;
procedure to_string_timestamp_ltz is
l_value timestamp(9) with local time zone := to_timestamp('2016-12-31 23:59:59.123456789', 'yyyy-mm-dd hh24:mi:ss.ff');
- l_expected varchar2(100) := '2016-12-31T23:59:59'||gc_delimiter||'123456789';
+ l_expected varchar2(100) := ' 2016-12-31T23:59:59'||gc_delimiter||'123456789';
begin
ut.expect(ut3_develop.ut_data_value_timestamp_ltz(l_value).to_string()).to_equal(l_expected);
end;
procedure to_string_timestamp_tz is
l_value timestamp(9) with time zone := to_timestamp_tz('2016-12-31 23:59:59.123456789 -8:00', 'yyyy-mm-dd hh24:mi:ss.ff tzh:tzm');
- l_expected varchar2(100) := '2016-12-31T23:59:59'||gc_delimiter||'123456789 -08:00';
+ l_expected varchar2(100) := ' 2016-12-31T23:59:59'||gc_delimiter||'123456789 -08:00';
begin
ut.expect(ut3_develop.ut_data_value_timestamp_tz(l_value).to_string()).to_equal(l_expected);
end;
@@ -432,5 +432,62 @@ end;
--Assert
ut.expect(l_actual).to_equal(l_expected);
end;
+
+ procedure int_conv_ds_sec is
+ l_expected varchar2(100) := '1 second';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(interval '1' second);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
+ procedure int_conv_ds_minute is
+ l_expected varchar2(100) := '1 minute';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(interval '1' minute);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
+ procedure int_conv_ds_hour is
+ l_expected varchar2(100) := '1 hour';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(interval '1' hour);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
+ procedure int_conv_ds_day is
+ l_expected varchar2(100) := '1 day';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(interval '1' day);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
+ procedure int_conv_ds_date is
+ l_expected varchar2(100) := '2 days 3 hours 4 minutes 11.333 seconds';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(INTERVAL '2 3:04:11.333' DAY TO SECOND);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
+ procedure int_conv_ym_year is
+ l_expected varchar2(100) := '1 year';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(interval '1' year);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
+ procedure int_conv_ym_month is
+ l_expected varchar2(100) := '1 month';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(interval '1' month);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
+ procedure int_conv_ym_date is
+ l_expected varchar2(100) := '1 year 2 months';
+ l_actual varchar2(200) := ut3_develop.ut_utils.interval_to_text(INTERVAL '1-2' YEAR TO MONTH);
+ begin
+ ut.expect(l_expected).to_equal(l_actual);
+ end;
+
end test_ut_utils;
/
diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks
index d8fca3b60..4d83b5042 100644
--- a/test/ut3_tester/core/test_ut_utils.pks
+++ b/test/ut3_tester/core/test_ut_utils.pks
@@ -128,5 +128,34 @@ create or replace package test_ut_utils is
--%test(replace_multiline_comments - replaces multi-line comments with empty lines)
procedure replace_multiline_comments;
+ --%context(interval_converter_to_strin)
+
+ --%test(returns text representation of interval day to second for 1 second interval)
+ procedure int_conv_ds_sec;
+
+ --%test(returns text representation of interval day to second for 1 minute interval)
+ procedure int_conv_ds_minute;
+
+ --%test(returns text representation of interval day to second for 1 hour interval)
+ procedure int_conv_ds_hour;
+
+ --%test(returns text representation of interval day to second for 1 day interval)
+ procedure int_conv_ds_day;
+
+ --%test(returns text representation of interval day to second for combination interval)
+ procedure int_conv_ds_date;
+
+ --%test(returns text representation of interval year to month for 1 year interval)
+ procedure int_conv_ym_year;
+
+ --%test(returns text representation of interval year to month for 1 month interval)
+ procedure int_conv_ym_month;
+
+ --%test(returns text representation of interval year to month for custom interval)
+ procedure int_conv_ym_date;
+
+
+ --%endcontext
+
end test_ut_utils;
/
diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb
index e9385d7d9..0abe10a4f 100644
--- a/test/ut3_tester_helper/coverage_helper.pkb
+++ b/test/ut3_tester_helper/coverage_helper.pkb
@@ -173,7 +173,7 @@ create or replace package body coverage_helper is
auto_drop => TRUE,
comments => 'one-time-job'
);
- while (l_status is null or l_status not in ('SUCCEEDED','FAILED')) and i < 30 loop
+ while (l_status is null or l_status not in ('SUCCEEDED','FAILED')) and i < 150 loop
l_status := get_job_status( l_job_name, l_timestamp );
sleep(0.1);
i := i + 1;
diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb
index e3af7c5ad..8ec19f6d8 100644
--- a/test/ut3_user/api/test_ut_run.pkb
+++ b/test/ut3_user/api/test_ut_run.pkb
@@ -6,6 +6,7 @@ create or replace package body test_ut_run is
gc_client_info constant varchar2(32767) := 'test client info';
g_context_test_results clob;
+ g_timestamp timestamp;
procedure clear_expectations is
begin
@@ -1260,6 +1261,7 @@ Failures:%
begin
select * bulk collect into l_lines from table(ut3_develop.ut.run('check_context'));
g_context_test_results := ut3_tester_helper.main_helper.table_to_clob(l_lines);
+ g_timestamp := current_timestamp;
end;
@@ -1272,7 +1274,7 @@ Failures:%
||'%BEFORE_SUITE:SUITE_DESCRIPTION=Suite description'
||'%BEFORE_SUITE:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%BEFORE_SUITE:SUITE_PATH=some.suite.path.check_context'
- ||'%BEFORE_SUITE:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_SUITE:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=before_suite%'
@@ -1287,14 +1289,14 @@ Failures:%
'%BEFORE_CONTEXT:CONTEXT_DESCRIPTION=context description'
||'%BEFORE_CONTEXT:CONTEXT_NAME=some_context'
||'%BEFORE_CONTEXT:CONTEXT_PATH=some.suite.path.check_context.some_context'
- ||'%BEFORE_CONTEXT:CONTEXT_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_CONTEXT:CONTEXT_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%BEFORE_CONTEXT:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.before_context'
||'%BEFORE_CONTEXT:CURRENT_EXECUTABLE_TYPE=beforeall'
||'%BEFORE_CONTEXT:RUN_PATHS=check_context'
||'%BEFORE_CONTEXT:SUITE_DESCRIPTION=Suite description'
||'%BEFORE_CONTEXT:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%BEFORE_CONTEXT:SUITE_PATH=some.suite.path.check_context'
- ||'%BEFORE_CONTEXT:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_CONTEXT:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=before_context%'
@@ -1308,17 +1310,17 @@ Failures:%
'%BEFORE_EACH_TEST:CONTEXT_DESCRIPTION=context description'
||'%BEFORE_EACH_TEST:CONTEXT_NAME=some_context'
||'%BEFORE_EACH_TEST:CONTEXT_PATH=some.suite.path.check_context.some_context'
- ||'%BEFORE_EACH_TEST:CONTEXT_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_EACH_TEST:CONTEXT_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%BEFORE_EACH_TEST:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.before_each_test'
||'%BEFORE_EACH_TEST:CURRENT_EXECUTABLE_TYPE=beforeeach'
||'%BEFORE_EACH_TEST:RUN_PATHS=check_context'
||'%BEFORE_EACH_TEST:SUITE_DESCRIPTION=Suite description'
||'%BEFORE_EACH_TEST:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%BEFORE_EACH_TEST:SUITE_PATH=some.suite.path.check_context'
- ||'%BEFORE_EACH_TEST:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_EACH_TEST:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%BEFORE_EACH_TEST:TEST_DESCRIPTION=Some test description'
||'%BEFORE_EACH_TEST:TEST_NAME='||gc_owner||'.check_context.the_test'
- ||'%BEFORE_EACH_TEST:TEST_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_EACH_TEST:TEST_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=before_each_test%'
@@ -1331,17 +1333,17 @@ Failures:%
'%BEFORE_TEST:CONTEXT_DESCRIPTION=context description'
||'%BEFORE_TEST:CONTEXT_NAME=some_context'
||'%BEFORE_TEST:CONTEXT_PATH=some.suite.path.check_context.some_context'
- ||'%BEFORE_TEST:CONTEXT_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_TEST:CONTEXT_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%BEFORE_TEST:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.before_test'
||'%BEFORE_TEST:CURRENT_EXECUTABLE_TYPE=beforetest'
||'%BEFORE_TEST:RUN_PATHS=check_context'
||'%BEFORE_TEST:SUITE_DESCRIPTION=Suite description'
||'%BEFORE_TEST:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%BEFORE_TEST:SUITE_PATH=some.suite.path.check_context'
- ||'%BEFORE_TEST:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_TEST:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%BEFORE_TEST:TEST_DESCRIPTION=Some test description'
||'%BEFORE_TEST:TEST_NAME='||gc_owner||'.check_context.the_test'
- ||'%BEFORE_TEST:TEST_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%BEFORE_TEST:TEST_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=before_test%'
@@ -1354,17 +1356,17 @@ Failures:%
'%THE_TEST:CONTEXT_DESCRIPTION=context description'
||'%THE_TEST:CONTEXT_NAME=some_context'
||'%THE_TEST:CONTEXT_PATH=some.suite.path.check_context.some_context'
- ||'%THE_TEST:CONTEXT_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%THE_TEST:CONTEXT_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%THE_TEST:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.the_test'
||'%THE_TEST:CURRENT_EXECUTABLE_TYPE=test'
||'%THE_TEST:RUN_PATHS=check_context'
||'%THE_TEST:SUITE_DESCRIPTION=Suite description'
||'%THE_TEST:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%THE_TEST:SUITE_PATH=some.suite.path.check_context'
- ||'%THE_TEST:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%THE_TEST:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%THE_TEST:TEST_DESCRIPTION=Some test description'
||'%THE_TEST:TEST_NAME='||gc_owner||'.check_context.the_test'
- ||'%THE_TEST:TEST_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%THE_TEST:TEST_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=the_test%'
@@ -1377,17 +1379,17 @@ Failures:%
'%AFTER_TEST:CONTEXT_DESCRIPTION=context description'
||'%AFTER_TEST:CONTEXT_NAME=some_context'
||'%AFTER_TEST:CONTEXT_PATH=some.suite.path.check_context.some_context'
- ||'%AFTER_TEST:CONTEXT_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_TEST:CONTEXT_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%AFTER_TEST:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.after_test'
||'%AFTER_TEST:CURRENT_EXECUTABLE_TYPE=aftertest'
||'%AFTER_TEST:RUN_PATHS=check_context'
||'%AFTER_TEST:SUITE_DESCRIPTION=Suite description'
||'%AFTER_TEST:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%AFTER_TEST:SUITE_PATH=some.suite.path.check_context'
- ||'%AFTER_TEST:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_TEST:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%AFTER_TEST:TEST_DESCRIPTION=Some test description'
||'%AFTER_TEST:TEST_NAME='||gc_owner||'.check_context.the_test'
- ||'%AFTER_TEST:TEST_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_TEST:TEST_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=after_test%'
@@ -1400,17 +1402,17 @@ Failures:%
'%AFTER_EACH_TEST:CONTEXT_DESCRIPTION=context description'
||'%AFTER_EACH_TEST:CONTEXT_NAME=some_context'
||'%AFTER_EACH_TEST:CONTEXT_PATH=some.suite.path.check_context.some_context'
- ||'%AFTER_EACH_TEST:CONTEXT_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_EACH_TEST:CONTEXT_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%AFTER_EACH_TEST:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.after_each_test'
||'%AFTER_EACH_TEST:CURRENT_EXECUTABLE_TYPE=aftereach'
||'%AFTER_EACH_TEST:RUN_PATHS=check_context'
||'%AFTER_EACH_TEST:SUITE_DESCRIPTION=Suite description'
||'%AFTER_EACH_TEST:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%AFTER_EACH_TEST:SUITE_PATH=some.suite.path.check_context'
- ||'%AFTER_EACH_TEST:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_EACH_TEST:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%AFTER_EACH_TEST:TEST_DESCRIPTION=Some test description'
||'%AFTER_EACH_TEST:TEST_NAME='||gc_owner||'.check_context.the_test'
- ||'%AFTER_EACH_TEST:TEST_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_EACH_TEST:TEST_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=after_each_test%'
@@ -1423,14 +1425,14 @@ Failures:%
'%AFTER_CONTEXT:CONTEXT_DESCRIPTION=context description'
||'%AFTER_CONTEXT:CONTEXT_NAME=some_context'
||'%AFTER_CONTEXT:CONTEXT_PATH=some.suite.path.check_context.some_context'
- ||'%AFTER_CONTEXT:CONTEXT_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_CONTEXT:CONTEXT_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%AFTER_CONTEXT:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.after_context'
||'%AFTER_CONTEXT:CURRENT_EXECUTABLE_TYPE=afterall'
||'%AFTER_CONTEXT:RUN_PATHS=check_context'
||'%AFTER_CONTEXT:SUITE_DESCRIPTION=Suite description'
||'%AFTER_CONTEXT:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%AFTER_CONTEXT:SUITE_PATH=some.suite.path.check_context'
- ||'%AFTER_CONTEXT:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_CONTEXT:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=after_context%'
@@ -1447,7 +1449,7 @@ Failures:%
||'%AFTER_SUITE:SUITE_DESCRIPTION=Suite description'
||'%AFTER_SUITE:SUITE_PACKAGE='||gc_owner||'.check_context'
||'%AFTER_SUITE:SUITE_PATH=some.suite.path.check_context'
- ||'%AFTER_SUITE:SUITE_START_TIME='||to_char(current_timestamp,'yyyy-mm-dd"T"hh24:mi')
+ ||'%AFTER_SUITE:SUITE_START_TIME='||to_char(g_timestamp,'syyyy-mm-dd"T"hh24:mi')
||'%APPLICATION_INFO:MODULE=utPLSQL'
||'%APPLICATION_INFO:ACTION=check_context'
||'%APPLICATION_INFO:CLIENT_INFO=after_suite%'
diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb
new file mode 100644
index 000000000..d490a8280
--- /dev/null
+++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb
@@ -0,0 +1,360 @@
+create or replace package body test_to_be_within is
+
+ procedure cleanup_expectations is
+ begin
+ ut3_tester_helper.main_helper.clear_expectations( );
+ end;
+
+ function be_within_expectation_block(
+ a_matcher_name varchar2,
+ a_actual_data_type varchar2,
+ a_actual_data varchar2,
+ a_expected_data_type varchar2,
+ a_expected_data varchar2,
+ a_distance varchar2,
+ a_distance_data_type varchar2,
+ a_matcher_end varchar2
+ ) return varchar2
+ is
+ l_execute varchar2(32000);
+ begin
+ l_execute := '
+ declare
+ l_actual '||a_actual_data_type||' := '||a_actual_data||';
+ l_expected '||a_expected_data_type||' := '||a_expected_data||';
+ l_distance '||a_distance_data_type||' := '||a_distance||';
+ begin
+ --act - execute the expectation
+ ut3_develop.ut.expect( l_actual ).'||a_matcher_name||'(l_distance).of_(l_expected)'||a_matcher_end||';
+ end;';
+ return l_execute;
+ end;
+
+ procedure test_to_be_within_fail(
+ a_matcher_name varchar2,
+ a_data_type varchar2,
+ a_actual varchar2,
+ a_expected varchar2,
+ a_distance varchar2,
+ a_distance_data_type varchar2,
+ a_matcher_end varchar2 := null
+ ) is
+ begin
+ execute immediate be_within_expectation_block(
+ a_matcher_name,a_data_type, a_actual, a_data_type, a_expected,
+ a_distance,a_distance_data_type, a_matcher_end
+ );
+ ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).not_to_equal(0);
+ cleanup_expectations;
+ end;
+
+ procedure test_to_be_within_success(
+ a_matcher_name varchar2,
+ a_data_type varchar2,
+ a_actual varchar2,
+ a_expected varchar2,
+ a_distance varchar2,
+ a_distance_data_type varchar2,
+ a_matcher_end varchar2 := null
+ ) is
+ begin
+ execute immediate be_within_expectation_block(
+ a_matcher_name,a_data_type, a_actual, a_data_type, a_expected,
+ a_distance,a_distance_data_type, a_matcher_end
+ );
+ ut.expect
+ (ut3_tester_helper.main_helper.get_failed_expectations_num
+ ,be_within_expectation_block(
+ a_matcher_name,a_data_type, a_actual, a_data_type, a_expected,
+ a_distance,a_distance_data_type, a_matcher_end
+ )
+ ).to_equal(0);
+ cleanup_expectations;
+ end;
+
+ procedure success_tests is
+ begin
+ test_to_be_within_success('to_be_within','number', '2', '4','2','number');
+ test_to_be_within_success('to_be_within','number', '4', '2','2','number');
+ test_to_be_within_success('to_be_within','date', 'sysdate+1', 'sysdate','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','date', 'sysdate', 'sysdate+1','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','date', 'sysdate', 'sysdate+200','''1-0''','interval year to month');
+ test_to_be_within_success('to_be_within','date', 'sysdate+200', 'sysdate','''1-0''','interval year to month');
+
+ test_to_be_within_success('to_be_within','timestamp', q'[TIMESTAMP '2017-08-09 07:00:00']', q'[TIMESTAMP '2017-08-08 06:59:48.667']','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','timestamp', q'[TIMESTAMP '2017-08-08 06:59:48.667']', q'[TIMESTAMP '2017-08-09 07:00:00']','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','timestamp', q'[TIMESTAMP '2017-08-09 07:00:00']', q'[TIMESTAMP '2018-08-09 07:00:00']','''1-0''','interval year to month');
+ test_to_be_within_success('to_be_within','timestamp', q'[TIMESTAMP '2018-08-09 07:00:00']', q'[TIMESTAMP '2017-08-09 07:00:00']','''1-0''','interval year to month');
+ test_to_be_within_success('to_be_within','timestamp_tz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','timestamp_tz_unconstrained', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','timestamp_tz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2018-08-09 07:00:00 -7:00']','''1-0''','interval year to month');
+ test_to_be_within_success('to_be_within','timestamp_tz_unconstrained', q'[TIMESTAMP '2018-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']','''1-0''','interval year to month');
+ test_to_be_within_success('to_be_within','timestamp_ltz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','timestamp_ltz_unconstrained', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_success('to_be_within','timestamp_ltz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2018-08-09 07:00:00 -7:00']','''1-0''','interval year to month');
+ test_to_be_within_success('to_be_within','timestamp_ltz_unconstrained', q'[TIMESTAMP '2018-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']','''1-0''','interval year to month');
+
+ test_to_be_within_success('to_( ut3_develop.be_within','number', '2', '4','2','number', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','number', '4', '2','2','number', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','date', 'sysdate+1', 'sysdate','''1 0:00:11.333''','interval day to second', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','date', 'sysdate', 'sysdate+1','''1 0:00:11.333''','interval day to second', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','date', 'sysdate', 'sysdate+200','''1-0''','interval year to month', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','date', 'sysdate+200', 'sysdate','''1-0''','interval year to month', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','timestamp', q'[TIMESTAMP '2018-08-09 07:00:00']', q'[TIMESTAMP '2017-08-09 07:00:00']','''1-0''','interval year to month', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','timestamp_tz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second', ')');
+ test_to_be_within_success('to_( ut3_develop.be_within','timestamp_ltz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second', ')');
+ test_to_be_within_fail('not_to_be_within','number', '2', '4','2','number');
+ test_to_be_within_fail('not_to_be_within','number', '4', '2','2','number');
+ test_to_be_within_fail('not_to_be_within','date', 'sysdate+1', 'sysdate','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_fail('not_to_be_within','date', 'sysdate', 'sysdate+1','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_fail('not_to_be_within','date', 'sysdate', 'sysdate+200','''1-0''','interval year to month');
+ test_to_be_within_fail('not_to_be_within','date', 'sysdate+200', 'sysdate','''1-0''','interval year to month');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','number', '2', '4','2','number',')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','number', '4', '2','2','number',')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','date', 'sysdate+1', 'sysdate','''1 0:00:11.333''','interval day to second',')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','date', 'sysdate', 'sysdate+1','''1 0:00:11.333''','interval day to second',')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','date', 'sysdate', 'sysdate+200','''1-0''','interval year to month',')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','date', 'sysdate+200', 'sysdate','''1-0''','interval year to month',')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','timestamp', q'[TIMESTAMP '2018-08-09 07:00:00']', q'[TIMESTAMP '2017-08-09 07:00:00']','''1-0''','interval year to month', ')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','timestamp_tz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second', ')');
+ test_to_be_within_fail('not_to( ut3_develop.be_within','timestamp_ltz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second', ')');
+ test_to_be_within_fail('not_to_be_within','timestamp', q'[TIMESTAMP '2018-08-09 07:00:00']', q'[TIMESTAMP '2017-08-09 07:00:00']','''1-0''','interval year to month');
+ test_to_be_within_fail('not_to_be_within','timestamp_tz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second');
+ test_to_be_within_fail('not_to_be_within','timestamp_ltz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', q'[TIMESTAMP '2017-08-08 05:59:48.668 -8:00']','''1 0:00:11.333''','interval day to second');
+ end;
+
+ procedure failed_tests is
+ begin
+ test_to_be_within_fail('to_be_within','number', '2', '4','1','number');
+ test_to_be_within_fail('to_be_within','number', '4', '2','1','number');
+ test_to_be_within_fail('to_be_within','date', 'sysdate', 'sysdate+1','''0 0:00:11.333''','interval day to second');
+ test_to_be_within_fail('to_be_within','date', 'sysdate+1', 'sysdate','''0 0:00:11.333''','interval day to second');
+ test_to_be_within_fail('to_be_within','date', 'sysdate', 'sysdate+750','''1-0''','interval year to month');
+ test_to_be_within_fail('to_be_within','date', 'sysdate+750', 'sysdate','''1-0''','interval year to month');
+ test_to_be_within_fail('to_( ut3_develop.be_within','number', '2', '4','1','number',')');
+ test_to_be_within_fail('to_( ut3_develop.be_within','number', '4', '2','1','number',')');
+ test_to_be_within_fail('to_( ut3_develop.be_within','date', 'sysdate', 'sysdate+1','''0 0:00:11.333''','interval day to second',')');
+ test_to_be_within_fail('to_( ut3_develop.be_within','date', 'sysdate+1', 'sysdate','''0 0:00:11.333''','interval day to second',')');
+ test_to_be_within_fail('to_( ut3_develop.be_within','date', 'sysdate', 'sysdate+750','''1-0''','interval year to month',')');
+ test_to_be_within_fail('to_( ut3_develop.be_within','date', 'sysdate+750', 'sysdate','''1-0''','interval year to month',')');
+ test_to_be_within_success('not_to_be_within','number', '2', '4','1','number');
+ test_to_be_within_success('not_to_be_within','number', '4', '2','1','number');
+ test_to_be_within_success('not_to_be_within','date', 'sysdate', 'sysdate+1','''0 0:00:11.333''','interval day to second');
+ test_to_be_within_success('not_to_be_within','date', 'sysdate+1', 'sysdate','''0 0:00:11.333''','interval day to second');
+ test_to_be_within_success('not_to_be_within','date', 'sysdate', 'sysdate+750','''1-0''','interval year to month');
+ test_to_be_within_success('not_to_be_within','date', 'sysdate+750', 'sysdate','''1-0''','interval year to month');
+ test_to_be_within_success('not_to( ut3_develop.be_within','number', '2', '4','1','number',')');
+ test_to_be_within_success('not_to( ut3_develop.be_within','number', '4', '2','1','number',')');
+ test_to_be_within_success('not_to( ut3_develop.be_within','date', 'sysdate', 'sysdate+1','''0 0:00:11.333''','interval day to second',')');
+ test_to_be_within_success('not_to( ut3_develop.be_within','date', 'sysdate+1', 'sysdate','''0 0:00:11.333''','interval day to second',')');
+ test_to_be_within_success('not_to( ut3_develop.be_within','date', 'sysdate', 'sysdate+750','''1-0''','interval year to month',')');
+ test_to_be_within_success('not_to( ut3_develop.be_within','date', 'sysdate+750', 'sysdate','''1-0''','interval year to month',')');
+ end;
+
+ procedure fail_for_number_not_within is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Arrange
+ --Act
+ ut3_develop.ut.expect(4).to_be_within(1).of_(7);
+ --Assert
+ l_expected_message := q'[Actual: 4 (number) was expected to be within 1 of 7 (number)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure fail_for_ds_int_not_within is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Arrange
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(interval '1' second).of_(sysdate+1);
+ --Assert
+ l_expected_message := q'[Actual: % (date) was expected to be within 1 second of % (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure fail_for_custom_ds_int is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Arrange
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(INTERVAL '2 3:04:11.333' DAY TO SECOND).of_(sysdate+100);
+ --Assert
+ l_expected_message := q'[Actual: % (date) was expected to be within 2 days 3 hours 4 minutes 11.333 seconds of % (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure fail_for_ym_int_not_within is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Arrange
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(INTERVAL '1' MONTH).of_(sysdate+ 45);
+ --Assert
+ l_expected_message := q'[Actual: % (date) was expected to be within 1 month of % (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure fail_for_custom_ym_int is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Arrange
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(INTERVAL '1-3' YEAR TO MONTH).of_(sysdate+720);
+ --Assert
+ l_expected_message := q'[Actual: % (date) was expected to be within 1 year 3 months % (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure fail_msg_when_not_within is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Arrange
+ --Act
+ ut3_develop.ut.expect(1).to_be_within(3).of_(12);
+ --Assert
+ l_expected_message := q'[Actual: 1 (number) was expected to be within 3 of 12 (number)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure fail_msg_wrong_types is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(interval '1' second).of_(systimestamp);
+ --Assert
+ l_expected_message := q'[Matcher 'be within' cannot be used to compare Actual (date) with Expected (timestamp with time zone) using distance (interval day to second).]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure null_expected is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(interval '1' second).of_(to_date(null));
+ --Assert
+ l_expected_message := q'[Actual: % (date) was expected to be within 1 second of NULL (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure null_actual_and_expected is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(to_date(null)).to_be_within(interval '1' second).of_(to_date(null));
+ --Assert
+ l_expected_message := q'[Actual: NULL (date) was expected to be within 1 second of NULL (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure null_actual is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(to_date(null)).to_be_within(interval '1' second).of_(sysdate);
+ --Assert
+ l_expected_message := q'[Actual: NULL (date) was expected to be within 1 second of % (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+
+ procedure null_distance is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(cast(null as interval day to second)).of_(sysdate);
+ --Assert
+ l_expected_message := q'[Actual: % (date) was expected to be within NULL of % (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+
+ procedure invalid_distance_for_number is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(2).to_be_within(interval '1' second).of_(1);
+ --Assert
+ l_expected_message := q'[Matcher 'be within' cannot be used to compare Actual (number) with Expected (number) using distance (interval day to second).]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+
+ procedure invalid_distance_for_timestamp is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(sysdate).to_be_within(1).of_(sysdate);
+ --Assert
+ l_expected_message := q'[Matcher 'be within' cannot be used to compare Actual (date) with Expected (date) using distance (number).]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+ procedure failure_on_tiny_time_diff is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(timestamp'2022-01-29 23:23:23.000000009').to_be_within(interval '0.000000001' second).of_(timestamp'2022-01-29 23:23:23.000000001');
+ --Assert
+ l_expected_message := q'[Actual: 2022-01-29T23:23:23.000000009 (timestamp) was expected to be within .000000001 seconds of 2022-01-29T23:23:23.000000001 (timestamp)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+
+ procedure failure_on_large_years_compare is
+ l_actual_message varchar2(32767);
+ l_expected_message varchar2(32767);
+ begin
+ --Act
+ ut3_develop.ut.expect(to_date('-4000-01-01','syyyy-mm-dd')).to_be_within(interval '9990' year).of_(date '9999-12-31');
+ --Assert
+ l_expected_message := q'[Actual: -4000-01-01T00:00:00 (date) was expected to be within 9990 years of 9999-12-31T00:00:00 (date)]';
+ l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ --Assert
+ ut.expect(l_actual_message).to_be_like(l_expected_message);
+ end;
+
+end;
+/
diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pks b/test/ut3_user/expectations/binary/test_to_be_within.pks
new file mode 100644
index 000000000..966e9baaf
--- /dev/null
+++ b/test/ut3_user/expectations/binary/test_to_be_within.pks
@@ -0,0 +1,61 @@
+create or replace package test_to_be_within is
+
+ --%suite((not)to_be_within)
+ --%suitepath(utplsql.test_user.expectations.binary)
+
+ --%aftereach
+ procedure cleanup_expectations;
+
+ --%test(gives success for values within a distance)
+ procedure success_tests;
+
+ --%test(gives failure when value is not within distance)
+ procedure failed_tests;
+
+ --%test(returns well formatted failure message when expectation fails)
+ procedure fail_for_number_not_within;
+
+ --%test(returns well formatted failure message for inteval of 1 sec not within)
+ procedure fail_for_ds_int_not_within;
+
+ --%test(returns well formatted failure message for custom ds interval not within)
+ procedure fail_for_custom_ds_int;
+
+ --%test(returns well formatted failure message for inteval of 1 month not within)
+ procedure fail_for_ym_int_not_within;
+
+ --%test(returns well formatted failure message for custom ym interval not within)
+ procedure fail_for_custom_ym_int;
+
+ --%test(returns well formatted failure message for simple within)
+ procedure fail_msg_when_not_within;
+
+ --%test(returns well formatted failure message when comparing different datatypes)
+ procedure fail_msg_wrong_types;
+
+ --%test(failure on null expected value)
+ procedure null_expected;
+
+ --%test(failure on null actual value)
+ procedure null_actual;
+
+ --%test(failure on null expected and actual value)
+ procedure null_actual_and_expected;
+
+ --%test(failure on null distance value)
+ procedure null_distance;
+
+ --%test(failure on invalid distance datatype for number expected)
+ procedure invalid_distance_for_number;
+
+ --%test(failure on invalid distance datatype for timestamp expected)
+ procedure invalid_distance_for_timestamp;
+
+ --%test(failure on exceeding difference in day second time by nanosecond)
+ procedure failure_on_tiny_time_diff;
+
+ --%test(failure when comparing very large year difference)
+ procedure failure_on_large_years_compare;
+
+end;
+/
diff --git a/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb b/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb
new file mode 100644
index 000000000..da634d90e
--- /dev/null
+++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb
@@ -0,0 +1,221 @@
+create or replace package body test_to_be_within_pct is
+
+ procedure cleanup_expectations is
+ begin
+ ut3_tester_helper.main_helper.clear_expectations( );
+ end;
+
+ function be_within_expectation_block(
+ a_matcher varchar2,
+ a_actual_type varchar2,
+ a_actual varchar2,
+ a_expected_type varchar2,
+ a_expected varchar2,
+ a_distance varchar2,
+ a_distance_type varchar2,
+ a_matcher_end varchar2
+ ) return varchar2
+ is
+ l_execute varchar2(32000);
+ begin
+ l_execute := '
+ declare
+ l_actual '||a_actual_type||' := '||a_actual||';
+ l_expected '||a_expected_type||' := '||a_expected||';
+ l_distance '||a_distance_type||' := '||a_distance||';
+ begin
+ --act - execute the expectation
+ ut3_develop.ut.expect( l_actual ).'||a_matcher||'( l_distance ).of_( l_expected )'||a_matcher_end||';
+ end;';
+ return l_execute;
+ end;
+
+ procedure test_to_be_within_fail(
+ a_matcher varchar2,
+ a_actual_type varchar2,
+ a_actual varchar2,
+ a_expected_type varchar2,
+ a_expected varchar2,
+ a_distance varchar2,
+ a_distance_type varchar2,
+ a_failure_message varchar2 := null,
+ a_matcher_end varchar2 := null
+ ) is
+ l_failure_text varchar2(4000);
+ begin
+ execute immediate be_within_expectation_block(
+ a_matcher,a_actual_type, a_actual, a_expected_type, a_expected,
+ a_distance,a_distance_type, a_matcher_end
+ );
+ ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(1);
+ if a_failure_message is not null then
+ l_failure_text := ut3_tester_helper.main_helper.get_failed_expectations(1);
+ ut.expect( l_failure_text ).to_be_like('%'||a_failure_message||'%' );
+ end if;
+ cleanup_expectations;
+ end;
+
+ procedure test_to_be_within_success(
+ a_matcher varchar2,
+ a_actual_type varchar2,
+ a_actual varchar2,
+ a_expected_type varchar2,
+ a_expected varchar2,
+ a_distance varchar2,
+ a_distance_type varchar2,
+ a_matcher_end varchar2 := null
+ ) is
+ begin
+ execute immediate be_within_expectation_block(
+ a_matcher,a_actual_type, a_actual, a_expected_type, a_expected,
+ a_distance,a_distance_type, a_matcher_end
+ );
+ ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0);
+ cleanup_expectations;
+ end;
+
+
+ procedure test_to_be_within_error(
+ a_matcher varchar2,
+ a_actual_type varchar2,
+ a_actual varchar2,
+ a_expected_type varchar2,
+ a_expected varchar2,
+ a_distance varchar2,
+ a_distance_type varchar2,
+ a_error_message varchar2,
+ a_matcher_end varchar2 := null
+ ) is
+ begin
+ execute immediate be_within_expectation_block(
+ a_matcher,a_actual_type, a_actual, a_expected_type, a_expected,
+ a_distance,a_distance_type, a_matcher_end
+ );
+ cleanup_expectations;
+ ut.fail('Expected exception but nothing was raised');
+ exception
+ when others then
+ ut.expect(sqlerrm).to_be_like('%'||a_error_message||'%');
+ cleanup_expectations;
+ end;
+
+
+ procedure expect_success is
+ begin
+ ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0);
+ cleanup_expectations;
+ end;
+
+ procedure expect_failure is
+ begin
+ ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(1);
+ cleanup_expectations;
+ end;
+
+ procedure success_tests is
+ begin
+ ut3_develop.ut.expect( 1 ).to_be_within_pct( 0.01 ).of_(1.0001);
+ expect_success;
+
+ ut3_develop.ut.expect( 1.0001 ).to_( ut3_develop.be_within_pct( 0.01 ).of_(1) );
+ expect_success;
+
+ ut3_develop.ut.expect( 1.0002 ).not_to_be_within_pct( 0.01 ).of_(1);
+ expect_success;
+
+ ut3_develop.ut.expect( 1 ).not_to( ut3_develop.be_within_pct( 0.01 ).of_(1.0002) );
+ expect_success;
+
+ ut3_develop.ut.expect( 1.0001 ).to_be_within_pct( -0.01 ).of_(1);
+ expect_success;
+
+ ut3_develop.ut.expect( 1 ).to_( ut3_develop.be_within_pct( -0.01 ).of_(1.0001) );
+ expect_success;
+
+ ut3_develop.ut.expect( 1.00000001 ).not_to_be_within_pct( 0 ).of_(1);
+ expect_success;
+
+ ut3_develop.ut.expect( 0 ).not_to( ut3_develop.be_within_pct( 0.01 ).of_(0.000001) );
+ expect_success;
+
+ ut3_develop.ut.expect( 0 ).to_be_within_pct( 0 ).of_( 0 );
+ expect_success;
+
+ ut3_develop.ut.expect( 0 ).to_be_within_pct( 100 ).of_( 1 );
+ expect_success;
+
+ ut3_develop.ut.expect( -1 ).to_be_within_pct( 200 ).of_( 1 );
+ expect_success;
+ end;
+
+ procedure failed_tests is
+ begin
+ ut3_develop.ut.expect( 1 ).not_to_be_within_pct( 0.01 ).of_(1.0001);
+ expect_failure;
+
+ ut3_develop.ut.expect( 1.0001 ).not_to( ut3_develop.be_within_pct( 0.01 ).of_(1) );
+ expect_failure;
+
+ ut3_develop.ut.expect( 1.0002 ).to_be_within_pct( 0.01 ).of_(1);
+ expect_failure;
+
+ ut3_develop.ut.expect( 1 ).to_( ut3_develop.be_within_pct( 0.01 ).of_(1.0002) );
+ expect_failure;
+
+ ut3_develop.ut.expect( 1.0001 ).not_to_be_within_pct( -0.01 ).of_(1);
+ expect_failure;
+
+ ut3_develop.ut.expect( 1 ).not_to( ut3_develop.be_within_pct( -0.01 ).of_(1.0001) );
+ expect_failure;
+
+ ut3_develop.ut.expect( 1.00000001 ).to_be_within_pct( 0 ).of_(1);
+ expect_failure;
+
+ ut3_develop.ut.expect( 0 ).to_( ut3_develop.be_within_pct( 0.01 ).of_(0.000001) );
+ expect_failure;
+
+ ut3_develop.ut.expect( 0 ).not_to_be_within_pct( 0 ).of_( 0 );
+ expect_failure;
+
+ ut3_develop.ut.expect( 0 ).not_to_be_within_pct( 100 ).of_( 1 );
+ expect_failure;
+
+ ut3_develop.ut.expect( -1 ).not_to_be_within_pct( 200 ).of_( 1 );
+ expect_failure;
+ end;
+
+ procedure fail_for_number_not_within is
+ begin
+ test_to_be_within_fail(
+ 'to_be_within_pct','number', '4', 'number','7',
+ '1','number',
+ q'[Actual: 4 (number) was expected to be within 1 % of 7 (number)]'
+ );
+ end;
+
+ procedure fail_at_invalid_argument_types is
+ begin
+ test_to_be_within_error(
+ 'to_be_within_pct','date', 'sysdate', 'date','sysdate',
+ '''0 0:00:11.333''','interval day to second',
+ 'wrong number or types of arguments in call to ''TO_BE_WITHIN_PCT'''
+ );
+ test_to_be_within_error(
+ 'to_be_within_pct','number','1', 'date', 'sysdate',
+ '1','number',
+ ' wrong number or types of arguments in call to ''OF_'''
+ );
+ test_to_be_within_error(
+ 'to_be_within_pct','number','1','number','1',
+ 'sysdate', 'date',
+ ' wrong number or types of arguments in call to ''TO_BE_WITHIN_PCT'''
+ );
+ test_to_be_within_fail(
+ 'to_be_within_pct','date', 'sysdate', 'number','1',
+ '1','number',
+ 'Matcher ''be within pct'' cannot be used to compare Actual (date) with Expected (number) using distance (number).'
+ );
+ end;
+
+end;
+/
diff --git a/test/ut3_user/expectations/binary/test_to_be_within_pct.pks b/test/ut3_user/expectations/binary/test_to_be_within_pct.pks
new file mode 100644
index 000000000..4b8f0cb4c
--- /dev/null
+++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pks
@@ -0,0 +1,22 @@
+create or replace package test_to_be_within_pct is
+
+ --%suite((not)to_be_within_pct)
+ --%suitepath(utplsql.test_user.expectations.binary)
+
+ --%aftereach
+ procedure cleanup_expectations;
+
+ --%test(gives success for values within a distance)
+ procedure success_tests;
+
+ --%test(gives failure when number is not within distance)
+ procedure failed_tests;
+
+ --%test(returns well formatted failure message when expectation fails)
+ procedure fail_for_number_not_within;
+
+ --%test(fails at compile or run time for unsupported data-types )
+ procedure fail_at_invalid_argument_types;
+
+end;
+/
diff --git a/test/ut3_user/expectations/test_expectations_cursor.pkb b/test/ut3_user/expectations/test_expectations_cursor.pkb
index f06132009..409c81ace 100644
--- a/test/ut3_user/expectations/test_expectations_cursor.pkb
+++ b/test/ut3_user/expectations/test_expectations_cursor.pkb
@@ -336,7 +336,7 @@ create or replace package body test_expectations_cursor is
open l_expected for select 1 as col_1, 2 as col_2 from dual;
open l_actual for select 2 as col_2, 1 as col_1 from dual;
--Act
- ut3_develop.ut.expect( l_actual ).to_equal( l_expected ).unordered_columns;
+ ut3_develop.ut.expect( l_actual ).to_( ut3_develop.equal( l_expected ).unordered_columns() );
--Assert
ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0);
end;
@@ -350,7 +350,7 @@ create or replace package body test_expectations_cursor is
open l_expected for select 1 as col_1, 2 as col_2 from dual;
open l_actual for select 2 as col_2, 1 as col_1 from dual;
--Act
- ut3_develop.ut.expect( l_actual ).to_equal( l_expected ).uc;
+ ut3_develop.ut.expect( l_actual ).to_( ut3_develop.equal( l_expected ).uc() );
--Assert
ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0);
end;
@@ -592,7 +592,7 @@ create or replace package body test_expectations_cursor is
open l_actual for select rownum as rn, 'a' as "A_Column", 'c' as A_COLUMN, 'x' SOME_COL, 'd' "Some_Col" from dual connect by level < 4;
open l_expected for select rownum as rn, 'a' as "A_Column", 'd' as A_COLUMN, 'x' SOME_COL, 'c' "Some_Col" from dual connect by level < 4;
--Act
- ut3_develop.ut.expect(l_actual).to_equal(l_expected).include('/ROW/RN|//A_Column|//SOME_COL');
+ ut3_develop.ut.expect(l_actual).to_( ut3_develop.equal(l_expected).include('/ROW/RN|//A_Column|//SOME_COL') );
--Assert
ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0);
end;
diff --git a/test/ut3_user/expectations/test_expectations_json.pkb b/test/ut3_user/expectations/test_expectations_json.pkb
index 9516ecb04..afc7198a2 100644
--- a/test/ut3_user/expectations/test_expectations_json.pkb
+++ b/test/ut3_user/expectations/test_expectations_json.pkb
@@ -49,7 +49,7 @@ create or replace package body test_expectations_json is
}');
--Act
- ut3_develop.ut.expect( l_actual ).to_equal( l_actual );
+ ut3_develop.ut.expect( l_actual ).to_( ut3_develop.equal( l_actual ) );
--Assert
ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0);
end;
diff --git a/test/ut3_user/reporters/test_debug_reporter.pkb b/test/ut3_user/reporters/test_debug_reporter.pkb
index ed7e14fcf..a022b5af8 100644
--- a/test/ut3_user/reporters/test_debug_reporter.pkb
+++ b/test/ut3_user/reporters/test_debug_reporter.pkb
@@ -21,7 +21,7 @@ create or replace package body test_debug_reporter as
begin
l_expected := '\s+' ||
'(\s+' ||
- '[0-9\-]+T[0-9:\.]+<\/TIMESTAMP>\s+' ||
+ ' [0-9\-]+T[0-9:\.]+<\/TIMESTAMP>\s+' ||
'[0-9 \+:\.]+<\/TIME_FROM_START>\s+' ||
'[0-9 \+:\.]+<\/TIME_FROM_PREVIOUS>\s+' ||
'\w+<\/EVENT_NAME>\s+' ||