From 48abf1a83c36ca44c2f395eceea5473ac99a0221 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 1 Jun 2020 21:58:35 +0100 Subject: [PATCH 01/35] Initial checkin --- source/expectations/matchers/ut_equal.tpb | 7 +++++++ source/expectations/matchers/ut_equal.tps | 3 ++- source/expectations/matchers/ut_matcher.tps | 7 +++---- .../expectations/matchers/ut_matcher_base.tpb | 20 +++++++++++++++++++ .../expectations/matchers/ut_matcher_base.tps | 4 ++++ source/expectations/ut_expectation.tpb | 10 +++++----- source/expectations/ut_expectation.tps | 8 ++++---- .../expectations/ut_expectation_compound.tpb | 5 +++-- .../expectations/ut_expectation_compound.tps | 4 ++-- 9 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 source/expectations/matchers/ut_matcher_base.tpb create mode 100644 source/expectations/matchers/ut_matcher_base.tps diff --git a/source/expectations/matchers/ut_equal.tpb b/source/expectations/matchers/ut_equal.tpb index afa2148f3..4f6fee119 100644 --- a/source/expectations/matchers/ut_equal.tpb +++ b/source/expectations/matchers/ut_equal.tpb @@ -172,6 +172,13 @@ create or replace type body ut_equal as return l_result; end; + member procedure include(self in ut_equal, a_items varchar2) is + --l_result ut_equal := self; + begin + null; + --l_result.expectation.to_(l_result ); + end; + member function exclude(a_items varchar2) return ut_equal is l_result ut_equal := self; begin diff --git a/source/expectations/matchers/ut_equal.tps b/source/expectations/matchers/ut_equal.tps index 1f42324d7..3a2ad6061 100644 --- a/source/expectations/matchers/ut_equal.tps +++ b/source/expectations/matchers/ut_equal.tps @@ -43,6 +43,7 @@ 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 procedure include(self in ut_equal, a_items varchar2), member function include(a_items ut_varchar2_list) return ut_equal, member function exclude(a_items varchar2) return ut_equal, member function exclude(a_items ut_varchar2_list) return ut_equal, @@ -56,4 +57,4 @@ create or replace type ut_equal force under ut_comparison_matcher( member function uc return ut_equal ) not final -/ + diff --git a/source/expectations/matchers/ut_matcher.tps b/source/expectations/matchers/ut_matcher.tps index 34e1742df..b37c06741 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 force under ut_matcher_base( /* utPLSQL - Version 3 Copyright 2016 - 2019 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, /* function: run_matcher @@ -41,4 +40,4 @@ create or replace type ut_matcher authid current_user as object( member function negated return ut_matcher, member function is_negated return boolean ) not final not instantiable -/ + diff --git a/source/expectations/matchers/ut_matcher_base.tpb b/source/expectations/matchers/ut_matcher_base.tpb new file mode 100644 index 000000000..bf3d9a187 --- /dev/null +++ b/source/expectations/matchers/ut_matcher_base.tpb @@ -0,0 +1,20 @@ +create or replace type body ut_matcher_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. + */ + +end; +/ diff --git a/source/expectations/matchers/ut_matcher_base.tps b/source/expectations/matchers/ut_matcher_base.tps new file mode 100644 index 000000000..7c18d35d7 --- /dev/null +++ b/source/expectations/matchers/ut_matcher_base.tps @@ -0,0 +1,4 @@ +create or replace type ut_matcher_base force authid current_user as object( + self_type varchar2(250) +) +not final not instantiable \ No newline at end of file diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index d8ed1f79a..b18e2f7b0 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -15,12 +15,12 @@ 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 + member procedure to_(self in ut_expectation, a_matcher ut_matcher_base) is l_expectation_result boolean; - l_matcher ut_matcher := a_matcher; + l_matcher ut_matcher := treat(a_matcher as ut_matcher); l_message varchar2(32767); begin - if a_matcher.is_negated() then + if l_matcher.is_negated() then self.not_to( a_matcher ); else l_expectation_result := l_matcher.run_matcher( self.actual_data ); @@ -30,9 +30,9 @@ create or replace type body ut_expectation as end if; end; - member procedure not_to(self in ut_expectation, a_matcher ut_matcher) is + member procedure not_to(self in ut_expectation, a_matcher ut_matcher_base) is l_expectation_result boolean; - l_matcher ut_matcher := a_matcher; + 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 ); diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps index 37fefd085..ffaa73981 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 authid current_user as object( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -19,8 +19,8 @@ create or replace type ut_expectation authid current_user as object( 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), + member procedure to_(self in ut_expectation, a_matcher ut_matcher_base), + member procedure not_to(self in ut_expectation, a_matcher ut_matcher_base), --shortcuts member procedure to_be_null(self in ut_expectation), @@ -172,4 +172,4 @@ create or replace type ut_expectation authid current_user as object( ) not final -/ + diff --git a/source/expectations/ut_expectation_compound.tpb b/source/expectations/ut_expectation_compound.tpb index 5e7268bd9..8fc67a5c9 100644 --- a/source/expectations/ut_expectation_compound.tpb +++ b/source/expectations/ut_expectation_compound.tpb @@ -48,11 +48,12 @@ create or replace type body ut_expectation_compound as return l_result; end; - member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_expectation_compound is + member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal is l_result ut_expectation_compound := self; begin l_result.matcher := ut_equal(a_expected, a_nulls_are_equal); - return l_result; + l_result.matcher.expectation := l_result; + return treat(l_result.matcher as ut_equal); end; member function not_to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_expectation_compound is diff --git a/source/expectations/ut_expectation_compound.tps b/source/expectations/ut_expectation_compound.tps index fc413e3fd..ea5f9d30a 100644 --- a/source/expectations/ut_expectation_compound.tps +++ b/source/expectations/ut_expectation_compound.tps @@ -24,7 +24,7 @@ create or replace type ut_expectation_compound force under ut_expectation( 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 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_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, @@ -51,4 +51,4 @@ create or replace type ut_expectation_compound force under ut_expectation( member function uc return ut_expectation_compound, member procedure uc(self in ut_expectation_compound) ) -/ + From 70419127716a0a5e8ad4bad7847f0d16a79af4d7 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 2 Jun 2020 19:46:33 +0100 Subject: [PATCH 02/35] added expectation --- source/expectations/matchers/ut_equal.tpb | 5 ++--- source/expectations/matchers/ut_equal.tps | 4 ++-- source/expectations/matchers/ut_matcher.tps | 4 ++-- .../expectations/matchers/ut_matcher_base.tpb | 20 ------------------- .../expectations/matchers/ut_matcher_base.tps | 3 ++- source/expectations/ut_expectation.tps | 4 ++-- .../expectations/ut_expectation_compound.tpb | 10 +++++----- .../expectations/ut_expectation_compound.tps | 4 ++-- source/install.sql | 3 ++- 9 files changed, 19 insertions(+), 38 deletions(-) delete mode 100644 source/expectations/matchers/ut_matcher_base.tpb diff --git a/source/expectations/matchers/ut_equal.tpb b/source/expectations/matchers/ut_equal.tpb index 4f6fee119..1ac449cf6 100644 --- a/source/expectations/matchers/ut_equal.tpb +++ b/source/expectations/matchers/ut_equal.tpb @@ -173,10 +173,9 @@ create or replace type body ut_equal as end; member procedure include(self in ut_equal, a_items varchar2) is - --l_result ut_equal := self; + l_result ut_equal := self; begin - null; - --l_result.expectation.to_(l_result ); + l_result.expectation.to_(l_result ); end; member function exclude(a_items varchar2) return ut_equal is diff --git a/source/expectations/matchers/ut_equal.tps b/source/expectations/matchers/ut_equal.tps index 3a2ad6061..52f116715 100644 --- a/source/expectations/matchers/ut_equal.tps +++ b/source/expectations/matchers/ut_equal.tps @@ -1,4 +1,4 @@ -create or replace type ut_equal force under ut_comparison_matcher( +create or replace type ut_equal under ut_comparison_matcher( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -57,4 +57,4 @@ create or replace type ut_equal force under ut_comparison_matcher( member function uc return ut_equal ) not final - +/ diff --git a/source/expectations/matchers/ut_matcher.tps b/source/expectations/matchers/ut_matcher.tps index b37c06741..16af94a1a 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 force under ut_matcher_base( +create or replace type ut_matcher under ut_matcher_base( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -40,4 +40,4 @@ create or replace type ut_matcher force under ut_matcher_base( member function negated return ut_matcher, member function is_negated return boolean ) not final not instantiable - +/ diff --git a/source/expectations/matchers/ut_matcher_base.tpb b/source/expectations/matchers/ut_matcher_base.tpb deleted file mode 100644 index bf3d9a187..000000000 --- a/source/expectations/matchers/ut_matcher_base.tpb +++ /dev/null @@ -1,20 +0,0 @@ -create or replace type body ut_matcher_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. - */ - -end; -/ diff --git a/source/expectations/matchers/ut_matcher_base.tps b/source/expectations/matchers/ut_matcher_base.tps index 7c18d35d7..ec37267a0 100644 --- a/source/expectations/matchers/ut_matcher_base.tps +++ b/source/expectations/matchers/ut_matcher_base.tps @@ -1,4 +1,5 @@ create or replace type ut_matcher_base force authid current_user as object( self_type varchar2(250) ) -not final not instantiable \ No newline at end of file +not final not instantiable +/ \ No newline at end of file diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps index ffaa73981..95aeb9fce 100644 --- a/source/expectations/ut_expectation.tps +++ b/source/expectations/ut_expectation.tps @@ -1,4 +1,4 @@ -create or replace type ut_expectation force authid current_user as object( +create or replace type ut_expectation authid current_user as object( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -172,4 +172,4 @@ create or replace type ut_expectation force authid current_user as object( ) not final - +/ diff --git a/source/expectations/ut_expectation_compound.tpb b/source/expectations/ut_expectation_compound.tpb index 8fc67a5c9..674b468b2 100644 --- a/source/expectations/ut_expectation_compound.tpb +++ b/source/expectations/ut_expectation_compound.tpb @@ -48,12 +48,12 @@ create or replace type body ut_expectation_compound as return l_result; end; - member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal 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_matcher; begin - l_result.matcher := ut_equal(a_expected, a_nulls_are_equal); - l_result.matcher.expectation := l_result; - return treat(l_result.matcher as ut_equal); + l_result := ut_equal(a_expected, a_nulls_are_equal); + l_result.expectation := self; + return treat(l_result as ut_equal); end; member function not_to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_expectation_compound is diff --git a/source/expectations/ut_expectation_compound.tps b/source/expectations/ut_expectation_compound.tps index ea5f9d30a..4b2347859 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 - 2019 utPLSQL Project @@ -51,4 +51,4 @@ create or replace type ut_expectation_compound force under ut_expectation( member function uc return ut_expectation_compound, member procedure uc(self in ut_expectation_compound) ) - +/ diff --git a/source/install.sql b/source/install.sql index 253b13fb2..45a67f924 100644 --- a/source/install.sql +++ b/source/install.sql @@ -236,6 +236,8 @@ 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/ut_expectation.tps' +@@install_component.sql 'expectations/matchers/ut_matcher_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_false.tps' @@ -253,7 +255,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' From 13d86b6d74e7aee203625e719640edb04e80551b Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 2 Jun 2020 21:11:00 +0100 Subject: [PATCH 03/35] Adding more methods --- source/expectations/matchers/ut_equal.tpb | 54 +++++++- source/expectations/matchers/ut_equal.tps | 14 +- .../expectations/ut_expectation_compound.tpb | 129 ++---------------- .../expectations/ut_expectation_compound.tps | 29 +--- 4 files changed, 83 insertions(+), 143 deletions(-) diff --git a/source/expectations/matchers/ut_equal.tpb b/source/expectations/matchers/ut_equal.tpb index 1ac449cf6..5eb256c22 100644 --- a/source/expectations/matchers/ut_equal.tpb +++ b/source/expectations/matchers/ut_equal.tpb @@ -173,8 +173,14 @@ create or replace type body ut_equal as 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; @@ -192,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 @@ -199,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 @@ -215,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 52f116715..8701fca94 100644 --- a/source/expectations/matchers/ut_equal.tps +++ b/source/expectations/matchers/ut_equal.tps @@ -1,4 +1,4 @@ -create or replace type ut_equal under ut_comparison_matcher( +create or replace type ut_equal force under ut_comparison_matcher( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -43,18 +43,26 @@ create or replace type ut_equal 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 procedure include(self in ut_equal, a_items varchar2), - member function include(a_items ut_varchar2_list) return ut_equal, + 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/ut_expectation_compound.tpb b/source/expectations/ut_expectation_compound.tpb index 674b468b2..365272b21 100644 --- a/source/expectations/ut_expectation_compound.tpb +++ b/source/expectations/ut_expectation_compound.tpb @@ -34,18 +34,20 @@ 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_matcher; begin - l_result.matcher := ut_equal(a_expected, a_nulls_are_equal); - return l_result; + l_result := ut_equal(a_expected, a_nulls_are_equal); + l_result.expectation := self; + return treat(l_result as ut_equal); 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; + 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 to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal is @@ -56,11 +58,12 @@ create or replace type body ut_expectation_compound as return treat(l_result as ut_equal); 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; + member function not_to_equal(a_expected sys_refcursor, 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; + 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 to_contain(a_expected sys_refcursor) return ut_expectation_compound is @@ -91,107 +94,5 @@ create or replace type body ut_expectation_compound as return l_result; end; - member function include(a_items varchar2) return ut_expectation_compound is - begin - return include( ut_varchar2_list( a_items ) ); - end; - - member function include(a_items ut_varchar2_list) return ut_expectation_compound is - l_result ut_expectation_compound := self; - begin - l_result.matcher := treat(l_result.matcher as ut_equal).include(a_items); - 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 - begin - self.to_( treat(matcher as ut_equal).include(a_items) ); - 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; - begin - l_result.matcher := treat(l_result.matcher as ut_equal).exclude(a_items); - 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 - begin - unordered_columns; - end; - end; / diff --git a/source/expectations/ut_expectation_compound.tps b/source/expectations/ut_expectation_compound.tps index 4b2347859..3aae56670 100644 --- a/source/expectations/ut_expectation_compound.tps +++ b/source/expectations/ut_expectation_compound.tps @@ -22,33 +22,14 @@ create or replace type ut_expectation_compound 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 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_expectation_compound, + 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_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 not_to_contain(a_expected anydata) return ut_expectation_compound ) / + From caeeb30ea4fef1eeeea2283e5c76b717eb9809e3 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 2 Jun 2020 21:30:05 +0100 Subject: [PATCH 04/35] Adding contain and not contain --- .../expectations/ut_expectation_compound.tpb | 38 ++++++++++--------- .../expectations/ut_expectation_compound.tps | 8 ++-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/source/expectations/ut_expectation_compound.tpb b/source/expectations/ut_expectation_compound.tpb index 365272b21..7043ec053 100644 --- a/source/expectations/ut_expectation_compound.tpb +++ b/source/expectations/ut_expectation_compound.tpb @@ -66,32 +66,36 @@ create or replace type body ut_expectation_compound as return treat(l_result as ut_equal); end; - member function to_contain(a_expected sys_refcursor) return ut_expectation_compound is - l_result ut_expectation_compound := self; + member function to_contain(a_expected sys_refcursor) return ut_equal is + l_result ut_matcher; begin - l_result.matcher := ut_contain(a_expected); - return l_result; + l_result := ut_contain(a_expected); + l_result.expectation := self; + return treat(l_result as ut_equal); end; - member function not_to_contain(a_expected sys_refcursor) return ut_expectation_compound is - l_result ut_expectation_compound := self; + member function not_to_contain(a_expected sys_refcursor) return ut_equal is + l_result ut_matcher; begin - l_result.matcher := ut_contain(a_expected).negated(); - return l_result; + l_result := ut_contain(a_expected).negated(); + l_result.expectation := self; + return treat(l_result as ut_equal); end; - - member function to_contain(a_expected anydata) return ut_expectation_compound is - l_result ut_expectation_compound := self; + + member function to_contain(a_expected anydata) return ut_equal is + l_result ut_matcher; begin - l_result.matcher := ut_contain(a_expected); - return l_result; + l_result := ut_contain(a_expected); + 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 not_to_contain(a_expected anydata) return ut_equal is + l_result ut_matcher; begin - l_result.matcher := ut_contain(a_expected).negated(); - return l_result; + l_result := ut_contain(a_expected).negated(); + l_result.expectation := self; + return treat(l_result as ut_equal); end; end; diff --git a/source/expectations/ut_expectation_compound.tps b/source/expectations/ut_expectation_compound.tps index 3aae56670..c840aaf35 100644 --- a/source/expectations/ut_expectation_compound.tps +++ b/source/expectations/ut_expectation_compound.tps @@ -26,10 +26,10 @@ create or replace type ut_expectation_compound under ut_expectation( 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_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 to_contain(a_expected sys_refcursor) return ut_equal, + member function not_to_contain(a_expected sys_refcursor) return ut_equal, + member function to_contain(a_expected anydata) return ut_equal, + member function not_to_contain(a_expected anydata) return ut_equal ) / From 8ff4f6bbf847bab652a1628aa68abc140655d7fe Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 6 Jun 2020 01:16:30 +0100 Subject: [PATCH 05/35] Adding code and tests,. --- source/core/ut_utils.pkb | 25 ++++ source/core/ut_utils.pks | 9 +- .../data_values/ut_data_value_dsinterval.tpb | 2 +- .../data_values/ut_data_value_yminterval.tpb | 2 +- source/expectations/matchers/ut_be_within.tpb | 104 +++++++++++++ source/expectations/matchers/ut_be_within.tps | 38 +++++ source/expectations/matchers/ut_matcher.tps | 2 +- source/expectations/ut_expectation.tpb | 57 +++---- source/expectations/ut_expectation.tps | 16 +- source/expectations/ut_expectation_base.tpb | 44 ++++++ source/expectations/ut_expectation_base.tps | 25 ++++ .../expectations/ut_expectation_compound.tps | 1 + source/install.sql | 6 +- test/install_ut3_user_tests.sql | 2 + .../ut3_tester_helper/expectations_helper.pkb | 26 +++- .../ut3_tester_helper/expectations_helper.pks | 10 ++ .../expectations/binary/test_to_be_within.pkb | 141 ++++++++++++++++++ .../expectations/binary/test_to_be_within.pks | 31 ++++ 18 files changed, 501 insertions(+), 40 deletions(-) create mode 100644 source/expectations/matchers/ut_be_within.tpb create mode 100644 source/expectations/matchers/ut_be_within.tps create mode 100644 source/expectations/ut_expectation_base.tpb create mode 100644 source/expectations/ut_expectation_base.tps create mode 100644 test/ut3_user/expectations/binary/test_to_be_within.pkb create mode 100644 test/ut3_user/expectations/binary/test_to_be_within.pks diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index ba98763e0..8e96870d9 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -877,5 +877,30 @@ 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 > 0 then l_day ||' day' else null end; + l_result := l_result || case when l_hour > 0 then ' '|| l_hour ||' hour' else null end; + l_result := l_result || case when l_minute> 0 then ' '||l_minute ||' minute' else null end; + l_result := l_result || case when l_second > 0 then ' '||l_second ||' second' else null end; + return trim(leading ' ' from 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 > 0 then l_year ||' year' else null end; + l_result := l_result || case when l_month > 0 then ' '||l_month ||' month' else null end; + return trim(leading ' ' from l_result); + end; + + end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 6ed6c4ac9..750b17a77 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -434,6 +434,13 @@ 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; + + function interval_to_text(a_interval yminterval_unconstrained) return varchar2; + end ut_utils; / diff --git a/source/expectations/data_values/ut_data_value_dsinterval.tpb b/source/expectations/data_values/ut_data_value_dsinterval.tpb index ff9d5fe1e..e55b2fb17 100644 --- a/source/expectations/data_values/ut_data_value_dsinterval.tpb +++ b/source/expectations/data_values/ut_data_value_dsinterval.tpb @@ -31,7 +31,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_yminterval.tpb b/source/expectations/data_values/ut_data_value_yminterval.tpb index 6d6a05b4a..225406756 100644 --- a/source/expectations/data_values/ut_data_value_yminterval.tpb +++ b/source/expectations/data_values/ut_data_value_yminterval.tpb @@ -31,7 +31,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/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb new file mode 100644 index 000000000..0832b4946 --- /dev/null +++ b/source/expectations/matchers/ut_be_within.tpb @@ -0,0 +1,104 @@ +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. + */ + + member procedure init(self in out nocopy ut_be_within, a_dist ut_data_value, a_is_pct number , a_self_type varchar2 := null) is + begin + self.dist := a_dist; + self.is_pct := nvl(a_is_pct,0); + self.self_type := nvl( a_self_type, $$plsql_unit ); + end; + + constructor function ut_be_within(self in out nocopy ut_be_within, a_dist number, a_is_pct number) return self as result is + begin + init(ut_data_value_number(a_dist),a_is_pct); + return; + end; + + constructor function ut_be_within(self in out nocopy ut_be_within, a_dist dsinterval_unconstrained, a_is_pct number) return self as result is + begin + init(ut_data_value_dsinterval(a_dist),a_is_pct); + return; + end; + + constructor function ut_be_within(self in out nocopy ut_be_within, a_dist yminterval_unconstrained, a_is_pct number) return self as result is + begin + init(ut_data_value_yminterval(a_dist),a_is_pct); + return; + end; + + member procedure of_(self in ut_be_within, a_expected number) is + l_result ut_be_within := self; + begin + l_result.expected := ut_data_value_number(a_expected); + l_result.expectation.to_(l_result ); + 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); + l_result.expectation.to_(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 then + if self.expected is of (ut_data_value_number) and self.is_pct = 0 then + l_result := abs((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value)) <= treat(self.dist as ut_data_value_number).data_value; + elsif self.expected is of (ut_data_value_number) and self.is_pct = 1 then + l_result := treat(self.dist as ut_data_value_number).data_value >= ((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / + (treat(self.expected as ut_data_value_number).data_value) ; + elsif self.expected is of (ut_data_value_date) and self.dist is of ( ut_data_value_yminterval) then + l_result := treat(a_actual as ut_data_value_date).data_value between (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_yminterval).data_value + and (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_yminterval).data_value; + elsif self.expected is of (ut_data_value_date) and self.dist is of ( ut_data_value_dsinterval) then + l_result := treat(a_actual as ut_data_value_date).data_value between (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_dsinterval).data_value + and (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_dsinterval).data_value; + 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 + l_distance varchar2(32767); + begin + l_distance := case + when self.dist is of (ut_data_value_number) then + treat(self.dist as ut_data_value_number).to_string + when self.dist is of (ut_data_value_yminterval) then + treat(self.dist as ut_data_value_yminterval).to_string + when self.dist is of (ut_data_value_dsinterval) then + treat(self.dist as ut_data_value_dsinterval).to_string + else + null + end; + + return (self as ut_matcher).failure_message(a_actual) || ' '||l_distance ||' of '|| expected.to_string_report(); + end; + + overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2 is + l_result varchar2(32767); + begin + return (self as ut_matcher).failure_message_when_negated(a_actual) || ': '|| expected.to_string_report(); + end; + +end; +/ \ No newline at end of file diff --git a/source/expectations/matchers/ut_be_within.tps b/source/expectations/matchers/ut_be_within.tps new file mode 100644 index 000000000..30947d2aa --- /dev/null +++ b/source/expectations/matchers/ut_be_within.tps @@ -0,0 +1,38 @@ +create or replace type ut_be_within 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 + */ + dist ut_data_value, + is_pct number(1,0), + + member procedure init(self in out nocopy ut_be_within, a_dist ut_data_value, a_is_pct number , a_self_type varchar2 := null), + constructor function ut_be_within(self in out nocopy ut_be_within, a_dist number, a_is_pct number) return self as result, + constructor function ut_be_within(self in out nocopy ut_be_within, a_dist dsinterval_unconstrained, a_is_pct number) return self as result, + constructor function ut_be_within(self in out nocopy ut_be_within, a_dist yminterval_unconstrained, a_is_pct number) return self as result, + member procedure of_(self in ut_be_within, a_expected number), + member procedure of_(self in ut_be_within, a_expected date), + + 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 +/ \ No newline at end of file diff --git a/source/expectations/matchers/ut_matcher.tps b/source/expectations/matchers/ut_matcher.tps index 16af94a1a..75231d4f3 100644 --- a/source/expectations/matchers/ut_matcher.tps +++ b/source/expectations/matchers/ut_matcher.tps @@ -17,7 +17,7 @@ create or replace type ut_matcher under ut_matcher_base( */ is_errored integer, is_negated_flag number(1,0), - expectation ut_expectation, + expectation ut_expectation_base, /* function: run_matcher diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index b18e2f7b0..288c6cf19 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_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, 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; member procedure to_be_null(self in ut_expectation) is begin @@ -719,5 +694,37 @@ create or replace type body ut_expectation as self.not_to( ut_contain(a_expected).negated() ); end; + member function to_be_within(a_dist natural) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,0); + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,0); + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function to_be_within(a_dist yminterval_unconstrained) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,0); + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function to_be_within_pct(a_dist natural) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,1); + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + end; / diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps index 95aeb9fce..b45141b5c 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 under ut_expectation_base( /* utPLSQL - Version 3 Copyright 2016 - 2019 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_base), - member procedure not_to(self in ut_expectation, a_matcher ut_matcher_base), - + --shortcuts member procedure to_be_null(self in ut_expectation), member procedure to_be_not_null(self in ut_expectation), @@ -168,8 +162,12 @@ 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 natural) 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 natural) return ut_be_within ) not final / diff --git a/source/expectations/ut_expectation_base.tpb b/source/expectations/ut_expectation_base.tpb new file mode 100644 index 000000000..d657c2822 --- /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; +/ \ No newline at end of file diff --git a/source/expectations/ut_expectation_base.tps b/source/expectations/ut_expectation_base.tps new file mode 100644 index 000000000..87c0083b0 --- /dev/null +++ b/source/expectations/ut_expectation_base.tps @@ -0,0 +1,25 @@ +create or replace type ut_expectation_base force 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 +/ \ No newline at end of file diff --git a/source/expectations/ut_expectation_compound.tps b/source/expectations/ut_expectation_compound.tps index c840aaf35..a2c06ce76 100644 --- a/source/expectations/ut_expectation_compound.tps +++ b/source/expectations/ut_expectation_compound.tps @@ -33,3 +33,4 @@ create or replace type ut_expectation_compound under ut_expectation( ) / + diff --git a/source/install.sql b/source/install.sql index 45a67f924..911760a63 100644 --- a/source/install.sql +++ b/source/install.sql @@ -236,10 +236,12 @@ 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/ut_expectation.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.tps' +@@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' @@ -294,11 +296,13 @@ 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.tpb' @@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' diff --git a/test/install_ut3_user_tests.sql b/test/install_ut3_user_tests.sql index 05f2634e8..1330a7f75 100644 --- a/test/install_ut3_user_tests.sql +++ b/test/install_ut3_user_tests.sql @@ -25,6 +25,7 @@ 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/test_matchers.pks @@ut3_user/expectations/test_expectation_anydata.pks @@ut3_user/expectations/test_expectations_cursor.pks @@ -66,6 +67,7 @@ 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/test_matchers.pkb @@ut3_user/expectations/test_expectation_anydata.pkb @@ut3_user/expectations/test_expectations_cursor.pkb diff --git a/test/ut3_tester_helper/expectations_helper.pkb b/test/ut3_tester_helper/expectations_helper.pkb index c5c1f379f..7714e1ea3 100644 --- a/test/ut3_tester_helper/expectations_helper.pkb +++ b/test/ut3_tester_helper/expectations_helper.pkb @@ -1,4 +1,4 @@ -create or replace package body expectations_helper is +create or replace package body ut3_tester_helper.expectations_helper is function unary_expectation_block( a_matcher_name varchar2, @@ -53,5 +53,29 @@ create or replace package body expectations_helper is return l_execute; 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 + ) 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); + end;'; + return l_execute; + end; + end; / diff --git a/test/ut3_tester_helper/expectations_helper.pks b/test/ut3_tester_helper/expectations_helper.pks index 9c1d54333..3b0a754d2 100644 --- a/test/ut3_tester_helper/expectations_helper.pks +++ b/test/ut3_tester_helper/expectations_helper.pks @@ -21,5 +21,15 @@ create or replace package expectations_helper is a_expected_data varchar2 ) return varchar2; + 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 + ) return varchar2; + end; / 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..eb4f2da68 --- /dev/null +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -0,0 +1,141 @@ +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_data_type varchar2, + a_actual varchar2, + a_expected varchar2, + a_distance varchar2, + a_distance_data_type varchar2 + ) return varchar2 is + begin + return ut3_tester_helper.expectations_helper.be_within_expectation_block( + a_matcher_name, a_data_type, a_actual, a_data_type, a_expected,a_distance,a_distance_data_type + ); + 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 + ) is + begin + execute immediate be_within_expectation_block(a_matcher_name,a_data_type, a_actual, a_expected,a_distance,a_distance_data_type); + 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 + ) is + begin + execute immediate be_within_expectation_block(a_matcher_name,a_data_type, a_actual, a_expected,a_distance,a_distance_data_type); + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).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'); + 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'); + 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_interval_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_interval_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 '2 3:04:11.333' DAY TO SECOND).of_(sysdate+100); + --Assert + l_expected_message := q'[Actual: % (date) was expected to be within 2 day 3 hour 4 minute 11.333 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_ym_interval_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_interval_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-3' YEAR TO MONTH).of_(sysdate+720); + --Assert + l_expected_message := q'[Actual: % (date) was expected to be within 1 year 3 month % (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; +/ \ No newline at end of file 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..259a80915 --- /dev/null +++ b/test/ut3_user/expectations/binary/test_to_be_within.pks @@ -0,0 +1,31 @@ +create or replace package test_to_be_within is + + --%suite((not)to_be_less_or_equal) + --%suitepath(utplsql.test_user.expectations.binary) + + --%aftereach + procedure cleanup_expectations; + + --%test(Gives failure when number is not within positive distance) + procedure success_tests; + + --%test(Gives failure when number is not within negative distance) + procedure failed_tests; + + --%test(Check failure message for number not within) + procedure fail_for_number_not_within; + + --%test(Check failure message for inteval of 1 sec not within) + procedure fail_for_ds_interval_not_within; + + --%test(Check failure message for custom ds interval not within) + procedure fail_for_custom_ds_interval_not_within; + + --%test(Check failure message for inteval of 1 month not within) + procedure fail_for_ym_interval_not_within; + + --%test(Check failure message for custom ym interval not within) + procedure fail_for_custom_ym_interval_not_within; + +end; +/ \ No newline at end of file From 89cb0bcfef59e838e493482d00427a750b5c27a9 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 6 Jun 2020 02:00:39 +0100 Subject: [PATCH 06/35] Fixingtoo long names --- docs/userguide/expectations.md | 12 ++++++++++++ .../expectations/binary/test_to_be_within.pkb | 8 ++++---- .../expectations/binary/test_to_be_within.pks | 8 ++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 5924be80f..0d8893ba4 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -333,6 +333,7 @@ The matrix below illustrates the data types supported by different matchers. | **be_like** | | | X | | | | | | X | | | | | | | | **be_empty** | X | | X | | | | | | | | | X | X | | X | | **have_count** | | | | | | | | | | | | X | X | | X | +| **be_within().of_()** | | | | x | x | | | | | | | X | X | | X | # Expecting exceptions @@ -1093,6 +1094,17 @@ SUCCESS DEF ``` +## to_be_within of + +This fuzzy matcher is designed to allow user to compare a numbers and dates within distance of error. + +We are allowing a numbers to be compared within a absolute distance from other number of within a percentage calculated based on expected value. + +When comparing a date a distance is measured in interval. + + + + ## Comparing cursors, object types, nested tables and varrays diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index eb4f2da68..727ebbc03 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -81,7 +81,7 @@ create or replace package body test_to_be_within is ut.expect(l_actual_message).to_be_like(l_expected_message); end; - procedure fail_for_ds_interval_not_within is + procedure fail_for_number_not_within is l_actual_message varchar2(32767); l_expected_message varchar2(32767); begin @@ -95,7 +95,7 @@ create or replace package body test_to_be_within is ut.expect(l_actual_message).to_be_like(l_expected_message); end; - procedure fail_for_custom_ds_interval_not_within is + procedure fail_for_custom_ds_int is l_actual_message varchar2(32767); l_expected_message varchar2(32767); begin @@ -109,7 +109,7 @@ create or replace package body test_to_be_within is ut.expect(l_actual_message).to_be_like(l_expected_message); end; - procedure fail_for_ym_interval_not_within is + procedure fail_for_ym_int_not_within is l_actual_message varchar2(32767); l_expected_message varchar2(32767); begin @@ -123,7 +123,7 @@ create or replace package body test_to_be_within is ut.expect(l_actual_message).to_be_like(l_expected_message); end; - procedure fail_for_custom_ym_interval_not_within is + procedure fail_for_custom_ym_int is l_actual_message varchar2(32767); l_expected_message varchar2(32767); begin diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pks b/test/ut3_user/expectations/binary/test_to_be_within.pks index 259a80915..5c042bd53 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pks +++ b/test/ut3_user/expectations/binary/test_to_be_within.pks @@ -16,16 +16,16 @@ create or replace package test_to_be_within is procedure fail_for_number_not_within; --%test(Check failure message for inteval of 1 sec not within) - procedure fail_for_ds_interval_not_within; + procedure fail_for_ds_int_not_within; --%test(Check failure message for custom ds interval not within) - procedure fail_for_custom_ds_interval_not_within; + procedure fail_for_custom_ds_int; --%test(Check failure message for inteval of 1 month not within) - procedure fail_for_ym_interval_not_within; + procedure fail_for_ym_int_not_within; --%test(Check failure message for custom ym interval not within) - procedure fail_for_custom_ym_interval_not_within; + procedure fail_for_custom_ym_int; end; / \ No newline at end of file From a5481ac993f3fd4951a40c1a14ff44b05452045d Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 6 Jun 2020 02:21:16 +0100 Subject: [PATCH 07/35] fixing issue --- test/ut3_user/expectations/binary/test_to_be_within.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index 727ebbc03..b4c727a34 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -81,7 +81,7 @@ create or replace package body test_to_be_within is ut.expect(l_actual_message).to_be_like(l_expected_message); end; - procedure fail_for_number_not_within is + procedure fail_for_ds_int_not_within is l_actual_message varchar2(32767); l_expected_message varchar2(32767); begin From 9ee0e75cfa6f3e8cfef95e7f47d54f62c1990d93 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 7 Jun 2020 14:34:48 +0100 Subject: [PATCH 08/35] Update documentation and tests --- docs/userguide/expectations.md | 76 ++++++++++++++++++- source/core/ut_utils.pkb | 40 ++++++++-- source/expectations/matchers/ut_be_within.tpb | 23 ++++-- test/ut3_tester/core/test_ut_utils.pkb | 57 ++++++++++++++ test/ut3_tester/core/test_ut_utils.pks | 29 +++++++ .../expectations/binary/test_to_be_within.pkb | 4 +- 6 files changed, 211 insertions(+), 18 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 0d8893ba4..4e93f0be1 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1096,15 +1096,85 @@ SUCCESS ## to_be_within of -This fuzzy matcher is designed to allow user to compare a numbers and dates within distance of error. +This matcher is created to determine wheter expected value is approximately equal or "close" to another value. -We are allowing a numbers to be compared within a absolute distance from other number of within a percentage calculated based on expected value. +Matcher will allow to compare numbers as well as dates. -When comparing a date a distance is measured in interval. +When comparing a number the tolerance / distance can be expressed as another postive number or a percentage. +When comparing a two dates tolerance can be expressed in interval time either Day-To-Second or Year-To-Month. +Matcher for numbers will calculate a absolute distance between expected and actual and check whether that value is within a tolerance. +When comparing a date a distance is measured in interval, the check is done that actual value is within date range of expected taking into account interval plus and minus. +**Example 1.** +```sql +begin + ut.expect(3).to_be_within(1).of_(4); +end; +/ +``` + +**Example 2.** +```sql +begin + ut.expect(9).to_be_within_pct(10).of_(10); +end; +/ +``` + +**Example 3.** +```sql +begin + ut.expect(sysdate).to_be_within_pct(interval '1' day).of_(sysdate + 1); +end; +/ +``` + +**Example 4.** +```sql +begin + ut.expect(sysdate).to_be_within_pct(interval '1' month).of_(add_months(sysdate,1)); +end; +/ +``` + +**Example 5.** +```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 6.** +```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 +``` ## Comparing cursors, object types, nested tables and varrays diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 8e96870d9..4b6c66d95 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -884,10 +884,29 @@ create or replace package body ut_utils is l_second varchar2(100) := extract(second from a_interval); l_result varchar2(32767); begin - l_result := case when l_day > 0 then l_day ||' day' else null end; - l_result := l_result || case when l_hour > 0 then ' '|| l_hour ||' hour' else null end; - l_result := l_result || case when l_minute> 0 then ' '||l_minute ||' minute' else null end; - l_result := l_result || case when l_second > 0 then ' '||l_second ||' second' else null end; + l_result := case + when l_day = 1 then l_day ||' day' + when l_day > 1 then l_day ||' days' + else null + end; + l_result := l_result || + case + when l_hour = 1 then ' '|| l_hour ||' hour' + when l_hour > 1 then ' '|| l_hour ||' hours' + else null + end; + l_result := l_result || + case + when l_minute = 1 then ' '||l_minute ||' minute' + when l_minute > 1 then ' '||l_minute ||' minutes' + else null + end; + l_result := l_result || + case + when l_second = 1 then ' '||l_second ||' second' + when l_second > 1 then ' '||l_second ||' seconds' + else null + end; return trim(leading ' ' from l_result); end; @@ -896,8 +915,17 @@ create or replace package body ut_utils is l_month varchar2(20) := extract(month from a_interval); l_result varchar2(32767); begin - l_result := case when l_year > 0 then l_year ||' year' else null end; - l_result := l_result || case when l_month > 0 then ' '||l_month ||' month' else null end; + l_result := case + when l_year = 1 then l_year ||' year' + when l_year > 1 then l_year ||' years' + else null + end; + l_result := l_result || + case + when l_month = 1 then ' '||l_month ||' month' + when l_month > 1 then ' '||l_month ||' months' + else null + end; return trim(leading ' ' from l_result); end; diff --git a/source/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index 0832b4946..ab4ed8b6f 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -60,16 +60,25 @@ create or replace type body ut_be_within as begin if self.expected.data_type = a_actual.data_type then if self.expected is of (ut_data_value_number) and self.is_pct = 0 then - l_result := abs((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value)) <= treat(self.dist as ut_data_value_number).data_value; + l_result := abs((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value)) <= + treat(self.dist as ut_data_value_number).data_value; elsif self.expected is of (ut_data_value_number) and self.is_pct = 1 then - l_result := treat(self.dist as ut_data_value_number).data_value >= ((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / - (treat(self.expected as ut_data_value_number).data_value) ; + l_result := treat(self.dist as ut_data_value_number).data_value >= + ( + ((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / + (treat(self.expected as ut_data_value_number).data_value)) ; elsif self.expected is of (ut_data_value_date) and self.dist is of ( ut_data_value_yminterval) then - l_result := treat(a_actual as ut_data_value_date).data_value between (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_yminterval).data_value - and (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_yminterval).data_value; + l_result := treat(a_actual as ut_data_value_date).data_value + between + (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_yminterval).data_value + and + (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_yminterval).data_value; elsif self.expected is of (ut_data_value_date) and self.dist is of ( ut_data_value_dsinterval) then - l_result := treat(a_actual as ut_data_value_date).data_value between (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_dsinterval).data_value - and (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_dsinterval).data_value; + l_result := treat(a_actual as ut_data_value_date).data_value + between + (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_dsinterval).data_value + and + (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_dsinterval).data_value; end if; else l_result := (self as ut_matcher).run_matcher(a_actual); diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index a3ed605f9..61bc61a84 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -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..9d428b363 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(Test day to second interval passing a second) + procedure int_conv_ds_sec; + + --%test(Test day to second interval passing a minute) + procedure int_conv_ds_minute; + + --%test(Test day to second interval passing a hour) + procedure int_conv_ds_hour; + + --%test(Test day to second interval passing a day) + procedure int_conv_ds_day; + + --%test(Test day to second interval passing a custom date ) + procedure int_conv_ds_date; + + --%test(Test year to month interval passing a hour) + procedure int_conv_ym_year; + + --%test(Test year to month interval passing a day) + procedure int_conv_ym_month; + + --%test(Test year to month interval passing a custom date ) + procedure int_conv_ym_date; + + + --%endcontext + end test_ut_utils; / diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index b4c727a34..af672e809 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -103,7 +103,7 @@ create or replace package body test_to_be_within is --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 day 3 hour 4 minute 11.333 second of % (date)]'; + 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); @@ -131,7 +131,7 @@ create or replace package body test_to_be_within is --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 month % (date)]'; + 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); From a660208acc592faee891a4ca22e7835fdca4224c Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 14 Jun 2020 20:02:49 +0100 Subject: [PATCH 09/35] First code corrections --- docs/userguide/expectations.md | 18 +------ source/core/ut_utils.pkb | 18 ++----- source/core/ut_utils.pks | 3 ++ source/expectations/matchers/ut_be_within.tpb | 52 +++++++++---------- source/expectations/matchers/ut_be_within.tps | 12 ++--- .../expectations/matchers/ut_matcher_base.tps | 2 +- source/expectations/ut_expectation_base.tpb | 2 +- source/expectations/ut_expectation_base.tps | 4 +- 8 files changed, 44 insertions(+), 67 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 4e93f0be1..3049ac447 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1126,22 +1126,6 @@ end; **Example 3.** ```sql -begin - ut.expect(sysdate).to_be_within_pct(interval '1' day).of_(sysdate + 1); -end; -/ -``` - -**Example 4.** -```sql -begin - ut.expect(sysdate).to_be_within_pct(interval '1' month).of_(add_months(sysdate,1)); -end; -/ -``` - -**Example 5.** -```sql begin ut.expect(3).to_be_within(1).of_(5); end; @@ -1158,7 +1142,7 @@ Failures: at "UT3_DEVELOP.TEST_BETWNSTR.WIHTIN_TEST", line 5 ``` -**Example 6.** +**Example 4.** ```sql begin ut.expect(sysdate).to_be_within(interval '1' day).of_(sysdate+2); diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 4b6c66d95..e2804a3b8 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -887,25 +887,18 @@ create or replace package body ut_utils is l_result := case when l_day = 1 then l_day ||' day' when l_day > 1 then l_day ||' days' - else null - end; - l_result := l_result || + end || case when l_hour = 1 then ' '|| l_hour ||' hour' when l_hour > 1 then ' '|| l_hour ||' hours' - else null - end; - l_result := l_result || + end || case when l_minute = 1 then ' '||l_minute ||' minute' when l_minute > 1 then ' '||l_minute ||' minutes' - else null - end; - l_result := l_result || + end || case when l_second = 1 then ' '||l_second ||' second' when l_second > 1 then ' '||l_second ||' seconds' - else null end; return trim(leading ' ' from l_result); end; @@ -918,13 +911,10 @@ create or replace package body ut_utils is l_result := case when l_year = 1 then l_year ||' year' when l_year > 1 then l_year ||' years' - else null - end; - l_result := l_result || + end || case when l_month = 1 then ' '||l_month ||' month' when l_month > 1 then ' '||l_month ||' months' - else null end; return trim(leading ' ' from l_result); end; diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 750b17a77..e8219374b 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -440,6 +440,9 @@ create or replace package ut_utils authid definer is */ 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/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index ab4ed8b6f..b6e975166 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -16,28 +16,28 @@ create or replace type body ut_be_within as limitations under the License. */ - member procedure init(self in out nocopy ut_be_within, a_dist ut_data_value, a_is_pct number , a_self_type varchar2 := null) is + member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value, a_is_pct number , a_self_type varchar2 := null) is begin - self.dist := a_dist; + self.distance_from_expected := a_distance_from_expected; self.is_pct := nvl(a_is_pct,0); self.self_type := nvl( a_self_type, $$plsql_unit ); end; - constructor function ut_be_within(self in out nocopy ut_be_within, a_dist number, a_is_pct number) return self as result is + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected number, a_is_pct number) return self as result is begin - init(ut_data_value_number(a_dist),a_is_pct); + init(ut_data_value_number(a_distance_from_expected),a_is_pct); return; end; - constructor function ut_be_within(self in out nocopy ut_be_within, a_dist dsinterval_unconstrained, a_is_pct number) return self as result is + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected dsinterval_unconstrained, a_is_pct number) return self as result is begin - init(ut_data_value_dsinterval(a_dist),a_is_pct); + init(ut_data_value_dsinterval(a_distance_from_expected),a_is_pct); return; end; - constructor function ut_be_within(self in out nocopy ut_be_within, a_dist yminterval_unconstrained, a_is_pct number) return self as result is + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected yminterval_unconstrained, a_is_pct number) return self as result is begin - init(ut_data_value_yminterval(a_dist),a_is_pct); + init(ut_data_value_yminterval(a_distance_from_expected),a_is_pct); return; end; @@ -61,24 +61,24 @@ create or replace type body ut_be_within as if self.expected.data_type = a_actual.data_type then if self.expected is of (ut_data_value_number) and self.is_pct = 0 then l_result := abs((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value)) <= - treat(self.dist as ut_data_value_number).data_value; + treat(self.distance_from_expected as ut_data_value_number).data_value; elsif self.expected is of (ut_data_value_number) and self.is_pct = 1 then - l_result := treat(self.dist as ut_data_value_number).data_value >= + l_result := treat(self.distance_from_expected as ut_data_value_number).data_value >= ( ((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / (treat(self.expected as ut_data_value_number).data_value)) ; - elsif self.expected is of (ut_data_value_date) and self.dist is of ( ut_data_value_yminterval) then + elsif self.expected is of (ut_data_value_date) and self.distance_from_expected is of ( ut_data_value_yminterval) then l_result := treat(a_actual as ut_data_value_date).data_value between - (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_yminterval).data_value + (treat(self.expected as ut_data_value_date).data_value) - treat(self.distance_from_expected as ut_data_value_yminterval).data_value and - (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_yminterval).data_value; - elsif self.expected is of (ut_data_value_date) and self.dist is of ( ut_data_value_dsinterval) then + (treat(self.expected as ut_data_value_date).data_value) + treat(self.distance_from_expected as ut_data_value_yminterval).data_value; + elsif self.expected is of (ut_data_value_date) and self.distance_from_expected is of ( ut_data_value_dsinterval) then l_result := treat(a_actual as ut_data_value_date).data_value between - (treat(self.expected as ut_data_value_date).data_value) - treat(self.dist as ut_data_value_dsinterval).data_value + (treat(self.expected as ut_data_value_date).data_value) - treat(self.distance_from_expected as ut_data_value_dsinterval).data_value and - (treat(self.expected as ut_data_value_date).data_value) + treat(self.dist as ut_data_value_dsinterval).data_value; + (treat(self.expected as ut_data_value_date).data_value) + treat(self.distance_from_expected as ut_data_value_dsinterval).data_value; end if; else l_result := (self as ut_matcher).run_matcher(a_actual); @@ -87,20 +87,20 @@ create or replace type body ut_be_within as end; overriding member function failure_message(a_actual ut_data_value) return varchar2 is - l_distance varchar2(32767); + l_distance_from_expected varchar2(32767); begin - l_distance := case - when self.dist is of (ut_data_value_number) then - treat(self.dist as ut_data_value_number).to_string - when self.dist is of (ut_data_value_yminterval) then - treat(self.dist as ut_data_value_yminterval).to_string - when self.dist is of (ut_data_value_dsinterval) then - treat(self.dist as ut_data_value_dsinterval).to_string + l_distance_from_expected := case + when self.distance_from_expected is of (ut_data_value_number) then + treat(self.distance_from_expected as ut_data_value_number).to_string + when self.distance_from_expected is of (ut_data_value_yminterval) then + treat(self.distance_from_expected as ut_data_value_yminterval).to_string + when self.distance_from_expected is of (ut_data_value_dsinterval) then + treat(self.distance_from_expected as ut_data_value_dsinterval).to_string else null end; - return (self as ut_matcher).failure_message(a_actual) || ' '||l_distance ||' of '|| expected.to_string_report(); + return (self as ut_matcher).failure_message(a_actual) || ' '||l_distance_from_expected ||' of '|| expected.to_string_report(); end; overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2 is @@ -110,4 +110,4 @@ create or replace type body ut_be_within as end; end; -/ \ No newline at end of file +/ diff --git a/source/expectations/matchers/ut_be_within.tps b/source/expectations/matchers/ut_be_within.tps index 30947d2aa..9b0d0109d 100644 --- a/source/expectations/matchers/ut_be_within.tps +++ b/source/expectations/matchers/ut_be_within.tps @@ -20,13 +20,13 @@ create or replace type ut_be_within under ut_comparison_matcher( /** * Holds information about mather options */ - dist ut_data_value, + distance_from_expected ut_data_value, is_pct number(1,0), - member procedure init(self in out nocopy ut_be_within, a_dist ut_data_value, a_is_pct number , a_self_type varchar2 := null), - constructor function ut_be_within(self in out nocopy ut_be_within, a_dist number, a_is_pct number) return self as result, - constructor function ut_be_within(self in out nocopy ut_be_within, a_dist dsinterval_unconstrained, a_is_pct number) return self as result, - constructor function ut_be_within(self in out nocopy ut_be_within, a_dist yminterval_unconstrained, a_is_pct number) return self as result, + member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value, a_is_pct number , a_self_type varchar2 := null), + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected number, a_is_pct number) return self as result, + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected dsinterval_unconstrained, a_is_pct number) return self as result, + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected yminterval_unconstrained, a_is_pct number) return self as result, member procedure of_(self in ut_be_within, a_expected number), member procedure of_(self in ut_be_within, a_expected date), @@ -35,4 +35,4 @@ create or replace type ut_be_within under ut_comparison_matcher( overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2 ) not final -/ \ No newline at end of file +/ diff --git a/source/expectations/matchers/ut_matcher_base.tps b/source/expectations/matchers/ut_matcher_base.tps index ec37267a0..ef7fd98a2 100644 --- a/source/expectations/matchers/ut_matcher_base.tps +++ b/source/expectations/matchers/ut_matcher_base.tps @@ -2,4 +2,4 @@ create or replace type ut_matcher_base force authid current_user as object( self_type varchar2(250) ) not final not instantiable -/ \ No newline at end of file +/ diff --git a/source/expectations/ut_expectation_base.tpb b/source/expectations/ut_expectation_base.tpb index d657c2822..20b3e7a95 100644 --- a/source/expectations/ut_expectation_base.tpb +++ b/source/expectations/ut_expectation_base.tpb @@ -41,4 +41,4 @@ create or replace type body ut_expectation_base as ut_expectation_processor.add_expectation_result( ut_expectation_result( ut_utils.to_test_result( l_expectation_result ), self.description, l_message ) ); end; end; -/ \ No newline at end of file +/ diff --git a/source/expectations/ut_expectation_base.tps b/source/expectations/ut_expectation_base.tps index 87c0083b0..ad96ea97b 100644 --- a/source/expectations/ut_expectation_base.tps +++ b/source/expectations/ut_expectation_base.tps @@ -21,5 +21,5 @@ create or replace type ut_expectation_base force authid current_user as object( --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 -/ \ No newline at end of file +) not final not instantiable +/ From ada1ea44fcaac3c118253f32ba710f2214e81705 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 14 Jun 2020 20:35:33 +0100 Subject: [PATCH 10/35] Resolving another comment --- source/expectations/ut_expectation_compound.tpb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source/expectations/ut_expectation_compound.tpb b/source/expectations/ut_expectation_compound.tpb index 7043ec053..ec6bf392c 100644 --- a/source/expectations/ut_expectation_compound.tpb +++ b/source/expectations/ut_expectation_compound.tpb @@ -35,11 +35,11 @@ create or replace type body ut_expectation_compound as member function to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_equal is - l_result ut_matcher; + l_result ut_equal; begin l_result := ut_equal(a_expected, a_nulls_are_equal); l_result.expectation := self; - return treat(l_result as ut_equal); + return l_result; end; member function not_to_equal(a_expected anydata, a_nulls_are_equal boolean := null) return ut_equal is @@ -51,11 +51,11 @@ create or replace type body ut_expectation_compound as end; member function to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal is - l_result ut_matcher; + l_result ut_equal; begin l_result := ut_equal(a_expected, a_nulls_are_equal); l_result.expectation := self; - return treat(l_result as ut_equal); + return l_result; end; member function not_to_equal(a_expected sys_refcursor, a_nulls_are_equal boolean := null) return ut_equal is @@ -67,11 +67,11 @@ create or replace type body ut_expectation_compound as end; member function to_contain(a_expected sys_refcursor) return ut_equal is - l_result ut_matcher; + l_result ut_equal; begin l_result := ut_contain(a_expected); l_result.expectation := self; - return treat(l_result as ut_equal); + return l_result; end; member function not_to_contain(a_expected sys_refcursor) return ut_equal is @@ -83,11 +83,11 @@ create or replace type body ut_expectation_compound as end; member function to_contain(a_expected anydata) return ut_equal is - l_result ut_matcher; + l_result ut_equal; begin l_result := ut_contain(a_expected); l_result.expectation := self; - return treat(l_result as ut_equal); + return l_result; end; member function not_to_contain(a_expected anydata) return ut_equal is From fe1b0cb4c93314257b196157e33eec42f3c7d251 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 14 Jun 2020 20:51:18 +0100 Subject: [PATCH 11/35] Updating issues --- source/expectations/ut_expectation_compound.tpb | 16 ++++++++-------- source/expectations/ut_expectation_compound.tps | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/source/expectations/ut_expectation_compound.tpb b/source/expectations/ut_expectation_compound.tpb index ec6bf392c..6a2047aed 100644 --- a/source/expectations/ut_expectation_compound.tpb +++ b/source/expectations/ut_expectation_compound.tpb @@ -66,36 +66,36 @@ create or replace type body ut_expectation_compound as return treat(l_result as ut_equal); end; - member function to_contain(a_expected sys_refcursor) return ut_equal is - l_result ut_equal; + member function to_contain(a_expected sys_refcursor) return ut_contain is + l_result ut_contain; begin l_result := ut_contain(a_expected); l_result.expectation := self; return l_result; end; - member function not_to_contain(a_expected sys_refcursor) return ut_equal is + member function not_to_contain(a_expected sys_refcursor) return ut_contain is l_result ut_matcher; begin l_result := ut_contain(a_expected).negated(); l_result.expectation := self; - return treat(l_result as ut_equal); + return treat(l_result as ut_contain); end; - member function to_contain(a_expected anydata) return ut_equal is - l_result ut_equal; + member function to_contain(a_expected anydata) return ut_contain is + l_result ut_contain; begin l_result := ut_contain(a_expected); l_result.expectation := self; return l_result; end; - member function not_to_contain(a_expected anydata) return ut_equal is + member function not_to_contain(a_expected anydata) return ut_contain is l_result ut_matcher; begin l_result := ut_contain(a_expected).negated(); l_result.expectation := self; - return treat(l_result as ut_equal); + 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 a2c06ce76..71c5e2ce9 100644 --- a/source/expectations/ut_expectation_compound.tps +++ b/source/expectations/ut_expectation_compound.tps @@ -26,10 +26,10 @@ create or replace type ut_expectation_compound under ut_expectation( 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_equal, - member function not_to_contain(a_expected sys_refcursor) return ut_equal, - member function to_contain(a_expected anydata) return ut_equal, - member function not_to_contain(a_expected anydata) 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 ) / From 013db74c9e0be8c67ffb7e3288b5027fac759296 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 14 Jun 2020 23:12:56 +0100 Subject: [PATCH 12/35] Update tble --- docs/userguide/expectations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 3049ac447..3ecf8db0a 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -333,7 +333,7 @@ The matrix below illustrates the data types supported by different matchers. | **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().of_()** | | | | x | x | | | | | | | | | | | # Expecting exceptions From b5c73b44898bfcfe28497f0ff27df4df892f6af2 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 19 Jun 2020 10:11:55 +0100 Subject: [PATCH 13/35] Separated into two different matchers Added synonym and grant for matcher Reworked expectation to work fine with syntax `to_( matcher() )` for to_be_within. TODO - add tests for other matchers with `to_( matcher )` and `not_to( matcher )` syntax --- source/api/be_within.syn | 1 + source/create_grants.sql | 1 + source/create_synonyms.sql | 1 + source/expectations/matchers/ut_be_within.tpb | 42 ++++++---- source/expectations/matchers/ut_be_within.tps | 14 ++-- .../matchers/ut_be_within_pct.tpb | 42 ++++++++++ .../matchers/ut_be_within_pct.tps | 24 ++++++ source/expectations/matchers/ut_matcher.tpb | 5 -- source/expectations/ut_expectation.tpb | 52 +++++++++--- source/expectations/ut_expectation.tps | 6 +- source/install.sql | 3 + .../ut3_tester_helper/expectations_helper.pkb | 24 ------ .../ut3_tester_helper/expectations_helper.pks | 10 --- .../expectations/binary/test_to_be_within.pkb | 81 ++++++++++++++++--- .../expectations/binary/test_to_be_within.pks | 2 +- 15 files changed, 220 insertions(+), 88 deletions(-) create mode 100644 source/api/be_within.syn create mode 100644 source/expectations/matchers/ut_be_within_pct.tpb create mode 100644 source/expectations/matchers/ut_be_within_pct.tps 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/create_grants.sql b/source/create_grants.sql index 4553c52f6..111294cef 100644 --- a/source/create_grants.sql +++ b/source/create_grants.sql @@ -87,6 +87,7 @@ 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_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 425ca57a6..53e2bb65f 100644 --- a/source/create_synonyms.sql +++ b/source/create_synonyms.sql @@ -103,6 +103,7 @@ 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.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/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index b6e975166..a5b5d6cbf 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -16,28 +16,27 @@ create or replace type body ut_be_within as limitations under the License. */ - member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value, a_is_pct number , a_self_type varchar2 := null) is + member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value) is begin self.distance_from_expected := a_distance_from_expected; - self.is_pct := nvl(a_is_pct,0); - self.self_type := nvl( a_self_type, $$plsql_unit ); + self.self_type := $$plsql_unit; end; - constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected number, a_is_pct number) return self as result is + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected number) return self as result is begin - init(ut_data_value_number(a_distance_from_expected),a_is_pct); + init(ut_data_value_number(a_distance_from_expected)); return; end; - constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected dsinterval_unconstrained, a_is_pct number) return self as result is + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected dsinterval_unconstrained) return self as result is begin - init(ut_data_value_dsinterval(a_distance_from_expected),a_is_pct); + init(ut_data_value_dsinterval(a_distance_from_expected)); return; end; - constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected yminterval_unconstrained, a_is_pct number) return self as result is + constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected yminterval_unconstrained) return self as result is begin - init(ut_data_value_yminterval(a_distance_from_expected),a_is_pct); + init(ut_data_value_yminterval(a_distance_from_expected)); return; end; @@ -54,20 +53,29 @@ create or replace type body ut_be_within as l_result.expected := ut_data_value_date(a_expected); l_result.expectation.to_(l_result ); end; - + + member function of_(self in ut_be_within, a_expected number) return ut_be_within is + l_result ut_be_within := self; + begin + l_result.expected := ut_data_value_number(a_expected); + return l_result; + 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; + 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 then - if self.expected is of (ut_data_value_number) and self.is_pct = 0 then + if self.expected is of (ut_data_value_number) then l_result := abs((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value)) <= treat(self.distance_from_expected as ut_data_value_number).data_value; - elsif self.expected is of (ut_data_value_number) and self.is_pct = 1 then - l_result := treat(self.distance_from_expected as ut_data_value_number).data_value >= - ( - ((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / - (treat(self.expected as ut_data_value_number).data_value)) ; - elsif self.expected is of (ut_data_value_date) and self.distance_from_expected is of ( ut_data_value_yminterval) then + elsif self.expected is of (ut_data_value_date) and self.distance_from_expected is of ( ut_data_value_yminterval) then l_result := treat(a_actual as ut_data_value_date).data_value between (treat(self.expected as ut_data_value_date).data_value) - treat(self.distance_from_expected as ut_data_value_yminterval).data_value diff --git a/source/expectations/matchers/ut_be_within.tps b/source/expectations/matchers/ut_be_within.tps index 9b0d0109d..55f32bc4e 100644 --- a/source/expectations/matchers/ut_be_within.tps +++ b/source/expectations/matchers/ut_be_within.tps @@ -21,15 +21,15 @@ create or replace type ut_be_within under ut_comparison_matcher( * Holds information about mather options */ distance_from_expected ut_data_value, - is_pct number(1,0), - - member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value, a_is_pct number , a_self_type varchar2 := null), - constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected number, a_is_pct number) return self as result, - constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected dsinterval_unconstrained, a_is_pct number) return self as result, - constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected yminterval_unconstrained, a_is_pct number) return self as result, + member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value), + 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 number), member procedure of_(self in ut_be_within, a_expected date), - + member function of_(self in ut_be_within, a_expected number) return ut_be_within, + member function of_(self in ut_be_within, a_expected date) 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 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..326197fe6 --- /dev/null +++ b/source/expectations/matchers/ut_be_within_pct.tpb @@ -0,0 +1,42 @@ +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_distance_from_expected number) return self as result is + begin + self.init(ut_data_value_number(a_distance_from_expected)); + return; + 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 := treat(self.distance_from_expected as ut_data_value_number).data_value >= + ( + ((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / + (treat(self.expected as ut_data_value_number).data_value)) ; + end if; + else + l_result := (self as ut_matcher).run_matcher(a_actual); + 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..b47c7a9fd --- /dev/null +++ b/source/expectations/matchers/ut_be_within_pct.tps @@ -0,0 +1,24 @@ +create or replace type ut_be_within_pct under ut_be_within( + /* + 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_distance_from_expected number) return self as result, + overriding member function run_matcher(self in out nocopy ut_be_within_pct, a_actual ut_data_value) return boolean +) +not final +/ diff --git a/source/expectations/matchers/ut_matcher.tpb b/source/expectations/matchers/ut_matcher.tpb index 11ff1b6b6..ca8598fd8 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/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index 288c6cf19..8801af724 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -694,37 +694,69 @@ create or replace type body ut_expectation as self.not_to( ut_contain(a_expected).negated() ); end; - member function to_be_within(a_dist natural) return ut_be_within is + member function to_be_within(a_dist natural) return ut_be_within is l_result ut_matcher; begin - l_result := ut_be_within(a_dist,0); + l_result := ut_be_within(a_dist); l_result.expectation := self; return treat(l_result as ut_be_within); end; - member function to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is + member function to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is l_result ut_matcher; begin - l_result := ut_be_within(a_dist,0); + l_result := ut_be_within(a_dist); l_result.expectation := self; return treat(l_result as ut_be_within); end; - member function to_be_within(a_dist yminterval_unconstrained) return ut_be_within is + member function to_be_within(a_dist yminterval_unconstrained) return ut_be_within is l_result ut_matcher; begin - l_result := ut_be_within(a_dist,0); + l_result := ut_be_within(a_dist); l_result.expectation := self; return treat(l_result as ut_be_within); end; - member function to_be_within_pct(a_dist natural) return ut_be_within is + member function to_be_within_pct(a_dist natural) return ut_be_within_pct is + l_result ut_matcher; + begin + l_result := ut_be_within_pct(a_dist); + l_result.expectation := self; + return treat(l_result as ut_be_within_pct); + end; + + member function not_to_be_within(a_dist natural) return ut_be_within is l_result ut_matcher; begin - l_result := ut_be_within(a_dist,1); + l_result := ut_be_within(a_dist).negated(); l_result.expectation := self; return treat(l_result as ut_be_within); - end; - + end; + + member function not_to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist).negated(); + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function not_to_be_within(a_dist yminterval_unconstrained) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist).negated(); + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function not_to_be_within_pct(a_dist natural) return ut_be_within_pct is + l_result ut_matcher; + begin + l_result := ut_be_within_pct(a_dist).negated(); + l_result.expectation := self; + return treat(l_result as ut_be_within_pct); + end; + end; / diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps index b45141b5c..31144d82c 100644 --- a/source/expectations/ut_expectation.tps +++ b/source/expectations/ut_expectation.tps @@ -167,7 +167,11 @@ create or replace type ut_expectation under ut_expectation_base( member function to_be_within(a_dist natural) 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 natural) return ut_be_within + member function to_be_within_pct(a_dist natural) return ut_be_within_pct, + member function not_to_be_within(a_dist natural) 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 natural) return ut_be_within_pct ) not final / diff --git a/source/install.sql b/source/install.sql index 911760a63..af639ac78 100644 --- a/source/install.sql +++ b/source/install.sql @@ -241,6 +241,7 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@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.tps' +@@install_component.sql 'expectations/matchers/ut_be_within_pct.tps' @@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' @@ -297,6 +298,7 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@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.tpb' +@@install_component.sql 'expectations/matchers/ut_be_within_pct.tpb' @@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' @@ -360,6 +362,7 @@ 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.syn' @@install_component.sql 'api/equal.syn' @@install_component.sql 'api/have_count.syn' @@install_component.sql 'api/match.syn' diff --git a/test/ut3_tester_helper/expectations_helper.pkb b/test/ut3_tester_helper/expectations_helper.pkb index 7714e1ea3..b2fb04320 100644 --- a/test/ut3_tester_helper/expectations_helper.pkb +++ b/test/ut3_tester_helper/expectations_helper.pkb @@ -53,29 +53,5 @@ create or replace package body ut3_tester_helper.expectations_helper is return l_execute; 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 - ) 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); - end;'; - return l_execute; - end; - end; / diff --git a/test/ut3_tester_helper/expectations_helper.pks b/test/ut3_tester_helper/expectations_helper.pks index 3b0a754d2..9c1d54333 100644 --- a/test/ut3_tester_helper/expectations_helper.pks +++ b/test/ut3_tester_helper/expectations_helper.pks @@ -21,15 +21,5 @@ create or replace package expectations_helper is a_expected_data varchar2 ) return varchar2; - 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 - ) return varchar2; - end; / diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index af672e809..2605d3c53 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -7,16 +7,27 @@ create or replace package body test_to_be_within is function be_within_expectation_block( a_matcher_name varchar2, - a_data_type varchar2, - a_actual varchar2, - a_expected 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 - ) return varchar2 is + a_distance_data_type varchar2, + a_matcher_end varchar2 + ) return varchar2 + is + l_execute varchar2(32000); begin - return ut3_tester_helper.expectations_helper.be_within_expectation_block( - a_matcher_name, a_data_type, a_actual, a_data_type, a_expected,a_distance,a_distance_data_type - ); + 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( @@ -25,10 +36,14 @@ create or replace package body test_to_be_within is a_actual varchar2, a_expected varchar2, a_distance varchar2, - a_distance_data_type 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_expected,a_distance,a_distance_data_type); + 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; @@ -39,10 +54,14 @@ create or replace package body test_to_be_within is a_actual varchar2, a_expected varchar2, a_distance varchar2, - a_distance_data_type 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_expected,a_distance,a_distance_data_type); + 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).to_equal(0); cleanup_expectations; end; @@ -55,6 +74,24 @@ create or replace package body test_to_be_within is 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_( 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_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',')'); end; procedure failed_tests is @@ -65,7 +102,25 @@ create or replace package body test_to_be_within is 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'); - end; + 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); diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pks b/test/ut3_user/expectations/binary/test_to_be_within.pks index 5c042bd53..dcfb471af 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pks +++ b/test/ut3_user/expectations/binary/test_to_be_within.pks @@ -1,6 +1,6 @@ create or replace package test_to_be_within is - --%suite((not)to_be_less_or_equal) + --%suite((not)to_be_within) --%suitepath(utplsql.test_user.expectations.binary) --%aftereach From 2e721da4635da8652d69fecbc908b961962bf8c1 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 19 Jun 2020 16:53:32 +0100 Subject: [PATCH 14/35] CHECKPOINT --- source/expectations/matchers/ut_be_within.tpb | 12 +++++-- source/expectations/ut_expectation.tpb | 33 +++++++++++++++++++ source/expectations/ut_expectation.tps | 8 ++++- source/expectations/ut_expectation_base.tps | 2 +- test/ut3_tester/core/test_ut_utils.pks | 16 ++++----- .../ut3_tester_helper/expectations_helper.pkb | 2 +- .../expectations/binary/test_to_be_within.pkb | 2 +- .../expectations/binary/test_to_be_within.pks | 8 ++--- 8 files changed, 65 insertions(+), 18 deletions(-) diff --git a/source/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index b6e975166..028bd6ad9 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -45,14 +45,22 @@ create or replace type body ut_be_within as l_result ut_be_within := self; begin l_result.expected := ut_data_value_number(a_expected); - l_result.expectation.to_(l_result ); + 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 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); - l_result.expectation.to_(l_result ); + 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; overriding member function run_matcher(self in out nocopy ut_be_within, a_actual ut_data_value) return boolean is diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index 288c6cf19..6ef07c47b 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -725,6 +725,39 @@ create or replace type body ut_expectation as l_result.expectation := self; return treat(l_result as ut_be_within); end; + + member function not_to_be_within(a_dist natural) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,0).negated; + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function not_to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,0).negated; + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function not_to_be_within(a_dist yminterval_unconstrained) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,0).negated; + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; + + member function not_to_be_within_pct(a_dist natural) return ut_be_within is + l_result ut_matcher; + begin + l_result := ut_be_within(a_dist,0).negated; + l_result.expectation := self; + return treat(l_result as ut_be_within); + end; end; / + diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps index b45141b5c..d4c446ea8 100644 --- a/source/expectations/ut_expectation.tps +++ b/source/expectations/ut_expectation.tps @@ -167,7 +167,13 @@ create or replace type ut_expectation under ut_expectation_base( member function to_be_within(a_dist natural) 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 natural) return ut_be_within + member function to_be_within_pct(a_dist natural) return ut_be_within, + + member function not_to_be_within(a_dist natural) 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 natural) return ut_be_within + ) not final / diff --git a/source/expectations/ut_expectation_base.tps b/source/expectations/ut_expectation_base.tps index ad96ea97b..a542d26ea 100644 --- a/source/expectations/ut_expectation_base.tps +++ b/source/expectations/ut_expectation_base.tps @@ -1,4 +1,4 @@ -create or replace type ut_expectation_base force authid current_user as object( +create or replace type ut_expectation_base authid current_user as object( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 9d428b363..4d83b5042 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -130,28 +130,28 @@ create or replace package test_ut_utils is --%context(interval_converter_to_strin) - --%test(Test day to second interval passing a second) + --%test(returns text representation of interval day to second for 1 second interval) procedure int_conv_ds_sec; - --%test(Test day to second interval passing a minute) + --%test(returns text representation of interval day to second for 1 minute interval) procedure int_conv_ds_minute; - --%test(Test day to second interval passing a hour) + --%test(returns text representation of interval day to second for 1 hour interval) procedure int_conv_ds_hour; - --%test(Test day to second interval passing a day) + --%test(returns text representation of interval day to second for 1 day interval) procedure int_conv_ds_day; - --%test(Test day to second interval passing a custom date ) + --%test(returns text representation of interval day to second for combination interval) procedure int_conv_ds_date; - --%test(Test year to month interval passing a hour) + --%test(returns text representation of interval year to month for 1 year interval) procedure int_conv_ym_year; - --%test(Test year to month interval passing a day) + --%test(returns text representation of interval year to month for 1 month interval) procedure int_conv_ym_month; - --%test(Test year to month interval passing a custom date ) + --%test(returns text representation of interval year to month for custom interval) procedure int_conv_ym_date; diff --git a/test/ut3_tester_helper/expectations_helper.pkb b/test/ut3_tester_helper/expectations_helper.pkb index 7714e1ea3..eafb9fa3e 100644 --- a/test/ut3_tester_helper/expectations_helper.pkb +++ b/test/ut3_tester_helper/expectations_helper.pkb @@ -1,4 +1,4 @@ -create or replace package body ut3_tester_helper.expectations_helper is +create or replace package body expectations_helper is function unary_expectation_block( a_matcher_name varchar2, diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index af672e809..97dd865f4 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -138,4 +138,4 @@ create or replace package body test_to_be_within is end; end; -/ \ No newline at end of file +/ diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pks b/test/ut3_user/expectations/binary/test_to_be_within.pks index 5c042bd53..76b606446 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pks +++ b/test/ut3_user/expectations/binary/test_to_be_within.pks @@ -6,10 +6,10 @@ create or replace package test_to_be_within is --%aftereach procedure cleanup_expectations; - --%test(Gives failure when number is not within positive distance) + --%test(gives success for values within a distance) procedure success_tests; - --%test(Gives failure when number is not within negative distance) + --%test(gives failure when number is not within distance) procedure failed_tests; --%test(Check failure message for number not within) @@ -25,7 +25,7 @@ create or replace package test_to_be_within is procedure fail_for_ym_int_not_within; --%test(Check failure message for custom ym interval not within) - procedure fail_for_custom_ym_int; + procedure fail_for_custom_ym_int; end; -/ \ No newline at end of file +/ From f1824303682355d85ca52fe0a45623225582e836 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 19 Jun 2020 19:48:49 +0100 Subject: [PATCH 15/35] Update uninstall --- source/uninstall_objects.sql | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index c905153f4..82d8a7e5a 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -54,6 +54,8 @@ drop synonym be_true; drop synonym equal; +drop synonym be_within; + drop type ut_coveralls_reporter force; drop type ut_coverage_sonar_reporter force; @@ -140,6 +142,10 @@ 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 type ut_comparison_matcher force; drop type ut_matcher force; From e3fb2d7f15062b91a81570973f56209be8f89cb3 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 19 Jun 2020 20:26:26 +0100 Subject: [PATCH 16/35] Update progress --- docs/userguide/expectations.md | 36 +++++++++++++------ source/expectations/matchers/ut_be_within.tpb | 20 +++-------- source/expectations/ut_expectation.tpb | 18 +++++----- .../expectations/binary/test_to_be_within.pkb | 15 ++++++++ .../expectations/binary/test_to_be_within.pks | 15 ++++---- 5 files changed, 63 insertions(+), 41 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 3ecf8db0a..3f26a0eff 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -334,7 +334,7 @@ The matrix below illustrates the data types supported by different matchers. | **be_empty** | X | | X | | | | | | | | | X | X | | X | | **have_count** | | | | | | | | | | | | X | X | | X | | **be_within().of_()** | | | | x | x | | | | | | | | | | | - +| **be_within_pct().of()**| | | | | x | | | | | | | | | | | # Expecting exceptions @@ -1118,14 +1118,6 @@ end; **Example 2.** ```sql -begin - ut.expect(9).to_be_within_pct(10).of_(10); -end; -/ -``` - -**Example 3.** -```sql begin ut.expect(3).to_be_within(1).of_(5); end; @@ -1142,7 +1134,7 @@ Failures: at "UT3_DEVELOP.TEST_BETWNSTR.WIHTIN_TEST", line 5 ``` -**Example 4.** +**Example 3.** ```sql begin ut.expect(sysdate).to_be_within(interval '1' day).of_(sysdate+2); @@ -1160,6 +1152,30 @@ Failures: at "UT3_DEVELOP.TEST_BETWNSTR.WIHTIN_TEST", line 5 ``` + +## to_be_within_pct of + +This matcher is created to determine wheter expected value is approximately equal or "close" to another value within percentage value of expected. + +Matcher will allow to compare numbers. + +When comparing a number the tolerance / distance can be expressed as another postive number or a percentage. + +When comparing a two dates tolerance can be expressed in interval time either Day-To-Second or Year-To-Month. + +Matcher for numbers will calculate a absolute distance between expected and actual and check whether that value is within a tolerance. + +When comparing a date a distance is measured in interval, the check is done that actual value is within date range of expected taking into account interval plus and minus. + +**Example 1.** +```sql +begin + ut.expect(9).to_be_within_pct(10).of_(10); +end; +/ +``` + + ## Comparing cursors, object types, nested tables and varrays utPLSQL is capable of comparing compound data-types including: diff --git a/source/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index 9089c0033..52fe6aef0 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -103,26 +103,14 @@ create or replace type body ut_be_within as end; overriding member function failure_message(a_actual ut_data_value) return varchar2 is - l_distance_from_expected varchar2(32767); - begin - l_distance_from_expected := case - when self.distance_from_expected is of (ut_data_value_number) then - treat(self.distance_from_expected as ut_data_value_number).to_string - when self.distance_from_expected is of (ut_data_value_yminterval) then - treat(self.distance_from_expected as ut_data_value_yminterval).to_string - when self.distance_from_expected is of (ut_data_value_dsinterval) then - treat(self.distance_from_expected as ut_data_value_dsinterval).to_string - else - null - end; - - return (self as ut_matcher).failure_message(a_actual) || ' '||l_distance_from_expected ||' of '|| expected.to_string_report(); + 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 l_result varchar2(32767); - begin - return (self as ut_matcher).failure_message_when_negated(a_actual) || ': '|| expected.to_string_report(); + 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/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index 710e8f68c..4c25872f5 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -695,35 +695,35 @@ create or replace type body ut_expectation as end; member function to_be_within(a_dist natural) return ut_be_within is - l_result ut_matcher; + l_result ut_be_within; begin l_result := ut_be_within(a_dist); l_result.expectation := self; - return treat(l_result as ut_be_within); + return l_result; end; member function to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is - l_result ut_matcher; + l_result ut_be_within; begin l_result := ut_be_within(a_dist); l_result.expectation := self; - return treat(l_result as ut_be_within); + return l_result; end; member function to_be_within(a_dist yminterval_unconstrained) return ut_be_within is - l_result ut_matcher; + l_result ut_be_within; begin l_result := ut_be_within(a_dist); l_result.expectation := self; - return treat(l_result as ut_be_within); + return l_result; end; member function to_be_within_pct(a_dist natural) return ut_be_within_pct is - l_result ut_matcher; + l_result ut_be_within_pct; begin l_result := ut_be_within_pct(a_dist); l_result.expectation := self; - return treat(l_result as ut_be_within_pct); + return l_result; end; member function not_to_be_within(a_dist natural) return ut_be_within is @@ -731,7 +731,7 @@ create or replace type body ut_expectation as begin l_result := ut_be_within(a_dist).negated(); l_result.expectation := self; - return treat(l_result as ut_be_within); + return treat(l_result as ut_be_within); end; member function not_to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index cb1b3317b..b845bb26a 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -192,5 +192,20 @@ create or replace package body test_to_be_within is 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; + + 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 index 6c3406ac4..8aa6798e2 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pks +++ b/test/ut3_user/expectations/binary/test_to_be_within.pks @@ -12,20 +12,23 @@ create or replace package test_to_be_within is --%test(gives failure when number is not within distance) procedure failed_tests; - --%test(Check failure message for number not within) + --%test(check failure message for number not within) procedure fail_for_number_not_within; - --%test(Check failure message for inteval of 1 sec not within) + --%test(check failure message for inteval of 1 sec not within) procedure fail_for_ds_int_not_within; - --%test(Check failure message for custom ds interval not within) + --%test(check failure message for custom ds interval not within) procedure fail_for_custom_ds_int; - --%test(Check failure message for inteval of 1 month not within) + --%test(check failure message for inteval of 1 month not within) procedure fail_for_ym_int_not_within; - --%test(Check failure message for custom ym interval not within) + --%test(check failure message for custom ym interval not within) procedure fail_for_custom_ym_int; - + + --%test(check failure message for simple within) + procedure fail_msg_when_not_within; + end; / From 322e0a15c5ea5a8879ee92a6950b7bc1f24a840a Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 19 Jun 2020 20:57:41 +0100 Subject: [PATCH 17/35] Making code a bit more readable --- source/expectations/matchers/ut_be_within.tpb | 43 ++++++++++++------- .../expectations/binary/test_to_be_within.pks | 12 +++--- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/source/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index 52fe6aef0..6f09f0392 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -75,26 +75,39 @@ create or replace type body ut_be_within as l_result.expected := ut_data_value_date(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; + function l_result_from_number return boolean is + l_expected number := treat(self.expected as ut_data_value_number).data_value; + l_actual number := treat(a_actual as ut_data_value_number).data_value; + l_distance number := treat(self.distance_from_expected as ut_data_value_number).data_value; + begin + return abs(l_expected - l_actual) <= l_distance; + end; + + function l_result_from_date(a_distance ut_data_value) return boolean is + l_expected date := treat(self.expected as ut_data_value_date).data_value; + l_actual date := treat(a_actual as ut_data_value_date).data_value; + l_distance_ym yminterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_yminterval) + then treat(self.distance_from_expected as ut_data_value_yminterval).data_value + end; + l_distance_ds dsinterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_dsinterval) + then treat(self.distance_from_expected as ut_data_value_dsinterval).data_value + end; + begin + return case when l_distance_ym is not null + then l_actual between l_expected - l_distance_ym and l_expected + l_distance_ym + else l_actual between l_expected - l_distance_ds and l_expected + l_distance_ds + end; + end; + 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.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value)) <= - treat(self.distance_from_expected as ut_data_value_number).data_value; - elsif self.expected is of (ut_data_value_date) and self.distance_from_expected is of ( ut_data_value_yminterval) then - l_result := treat(a_actual as ut_data_value_date).data_value - between - (treat(self.expected as ut_data_value_date).data_value) - treat(self.distance_from_expected as ut_data_value_yminterval).data_value - and - (treat(self.expected as ut_data_value_date).data_value) + treat(self.distance_from_expected as ut_data_value_yminterval).data_value; - elsif self.expected is of (ut_data_value_date) and self.distance_from_expected is of ( ut_data_value_dsinterval) then - l_result := treat(a_actual as ut_data_value_date).data_value - between - (treat(self.expected as ut_data_value_date).data_value) - treat(self.distance_from_expected as ut_data_value_dsinterval).data_value - and - (treat(self.expected as ut_data_value_date).data_value) + treat(self.distance_from_expected as ut_data_value_dsinterval).data_value; + l_result := l_result_from_number; + elsif self.expected is of (ut_data_value_date)then + l_result := l_result_from_date(self.distance_from_expected); end if; else l_result := (self as ut_matcher).run_matcher(a_actual); diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pks b/test/ut3_user/expectations/binary/test_to_be_within.pks index 8aa6798e2..b2f456584 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pks +++ b/test/ut3_user/expectations/binary/test_to_be_within.pks @@ -12,22 +12,22 @@ create or replace package test_to_be_within is --%test(gives failure when number is not within distance) procedure failed_tests; - --%test(check failure message for number not within) + --%test(returns well formatted failure message when expectation fails) procedure fail_for_number_not_within; - --%test(check failure message for inteval of 1 sec not within) + --%test(returns well formatted failure message for inteval of 1 sec not within) procedure fail_for_ds_int_not_within; - --%test(check failure message for custom ds interval not within) + --%test(returns well formatted failure message for custom ds interval not within) procedure fail_for_custom_ds_int; - --%test(check failure message for inteval of 1 month not within) + --%test(returns well formatted failure message for inteval of 1 month not within) procedure fail_for_ym_int_not_within; - --%test(check failure message for custom ym interval not within) + --%test(returns well formatted failure message for custom ym interval not within) procedure fail_for_custom_ym_int; - --%test(check failure message for simple within) + --%test(returns well formatted failure message for simple within) procedure fail_msg_when_not_within; end; From ff15596a7c8c3b907136ea2e83bb52f33dff00ca Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 20 Jun 2020 21:57:10 +0100 Subject: [PATCH 18/35] Added tests for `be_within_pct` Reorganized code so that `be_within_pct` is only supported for `number` Added tests for non-supported syntax --- source/api/be_within_pct.syn | 1 + source/core/ut_expectation_processor.pkb | 1 + source/create_grants.sql | 1 + source/create_synonyms.sql | 1 + source/expectations/matchers/ut_be_within.tpb | 43 +--- source/expectations/matchers/ut_be_within.tps | 10 +- .../matchers/ut_be_within_pct.tpb | 46 ++++- .../matchers/ut_be_within_pct.tps | 16 +- source/install.sql | 5 +- source/uninstall_objects.sql | 2 + test/install_ut3_user_tests.sql | 2 + .../binary/test_to_be_within_pct.pkb | 184 ++++++++++++++++++ .../binary/test_to_be_within_pct.pks | 22 +++ 13 files changed, 280 insertions(+), 54 deletions(-) create mode 100644 source/api/be_within_pct.syn create mode 100644 test/ut3_user/expectations/binary/test_to_be_within_pct.pkb create mode 100644 test/ut3_user/expectations/binary/test_to_be_within_pct.pks 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 d65d210c8..4bf15ee55 100644 --- a/source/core/ut_expectation_processor.pkb +++ b/source/core/ut_expectation_processor.pkb @@ -183,6 +183,7 @@ create or replace package body ut_expectation_processor as ); end; begin +-- dbms_output.put_line(a_call_stack); l_call_stack := cut_header_and_expectations( a_call_stack ); l_call_stack := cut_address_columns( l_call_stack ); l_call_stack := cut_framework_stack( l_call_stack ); diff --git a/source/create_grants.sql b/source/create_grants.sql index 111294cef..d2f51e121 100644 --- a/source/create_grants.sql +++ b/source/create_grants.sql @@ -88,6 +88,7 @@ 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 53e2bb65f..7b04dacd0 100644 --- a/source/create_synonyms.sql +++ b/source/create_synonyms.sql @@ -104,6 +104,7 @@ 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/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index 6f09f0392..40bcfbab0 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -16,41 +16,24 @@ create or replace type body ut_be_within as limitations under the License. */ - member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value) is - begin - self.distance_from_expected := a_distance_from_expected; - self.self_type := $$plsql_unit; - end; - constructor function ut_be_within(self in out nocopy ut_be_within, a_distance_from_expected number) return self as result is begin - init(ut_data_value_number(a_distance_from_expected)); + 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 - init(ut_data_value_dsinterval(a_distance_from_expected)); + 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 - init(ut_data_value_yminterval(a_distance_from_expected)); + self.init(ut_data_value_yminterval(a_distance_from_expected), $$plsql_unit); return; end; - member procedure of_(self in ut_be_within, a_expected number) is - l_result ut_be_within := 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 procedure of_(self in ut_be_within, a_expected date) is l_result ut_be_within := self; begin @@ -62,13 +45,6 @@ create or replace type body ut_be_within as end if; end; - member function of_(self in ut_be_within, a_expected number) return ut_be_within is - l_result ut_be_within := self; - begin - l_result.expected := ut_data_value_number(a_expected); - return l_result; - end; - member function of_(self in ut_be_within, a_expected date) return ut_be_within is l_result ut_be_within := self; begin @@ -96,7 +72,7 @@ create or replace type body ut_be_within as then treat(self.distance_from_expected as ut_data_value_dsinterval).data_value end; begin - return case when l_distance_ym is not null + return case when l_distance_ym is not null then l_actual between l_expected - l_distance_ym and l_expected + l_distance_ym else l_actual between l_expected - l_distance_ds and l_expected + l_distance_ds end; @@ -116,15 +92,14 @@ create or replace type body ut_be_within as end; overriding member function failure_message(a_actual ut_data_value) return varchar2 is - begin + 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 - l_result varchar2(32767); - begin + 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; + end; / diff --git a/source/expectations/matchers/ut_be_within.tps b/source/expectations/matchers/ut_be_within.tps index 55f32bc4e..5090d3414 100644 --- a/source/expectations/matchers/ut_be_within.tps +++ b/source/expectations/matchers/ut_be_within.tps @@ -1,4 +1,4 @@ -create or replace type ut_be_within under ut_comparison_matcher( +create or replace type ut_be_within under ut_be_within_pct( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -17,19 +17,11 @@ create or replace type ut_be_within under ut_comparison_matcher( */ - /** - * Holds information about mather options - */ - distance_from_expected ut_data_value, - member procedure init(self in out nocopy ut_be_within, a_distance_from_expected ut_data_value), 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 number), member procedure of_(self in ut_be_within, a_expected date), - member function of_(self in ut_be_within, a_expected number) return ut_be_within, member function of_(self in ut_be_within, a_expected date) 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 diff --git a/source/expectations/matchers/ut_be_within_pct.tpb b/source/expectations/matchers/ut_be_within_pct.tpb index 326197fe6..bf662c066 100644 --- a/source/expectations/matchers/ut_be_within_pct.tpb +++ b/source/expectations/matchers/ut_be_within_pct.tpb @@ -16,21 +16,45 @@ create or replace type body ut_be_within_pct as limitations under the License. */ - constructor function ut_be_within_pct(self in out nocopy ut_be_within_pct, a_distance_from_expected number) return self as result is + 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_distance_from_expected)); + 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 := treat(self.distance_from_expected as ut_data_value_number).data_value >= - ( - ((treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / - (treat(self.expected as ut_data_value_number).data_value)) ; + l_result := + treat(self.distance_from_expected as ut_data_value_number).data_value + >= ( ( treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / + treat(self.expected as ut_data_value_number).data_value; end if; else l_result := (self as ut_matcher).run_matcher(a_actual); @@ -38,5 +62,15 @@ create or replace type body ut_be_within_pct as 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; + end; / diff --git a/source/expectations/matchers/ut_be_within_pct.tps b/source/expectations/matchers/ut_be_within_pct.tps index b47c7a9fd..b1c7e4dfc 100644 --- a/source/expectations/matchers/ut_be_within_pct.tps +++ b/source/expectations/matchers/ut_be_within_pct.tps @@ -1,4 +1,4 @@ -create or replace type ut_be_within_pct under ut_be_within( +create or replace type ut_be_within_pct under ut_comparison_matcher( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -17,8 +17,18 @@ create or replace type ut_be_within_pct under ut_be_within( */ - constructor function ut_be_within_pct(self in out nocopy ut_be_within_pct, a_distance_from_expected number) return self as result, - overriding member function run_matcher(self in out nocopy ut_be_within_pct, a_actual ut_data_value) return boolean + /** + * 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 ) not final / diff --git a/source/install.sql b/source/install.sql index af639ac78..a3cf2c3d8 100644 --- a/source/install.sql +++ b/source/install.sql @@ -240,8 +240,8 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@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.tps' @@install_component.sql 'expectations/matchers/ut_be_within_pct.tps' +@@install_component.sql 'expectations/matchers/ut_be_within.tps' @@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' @@ -297,8 +297,8 @@ 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.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_contain.tpb' @@install_component.sql 'expectations/matchers/ut_have_count.tpb' @@install_component.sql 'expectations/matchers/ut_be_between.tpb' @@ -362,6 +362,7 @@ 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' diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index 82d8a7e5a..ee76cb8eb 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -56,6 +56,8 @@ 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; diff --git a/test/install_ut3_user_tests.sql b/test/install_ut3_user_tests.sql index 1330a7f75..8431c69ed 100644 --- a/test/install_ut3_user_tests.sql +++ b/test/install_ut3_user_tests.sql @@ -26,6 +26,7 @@ prompt Install user tests @@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 @@ -68,6 +69,7 @@ set define off @@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_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..728cdeec6 --- /dev/null +++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb @@ -0,0 +1,184 @@ +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( 2.987654321 ).to_be_within_pct( 1 ).of_(3); + expect_success; + + ut3_develop.ut.expect( 2.987654321 ).to_( ut3_develop.be_within_pct( 1 ).of_(3) ); + expect_success; + + ut3_develop.ut.expect( 2.987654321 ).not_to_be_within_pct( 0.1 ).of_(3); + expect_success; + + ut3_develop.ut.expect( 2.987654321 ).not_to( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + expect_success; + end; + + procedure failed_tests is + begin + ut3_develop.ut.expect( 2.987654321 ).to_be_within_pct( 0.1 ).of_(3); + expect_failure; + + ut3_develop.ut.expect( 2.987654321 ).to_( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + expect_failure; + + ut3_develop.ut.expect( 2.987654321 ).not_to_be_within_pct( 1 ).of_(3); + expect_failure; + + ut3_develop.ut.expect( 2.987654321 ).not_to( ut3_develop.be_within_pct( 1 ).of_(3) ); + expect_failure; + 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_pct(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_to_compile_for_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', + 'Actual (date) cannot be compared to Expected (number) using matcher ''be within pct''' + ); + 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..6203d48e3 --- /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_in_invalid_argument_types; + +end; +/ From 3cae9a2d75311abda3c8cdd736848615682dddd9 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 20 Jun 2020 22:20:28 +0100 Subject: [PATCH 19/35] Fixed test issue --- .../binary/test_to_be_within_pct.pkb | 17 ++++++----------- .../binary/test_to_be_within_pct.pks | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) 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 index 728cdeec6..a184c3728 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb @@ -143,20 +143,15 @@ create or replace package body test_to_be_within_pct is 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_pct(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); + 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_to_compile_for_types is + procedure fail_at_invalid_argument_types is begin test_to_be_within_error( 'to_be_within_pct','date', 'sysdate', 'date','sysdate', 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 index 6203d48e3..4b8f0cb4c 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within_pct.pks +++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pks @@ -16,7 +16,7 @@ create or replace package test_to_be_within_pct is procedure fail_for_number_not_within; --%test(fails at compile or run time for unsupported data-types ) - procedure fail_in_invalid_argument_types; + procedure fail_at_invalid_argument_types; end; / From 22549db1c0aaa2d34c43d8365de6e6023807247d Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 21 Jun 2020 12:11:58 +0100 Subject: [PATCH 20/35] Fixed stacktrace for failed expectations on chained matchers. --- source/core/ut_expectation_processor.pkb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/core/ut_expectation_processor.pkb b/source/core/ut_expectation_processor.pkb index 4bf15ee55..7e1217acf 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 @@ -183,7 +183,6 @@ create or replace package body ut_expectation_processor as ); end; begin --- dbms_output.put_line(a_call_stack); l_call_stack := cut_header_and_expectations( a_call_stack ); l_call_stack := cut_address_columns( l_call_stack ); l_call_stack := cut_framework_stack( l_call_stack ); From 1d771a546e1a081c07c1ad539624e6c67b2f97be Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 25 Jun 2020 20:31:51 +0100 Subject: [PATCH 21/35] Update timestamps No tests --- source/expectations/matchers/ut_be_within.tpb | 81 +++++++++++++++++++ source/expectations/matchers/ut_be_within.tps | 6 ++ .../expectations/binary/test_to_be_within.pkb | 6 ++ 3 files changed, 93 insertions(+) diff --git a/source/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index 40bcfbab0..7e90ff4e6 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -52,6 +52,60 @@ create or replace type body ut_be_within as return l_result; end; + member procedure of_(self in ut_be_within, a_expected timestamp) 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) 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; function l_result_from_number return boolean is @@ -78,12 +132,39 @@ create or replace type body ut_be_within as end; end; + function l_result_from_timestamp (a_distance ut_data_value) return boolean is + l_expected timestamp := case when self.expected is of ( ut_data_value_timestamp) then + treat(self.expected as ut_data_value_timestamp).data_value + when self.expected is of ( ut_data_value_timestamp_tz) then + treat(self.expected as ut_data_value_timestamp_tz).data_value + when self.expected is of ( ut_data_value_timestamp_ltz) then + treat(self.expected as ut_data_value_timestamp_ltz).data_value + end; + l_actual timestamp with time zone := treat(a_actual as ut_data_value_date).data_value; + l_distance_ym yminterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_yminterval) + then treat(self.distance_from_expected as ut_data_value_yminterval).data_value + end; + l_distance_ds dsinterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_dsinterval) + then treat(self.distance_from_expected as ut_data_value_dsinterval).data_value + end; + begin + return case when l_distance_ym is not null + then l_actual between l_expected - l_distance_ym and l_expected + l_distance_ym + else l_actual between l_expected - l_distance_ds and l_expected + l_distance_ds + end; + end; + + begin if self.expected.data_type = a_actual.data_type then if self.expected is of (ut_data_value_number) then l_result := l_result_from_number; elsif self.expected is of (ut_data_value_date)then l_result := l_result_from_date(self.distance_from_expected); + elsif self.expected is of (ut_data_value_timestamp_tz)then + l_result := l_result_from_date(self.distance_from_expected); + elsif self.expected is of (ut_data_value_timestamp_ltz)then + l_result := l_result_from_date(self.distance_from_expected); end if; else l_result := (self as ut_matcher).run_matcher(a_actual); diff --git a/source/expectations/matchers/ut_be_within.tps b/source/expectations/matchers/ut_be_within.tps index 5090d3414..0b14bce44 100644 --- a/source/expectations/matchers/ut_be_within.tps +++ b/source/expectations/matchers/ut_be_within.tps @@ -22,6 +22,12 @@ create or replace type ut_be_within under ut_be_within_pct( 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), + member function of_(self in ut_be_within, a_expected timestamp) 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 diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index b845bb26a..2ea90bd6b 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -74,6 +74,12 @@ create or replace package body test_to_be_within is 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_tz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', 'sysdate','''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']', 'sysdate+1','''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']', 'sysdate+200','''1-0''','interval year to month'); + test_to_be_within_success('to_be_within','timestamp_ltz_unconstrained', 'sysdate+200', 'sysdate','''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', ')'); From 363c333ba466eef38b57992f821afd397bb08d6a Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 27 Jun 2020 01:07:06 +0100 Subject: [PATCH 22/35] Fixed and simplified matcher --- .../data_values/ut_data_value_dsinterval.tps | 2 +- .../data_values/ut_data_value_yminterval.tps | 2 +- source/expectations/matchers/ut_be_within.tpb | 63 ++----------------- .../matchers/ut_be_within_helper.pkb | 41 ++++++++++++ .../matchers/ut_be_within_helper.pks | 24 +++++++ source/install.sql | 2 + source/uninstall_objects.sql | 2 + .../expectations/binary/test_to_be_within.pkb | 18 ++++-- 8 files changed, 90 insertions(+), 64 deletions(-) create mode 100644 source/expectations/matchers/ut_be_within_helper.pkb create mode 100644 source/expectations/matchers/ut_be_within_helper.pks diff --git a/source/expectations/data_values/ut_data_value_dsinterval.tps b/source/expectations/data_values/ut_data_value_dsinterval.tps index 114619bf2..09aa7ac0d 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_yminterval.tps b/source/expectations/data_values/ut_data_value_yminterval.tps index d20dfcad7..3144d205c 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 index 7e90ff4e6..c411c4f61 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -107,64 +107,13 @@ create or replace type body ut_be_within as end; overriding member function run_matcher(self in out nocopy ut_be_within, a_actual ut_data_value) return boolean is - l_result boolean; - function l_result_from_number return boolean is - l_expected number := treat(self.expected as ut_data_value_number).data_value; - l_actual number := treat(a_actual as ut_data_value_number).data_value; - l_distance number := treat(self.distance_from_expected as ut_data_value_number).data_value; - begin - return abs(l_expected - l_actual) <= l_distance; - end; - - function l_result_from_date(a_distance ut_data_value) return boolean is - l_expected date := treat(self.expected as ut_data_value_date).data_value; - l_actual date := treat(a_actual as ut_data_value_date).data_value; - l_distance_ym yminterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_yminterval) - then treat(self.distance_from_expected as ut_data_value_yminterval).data_value - end; - l_distance_ds dsinterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_dsinterval) - then treat(self.distance_from_expected as ut_data_value_dsinterval).data_value - end; - begin - return case when l_distance_ym is not null - then l_actual between l_expected - l_distance_ym and l_expected + l_distance_ym - else l_actual between l_expected - l_distance_ds and l_expected + l_distance_ds - end; - end; - - function l_result_from_timestamp (a_distance ut_data_value) return boolean is - l_expected timestamp := case when self.expected is of ( ut_data_value_timestamp) then - treat(self.expected as ut_data_value_timestamp).data_value - when self.expected is of ( ut_data_value_timestamp_tz) then - treat(self.expected as ut_data_value_timestamp_tz).data_value - when self.expected is of ( ut_data_value_timestamp_ltz) then - treat(self.expected as ut_data_value_timestamp_ltz).data_value - end; - l_actual timestamp with time zone := treat(a_actual as ut_data_value_date).data_value; - l_distance_ym yminterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_yminterval) - then treat(self.distance_from_expected as ut_data_value_yminterval).data_value - end; - l_distance_ds dsinterval_unconstrained := case when self.distance_from_expected is of ( ut_data_value_dsinterval) - then treat(self.distance_from_expected as ut_data_value_dsinterval).data_value - end; - begin - return case when l_distance_ym is not null - then l_actual between l_expected - l_distance_ym and l_expected + l_distance_ym - else l_actual between l_expected - l_distance_ds and l_expected + l_distance_ds - end; - end; - - - begin + 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 := l_result_from_number; - elsif self.expected is of (ut_data_value_date)then - l_result := l_result_from_date(self.distance_from_expected); - elsif self.expected is of (ut_data_value_timestamp_tz)then - l_result := l_result_from_date(self.distance_from_expected); - elsif self.expected is of (ut_data_value_timestamp_ltz)then - l_result := l_result_from_date(self.distance_from_expected); + if self.expected is of (ut_data_value_date, ut_data_value_number, ut_data_value_timestamp, ut_data_value_timestamp_tz, ut_data_value_timestamp_ltz) then + l_result := ut_be_within_helper.values_within_abs_distance(self.expected, a_actual, self.distance_from_expected) ; + else + l_result := (self as ut_matcher).run_matcher(a_actual); end if; else l_result := (self as ut_matcher).run_matcher(a_actual); 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..a958c3e0f --- /dev/null +++ b/source/expectations/matchers/ut_be_within_helper.pkb @@ -0,0 +1,41 @@ +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_value_1 ut_data_value, a_value_2 ut_data_value, a_distance ut_data_value + ) return boolean is + l_result boolean; + begin + execute immediate q'[ + begin + :result := + treat(:a_value_1 as ut3_develop.]'||a_value_1.self_type||q'[).data_value + between + treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value + - treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value + and + treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value + + treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value; + end; + ]' + using out l_result, a_value_1, a_value_2, a_distance; + return l_result; + 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..0cb146a98 --- /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_value_1 ut_data_value, a_value_2 ut_data_value, a_distance ut_data_value + ) return boolean; + +end; +/ diff --git a/source/install.sql b/source/install.sql index a3cf2c3d8..8a855f817 100644 --- a/source/install.sql +++ b/source/install.sql @@ -242,6 +242,7 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@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' @@ -299,6 +300,7 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@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' diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index ee76cb8eb..84d319f96 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -148,6 +148,8 @@ 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/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index 2ea90bd6b..ae6220d2a 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -75,11 +75,19 @@ create or replace package body test_to_be_within is 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_tz_unconstrained', q'[TIMESTAMP '2017-08-09 07:00:00 -7:00']', 'sysdate','''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']', 'sysdate+1','''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']', 'sysdate+200','''1-0''','interval year to month'); - test_to_be_within_success('to_be_within','timestamp_ltz_unconstrained', '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', ')'); From 0ea892522cad433a18664e20da41d2e559157d90 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 28 Jun 2020 12:15:37 +0100 Subject: [PATCH 23/35] Fixed native dynamic SQL types compatibility for 11g --- .../matchers/ut_be_within_helper.pkb | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/source/expectations/matchers/ut_be_within_helper.pkb b/source/expectations/matchers/ut_be_within_helper.pkb index a958c3e0f..03f88e3a4 100644 --- a/source/expectations/matchers/ut_be_within_helper.pkb +++ b/source/expectations/matchers/ut_be_within_helper.pkb @@ -19,22 +19,26 @@ create or replace package body ut_be_within_helper as function values_within_abs_distance( a_value_1 ut_data_value, a_value_2 ut_data_value, a_distance ut_data_value ) return boolean is - l_result boolean; + l_result integer; begin execute immediate q'[ begin :result := - treat(:a_value_1 as ut3_develop.]'||a_value_1.self_type||q'[).data_value - between - treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value - - treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value - and - treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value - + treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value; + case + when + treat(:a_value_1 as ut3_develop.]'||a_value_1.self_type||q'[).data_value + between + treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value + - treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value + and + treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value + + treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value + then 1 + end; end; ]' using out l_result, a_value_1, a_value_2, a_distance; - return l_result; + return l_result > 0; end; end; From 7c01afbcbe5e7fba235dba49d1eb9d693bd4157f Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 28 Jun 2020 12:21:03 +0100 Subject: [PATCH 24/35] Fixed native dynamic SQL types compatibility for 11g --- source/expectations/matchers/ut_be_within_helper.pkb | 1 + 1 file changed, 1 insertion(+) diff --git a/source/expectations/matchers/ut_be_within_helper.pkb b/source/expectations/matchers/ut_be_within_helper.pkb index 03f88e3a4..aecaf7179 100644 --- a/source/expectations/matchers/ut_be_within_helper.pkb +++ b/source/expectations/matchers/ut_be_within_helper.pkb @@ -34,6 +34,7 @@ create or replace package body ut_be_within_helper as treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value + treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value then 1 + else 0 end; end; ]' From 590fb38c589b661a07488310d6a1113f031bbe6c Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 28 Jan 2022 23:20:04 +0200 Subject: [PATCH 25/35] Improving test stability (flaky tests) --- test/ut3_tester_helper/coverage_helper.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 5e2642ae2d0b8304bc8132a1015aaa08cf07e1ab Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 28 Jan 2022 23:23:12 +0200 Subject: [PATCH 26/35] Removing reference to ut3_develop schema. Added sql-injection check. --- source/expectations/matchers/ut_be_within_helper.pkb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/expectations/matchers/ut_be_within_helper.pkb b/source/expectations/matchers/ut_be_within_helper.pkb index aecaf7179..87fb2940b 100644 --- a/source/expectations/matchers/ut_be_within_helper.pkb +++ b/source/expectations/matchers/ut_be_within_helper.pkb @@ -26,13 +26,13 @@ create or replace package body ut_be_within_helper as :result := case when - treat(:a_value_1 as ut3_develop.]'||a_value_1.self_type||q'[).data_value + treat(:a_value_1 as ]'||dbms_assert.sql_object_name(a_value_1.self_type)||q'[).data_value between - treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value - - treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value + treat(:a_value_2 as ]'||dbms_assert.sql_object_name(a_value_2.self_type)||q'[).data_value + - treat(:a_distance as ]'||dbms_assert.sql_object_name(a_distance.self_type)||q'[).data_value and - treat(:a_value_2 as ut3_develop.]'||a_value_2.self_type||q'[).data_value - + treat(:a_distance as ut3_develop.]'||a_distance.self_type||q'[).data_value + treat(:a_value_2 as ]'||dbms_assert.sql_object_name(a_value_2.self_type)||q'[).data_value + + treat(:a_distance as ]'||dbms_assert.sql_object_name(a_distance.self_type)||q'[).data_value then 1 else 0 end; From ed06e332faedcc77b1e67250faca258e11c7b4b3 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 28 Jan 2022 23:42:01 +0200 Subject: [PATCH 27/35] Relaxed sql-injection check to work with 11g2 --- source/expectations/matchers/ut_be_within_helper.pkb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/expectations/matchers/ut_be_within_helper.pkb b/source/expectations/matchers/ut_be_within_helper.pkb index 87fb2940b..14444ea3e 100644 --- a/source/expectations/matchers/ut_be_within_helper.pkb +++ b/source/expectations/matchers/ut_be_within_helper.pkb @@ -26,13 +26,13 @@ create or replace package body ut_be_within_helper as :result := case when - treat(:a_value_1 as ]'||dbms_assert.sql_object_name(a_value_1.self_type)||q'[).data_value + treat(:a_value_1 as ]'||dbms_assert.simple_sql_name(a_value_1.self_type)||q'[).data_value between - treat(:a_value_2 as ]'||dbms_assert.sql_object_name(a_value_2.self_type)||q'[).data_value - - treat(:a_distance as ]'||dbms_assert.sql_object_name(a_distance.self_type)||q'[).data_value + treat(:a_value_2 as ]'||dbms_assert.simple_sql_name(a_value_2.self_type)||q'[).data_value + - treat(:a_distance as ]'||dbms_assert.simple_sql_name(a_distance.self_type)||q'[).data_value and - treat(:a_value_2 as ]'||dbms_assert.sql_object_name(a_value_2.self_type)||q'[).data_value - + treat(:a_distance as ]'||dbms_assert.sql_object_name(a_distance.self_type)||q'[).data_value + treat(:a_value_2 as ]'||dbms_assert.simple_sql_name(a_value_2.self_type)||q'[).data_value + + treat(:a_distance as ]'||dbms_assert.simple_sql_name(a_distance.self_type)||q'[).data_value then 1 else 0 end; From 38f3cbc1ff2ea87627e6744481715fa6571ad36a Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 31 Jan 2022 01:48:12 +0200 Subject: [PATCH 28/35] Fixed issues with comparison of dates×tamps using interval year-month Improved error handling for null values and incompatible datatypes Improved handling of negative dates (BC) Improved reporting of interval text value Improved datatypes to handle large&small precissions for timestamps --- docs/userguide/expectations.md | 38 ++--- source/core/ut_utils.pkb | 33 +++-- source/core/ut_utils.pks | 6 +- .../data_values/ut_data_value.tps | 1 + .../data_values/ut_data_value_blob.tpb | 1 + .../data_values/ut_data_value_boolean.tpb | 1 + .../data_values/ut_data_value_clob.tpb | 1 + .../data_values/ut_data_value_date.tpb | 1 + .../data_values/ut_data_value_dsinterval.tpb | 1 + .../data_values/ut_data_value_number.tpb | 1 + .../data_values/ut_data_value_refcursor.tpb | 1 + .../data_values/ut_data_value_timestamp.tpb | 1 + .../ut_data_value_timestamp_ltz.tpb | 1 + .../ut_data_value_timestamp_tz.tpb | 1 + .../data_values/ut_data_value_varchar2.tpb | 1 + .../data_values/ut_data_value_xmltype.tpb | 1 + .../data_values/ut_data_value_yminterval.tpb | 1 + source/expectations/matchers/ut_be_within.tpb | 46 +++--- source/expectations/matchers/ut_be_within.tps | 6 +- .../matchers/ut_be_within_helper.pkb | 33 +++-- .../matchers/ut_be_within_helper.pks | 2 +- .../matchers/ut_be_within_pct.tpb | 13 +- .../matchers/ut_be_within_pct.tps | 5 +- test/ut3_tester/core/test_ut_utils.pkb | 8 +- test/ut3_user/api/test_ut_run.pkb | 42 +++--- .../expectations/binary/test_to_be_within.pkb | 136 +++++++++++++++++- .../expectations/binary/test_to_be_within.pks | 29 +++- .../binary/test_to_be_within_pct.pkb | 2 +- .../reporters/test_debug_reporter.pkb | 2 +- 29 files changed, 312 insertions(+), 103 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 851eb9955..833235c24 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -316,25 +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 | -| **be_within().of_()** | | | | x | x | | | | | | | | | | | -| **be_within_pct().of()**| | | | | 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 | | | | | | | | | | | +| **be_within_pct().of_()** | | | | | x | | | | | | | | | | | # Expecting exceptions diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 1c1943f1d..655b20d3d 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -919,12 +919,20 @@ create or replace package body ut_utils is when l_minute > 1 then ' '||l_minute ||' minutes' end || case - when l_second = 1 then ' '||l_second ||' second' - when l_second > 1 then ' '||l_second ||' seconds' - end; - return trim(leading ' ' from l_result); + 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); @@ -935,10 +943,17 @@ create or replace package body ut_utils is when l_year > 1 then l_year ||' years' end || case - when l_month = 1 then ' '||l_month ||' month' - when l_month > 1 then ' '||l_month ||' months' - end; - return trim(leading ' ' from l_result); + 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; diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 228500396..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'; 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 fd6b03234..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; 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 df4a46a5c..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; diff --git a/source/expectations/matchers/ut_be_within.tpb b/source/expectations/matchers/ut_be_within.tpb index c411c4f61..e2aa792d0 100644 --- a/source/expectations/matchers/ut_be_within.tpb +++ b/source/expectations/matchers/ut_be_within.tpb @@ -39,9 +39,9 @@ create or replace type body ut_be_within as 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 ); + l_result.expectation.not_to(l_result); else - l_result.expectation.to_(l_result ); + l_result.expectation.to_(l_result); end if; end; @@ -51,33 +51,33 @@ create or replace type body ut_be_within as l_result.expected := ut_data_value_date(a_expected); return l_result; end; - - member procedure of_(self in ut_be_within, a_expected timestamp) is + + 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 ); + l_result.expectation.not_to(l_result); else - l_result.expectation.to_(l_result ); + l_result.expectation.to_(l_result); end if; end; - member function of_(self in ut_be_within, a_expected timestamp) return ut_be_within is + 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; + 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 ); + l_result.expectation.not_to(l_result); else - l_result.expectation.to_(l_result ); + l_result.expectation.to_(l_result); end if; end; @@ -86,16 +86,16 @@ create or replace type body ut_be_within as begin l_result.expected := ut_data_value_timestamp_tz(a_expected); return l_result; - end; - + 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 ); + l_result.expectation.not_to(l_result); else - l_result.expectation.to_(l_result ); + l_result.expectation.to_(l_result); end if; end; @@ -104,17 +104,19 @@ create or replace type body ut_be_within as begin l_result.expected := ut_data_value_timestamp_ltz(a_expected); return l_result; - end; - + 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 then - if self.expected is of (ut_data_value_date, ut_data_value_number, ut_data_value_timestamp, ut_data_value_timestamp_tz, ut_data_value_timestamp_ltz) then - l_result := ut_be_within_helper.values_within_abs_distance(self.expected, a_actual, self.distance_from_expected) ; - else - l_result := (self as ut_matcher).run_matcher(a_actual); - end if; + 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; diff --git a/source/expectations/matchers/ut_be_within.tps b/source/expectations/matchers/ut_be_within.tps index 0b14bce44..576f9ff37 100644 --- a/source/expectations/matchers/ut_be_within.tps +++ b/source/expectations/matchers/ut_be_within.tps @@ -1,4 +1,4 @@ -create or replace type ut_be_within under ut_be_within_pct( +create or replace type ut_be_within force under ut_be_within_pct( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -22,8 +22,8 @@ create or replace type ut_be_within under ut_be_within_pct( 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), - member function of_(self in ut_be_within, a_expected timestamp) 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), diff --git a/source/expectations/matchers/ut_be_within_helper.pkb b/source/expectations/matchers/ut_be_within_helper.pkb index 14444ea3e..5dd82baa2 100644 --- a/source/expectations/matchers/ut_be_within_helper.pkb +++ b/source/expectations/matchers/ut_be_within_helper.pkb @@ -17,28 +17,37 @@ create or replace package body ut_be_within_helper as */ function values_within_abs_distance( - a_value_1 ut_data_value, a_value_2 ut_data_value, a_distance ut_data_value + 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 - execute immediate q'[ + 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 - treat(:a_value_1 as ]'||dbms_assert.simple_sql_name(a_value_1.self_type)||q'[).data_value - between - treat(:a_value_2 as ]'||dbms_assert.simple_sql_name(a_value_2.self_type)||q'[).data_value - - treat(:a_distance as ]'||dbms_assert.simple_sql_name(a_distance.self_type)||q'[).data_value - and - treat(:a_value_2 as ]'||dbms_assert.simple_sql_name(a_value_2.self_type)||q'[).data_value - + treat(:a_distance as ]'||dbms_assert.simple_sql_name(a_distance.self_type)||q'[).data_value + when + ]'||l_formula||q'[ then 1 else 0 end; end; - ]' - using out l_result, a_value_1, a_value_2, a_distance; + ]'; + execute immediate l_code + using a_actual, a_expected, a_distance, out l_result; return l_result > 0; end; diff --git a/source/expectations/matchers/ut_be_within_helper.pks b/source/expectations/matchers/ut_be_within_helper.pks index 0cb146a98..41737cc8f 100644 --- a/source/expectations/matchers/ut_be_within_helper.pks +++ b/source/expectations/matchers/ut_be_within_helper.pks @@ -17,7 +17,7 @@ create or replace package ut_be_within_helper authid definer as */ function values_within_abs_distance( - a_value_1 ut_data_value, a_value_2 ut_data_value, a_distance ut_data_value + 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 index bf662c066..fabab2d09 100644 --- a/source/expectations/matchers/ut_be_within_pct.tpb +++ b/source/expectations/matchers/ut_be_within_pct.tpb @@ -33,9 +33,9 @@ create or replace type body ut_be_within_pct as 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 ); + l_result.expectation.not_to(l_result); else - l_result.expectation.to_(l_result ); + l_result.expectation.to_(l_result); end if; end; @@ -72,5 +72,14 @@ create or replace type body ut_be_within_pct as 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 index b1c7e4dfc..499e9a2d8 100644 --- a/source/expectations/matchers/ut_be_within_pct.tps +++ b/source/expectations/matchers/ut_be_within_pct.tps @@ -1,4 +1,4 @@ -create or replace type ut_be_within_pct under ut_comparison_matcher( +create or replace type ut_be_within_pct force under ut_comparison_matcher( /* utPLSQL - Version 3 Copyright 2016 - 2019 utPLSQL Project @@ -28,7 +28,8 @@ create or replace type ut_be_within_pct under ut_comparison_matcher( 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 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/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 61bc61a84..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; diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index e3af7c5ad..19c69c74e 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -1272,7 +1272,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(current_timestamp,'syyyy-mm-dd"T"hh24:mi') ||'%APPLICATION_INFO:MODULE=utPLSQL' ||'%APPLICATION_INFO:ACTION=check_context' ||'%APPLICATION_INFO:CLIENT_INFO=before_suite%' @@ -1287,14 +1287,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(current_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(current_timestamp,'syyyy-mm-dd"T"hh24:mi') ||'%APPLICATION_INFO:MODULE=utPLSQL' ||'%APPLICATION_INFO:ACTION=check_context' ||'%APPLICATION_INFO:CLIENT_INFO=before_context%' @@ -1308,17 +1308,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(current_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(current_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(current_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 +1331,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(current_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(current_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(current_timestamp,'syyyy-mm-dd"T"hh24:mi') ||'%APPLICATION_INFO:MODULE=utPLSQL' ||'%APPLICATION_INFO:ACTION=check_context' ||'%APPLICATION_INFO:CLIENT_INFO=before_test%' @@ -1354,17 +1354,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(current_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(current_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(current_timestamp,'syyyy-mm-dd"T"hh24:mi') ||'%APPLICATION_INFO:MODULE=utPLSQL' ||'%APPLICATION_INFO:ACTION=check_context' ||'%APPLICATION_INFO:CLIENT_INFO=the_test%' @@ -1377,17 +1377,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(current_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(current_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(current_timestamp,'syyyy-mm-dd"T"hh24:mi') ||'%APPLICATION_INFO:MODULE=utPLSQL' ||'%APPLICATION_INFO:ACTION=check_context' ||'%APPLICATION_INFO:CLIENT_INFO=after_test%' @@ -1400,17 +1400,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(current_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(current_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(current_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 +1423,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(current_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(current_timestamp,'syyyy-mm-dd"T"hh24:mi') ||'%APPLICATION_INFO:MODULE=utPLSQL' ||'%APPLICATION_INFO:ACTION=check_context' ||'%APPLICATION_INFO:CLIENT_INFO=after_context%' @@ -1447,7 +1447,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(current_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 index ae6220d2a..5213bd362 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -62,7 +62,13 @@ create or replace package body test_to_be_within is 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).to_equal(0); + 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; @@ -94,6 +100,9 @@ create or replace package body test_to_be_within is 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'); @@ -106,6 +115,9 @@ create or replace package body test_to_be_within is 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', ')'); end; procedure failed_tests is @@ -220,6 +232,126 @@ create or replace package body test_to_be_within is 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 index b2f456584..966e9baaf 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pks +++ b/test/ut3_user/expectations/binary/test_to_be_within.pks @@ -9,7 +9,7 @@ create or replace package test_to_be_within is --%test(gives success for values within a distance) procedure success_tests; - --%test(gives failure when number is not within distance) + --%test(gives failure when value is not within distance) procedure failed_tests; --%test(returns well formatted failure message when expectation fails) @@ -30,5 +30,32 @@ create or replace package test_to_be_within is --%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 index a184c3728..d1e71943a 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb @@ -171,7 +171,7 @@ create or replace package body test_to_be_within_pct is test_to_be_within_fail( 'to_be_within_pct','date', 'sysdate', 'number','1', '1','number', - 'Actual (date) cannot be compared to Expected (number) using matcher ''be within pct''' + 'Matcher ''be within pct'' cannot be used to compare Actual (date) with Expected (number) using distance (number).' ); 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+' || From 86e84c8b349ddc4c0b488f8efada429c08271210 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 31 Jan 2022 23:04:57 +0200 Subject: [PATCH 29/35] Improving code coverage. --- source/expectations/ut_expectation.tpb | 42 +++++++++---------- .../expectations/test_expectations_cursor.pkb | 6 +-- .../expectations/test_expectations_json.pkb | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index 95a117bc1..cc5bfe0ca 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -718,44 +718,44 @@ create or replace type body ut_expectation as return l_result; end; - member function to_be_within_pct(a_dist natural) 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; + member function to_be_within_pct(a_dist natural) 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 natural) return ut_be_within is - l_result ut_matcher; + l_result ut_be_within; begin - l_result := ut_be_within(a_dist).negated(); + l_result := treat( ut_be_within(a_dist).negated() as ut_be_within); l_result.expectation := self; - return treat(l_result as ut_be_within); + return l_result; end; member function not_to_be_within(a_dist dsinterval_unconstrained) return ut_be_within is - l_result ut_matcher; + l_result ut_be_within; begin - l_result := ut_be_within(a_dist).negated(); + l_result := treat( ut_be_within(a_dist).negated() as ut_be_within); l_result.expectation := self; - return treat(l_result as ut_be_within); + return l_result; end; member function not_to_be_within(a_dist yminterval_unconstrained) return ut_be_within is - l_result ut_matcher; + l_result ut_be_within; begin - l_result := ut_be_within(a_dist).negated(); + l_result := treat( ut_be_within(a_dist).negated() as ut_be_within); l_result.expectation := self; - return treat(l_result as ut_be_within); + return l_result; end; - member function not_to_be_within_pct(a_dist natural) return ut_be_within_pct is - l_result ut_matcher; - begin - l_result := ut_be_within_pct(a_dist).negated(); - l_result.expectation := self; - return treat(l_result as ut_be_within_pct); + member function not_to_be_within_pct(a_dist natural) 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/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; From 718ac0d45b52099d2dfa0a8f2f934cd8e758a00d Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Tue, 1 Feb 2022 00:14:48 +0200 Subject: [PATCH 30/35] Improved test stability. Added human-readable reporting of tests run-time into `ut_documentation_reporter`. --- .../reporters/ut_documentation_reporter.tpb | 2 +- test/ut3_user/api/test_ut_run.pkb | 44 ++++++++++--------- 2 files changed, 24 insertions(+), 22 deletions(-) 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/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 19c69c74e..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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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,'syyyy-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%' From 6dbef20a5b0d7c67d709bd5ea519e5a27b1f049e Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Tue, 1 Feb 2022 00:29:16 +0200 Subject: [PATCH 31/35] Fixing build process to build using develop branch as testing framework for Pull Requests --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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} From 25b55b4cb776e6a4aeb019297e7be12ff6699784 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Tue, 1 Feb 2022 00:44:49 +0200 Subject: [PATCH 32/35] Improving test coverage. --- test/ut3_user/expectations/binary/test_to_be_within.pkb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index 5213bd362..d490a8280 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -118,6 +118,9 @@ create or replace package body test_to_be_within is 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 From 5b5a5c017d70e0a17ffdf872850e757f69ed9ea9 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Tue, 1 Feb 2022 01:58:44 +0200 Subject: [PATCH 33/35] Improving matcher documentation --- docs/userguide/expectations.md | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 833235c24..88c244977 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -333,8 +333,8 @@ The matrix below illustrates the data types supported by different matchers. | **be_like** | | | X | | | | | | X | | | | | | | | **be_empty** | X | | X | | | | | | | | | X | X | | X | | **have_count** | | | | | | | | | | | | X | X | | X | -| **be_within().of_()** | | | | x | x | | | | | | | | | | | -| **be_within_pct().of_()** | | | | | x | | | | | | | | | | | +| **be_within().of_()** | | | | X | X | X | X | X | | | | | | | | +| **be_within_pct().of_()** | | | | | X | | | | | | | | | | | # Expecting exceptions @@ -1096,17 +1096,34 @@ SUCCESS ## to_be_within of -This matcher is created to determine wheter expected value is approximately equal or "close" to another value. +This matcher determines wheter expected value is within range from another value. -Matcher will allow to compare numbers as well as dates. +The logical formual used for calcuating the matcher is: +`abs( expected - actual ) <= distance` +The matcher will succeed if the `expected` and `actual` are not more than `distance` apart from each other. -When comparing a number the tolerance / distance can be expressed as another postive number or a percentage. +The matcher works with data-type 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. -When comparing a two dates tolerance can be expressed in interval time either Day-To-Second or Year-To-Month. +| 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 | -Matcher for numbers will calculate a absolute distance between expected and actual and check whether that value is within a tolerance. -When comparing a date a distance is measured in interval, the check is done that actual value is within date range of expected taking into account interval plus and minus. +The distance can be expressed as a postive number or positive 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 distance of `interval '0-1' year to month` will actuall be successful if the distance isnot greater than a month and a half. +> This is due to how oracle evaluates conversion between timestamp difference converted to `year to month interval`. **Example 1.** ```sql From 7fec0f998c59fcd2fac6f4d97f508b53bd6d3d15 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 3 Feb 2022 01:03:18 +0200 Subject: [PATCH 34/35] Added tests for 0 value of actual and expected and actual greater than expected (not only smaller). Updated documentation. --- docs/userguide/expectations.md | 43 +++++++++++-------- .../matchers/ut_be_within_pct.tpb | 5 +-- .../binary/test_to_be_within_pct.pkb | 36 ++++++++++++++++ 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 88c244977..a74e2576e 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1096,13 +1096,17 @@ SUCCESS ## to_be_within of -This matcher determines wheter expected value is within range from another value. +Determines wheter expected value is within range (tolerance) from another value. -The logical formual used for calcuating the matcher is: -`abs( expected - actual ) <= distance` -The matcher will succeed if the `expected` and `actual` are not more than `distance` apart from each other. +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-type number, date, timestamp, timestamp with time zone, timestamp with local time zone. +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 | @@ -1118,12 +1122,13 @@ The data-types of compared values must match exactly and if type does not match, | timestamp with local time zone | interval year to month | -The distance can be expressed as a postive number or positive interval. +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 distance of `interval '0-1' year to month` will actuall be successful if the distance isnot greater than a month and a half. -> This is due to how oracle evaluates conversion between timestamp difference converted to `year to month 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 @@ -1172,17 +1177,14 @@ Failures: ## to_be_within_pct of -This matcher is created to determine wheter expected value is approximately equal or "close" to another value within percentage value of expected. - -Matcher will allow to compare numbers. - -When comparing a number the tolerance / distance can be expressed as another postive number or a percentage. - -When comparing a two dates tolerance can be expressed in interval time either Day-To-Second or Year-To-Month. - -Matcher for numbers will calculate a absolute distance between expected and actual and check whether that value is within a tolerance. +Determines wheter actual value is within percentage range of expected value. +The matcher only works with `number` data-type. -When comparing a date a distance is measured in interval, the check is done that actual value is within date range of expected taking into account interval plus and minus. +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 @@ -1192,6 +1194,11 @@ 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/expectations/matchers/ut_be_within_pct.tpb b/source/expectations/matchers/ut_be_within_pct.tpb index fabab2d09..8b280ffff 100644 --- a/source/expectations/matchers/ut_be_within_pct.tpb +++ b/source/expectations/matchers/ut_be_within_pct.tpb @@ -52,9 +52,8 @@ create or replace type body ut_be_within_pct as if self.expected.data_type = a_actual.data_type then if self.expected is of (ut_data_value_number) then l_result := - treat(self.distance_from_expected as ut_data_value_number).data_value - >= ( ( treat(self.expected as ut_data_value_number).data_value - treat(a_actual as ut_data_value_number).data_value ) * 100 ) / - treat(self.expected as ut_data_value_number).data_value; + 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); 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 index d1e71943a..5214b540c 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb @@ -125,6 +125,27 @@ create or replace package body test_to_be_within_pct is ut3_develop.ut.expect( 2.987654321 ).not_to( ut3_develop.be_within_pct( 0.1 ).of_(3) ); expect_success; + + ut3_develop.ut.expect( 3.012345679 ).to_be_within_pct( 1 ).of_(3); + expect_success; + + ut3_develop.ut.expect( 3.012345679 ).to_( ut3_develop.be_within_pct( 1 ).of_(3) ); + expect_success; + + ut3_develop.ut.expect( 3.012345679 ).not_to_be_within_pct( 0.1 ).of_(3); + expect_success; + + ut3_develop.ut.expect( 3.012345679 ).not_to( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + expect_success; + + ut3_develop.ut.expect( 0 ).to_be_within_pct( 10 ).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 @@ -140,6 +161,21 @@ create or replace package body test_to_be_within_pct is ut3_develop.ut.expect( 2.987654321 ).not_to( ut3_develop.be_within_pct( 1 ).of_(3) ); expect_failure; + + ut3_develop.ut.expect( 3.012345679 ).to_be_within_pct( 0.1 ).of_(3); + expect_failure; + + ut3_develop.ut.expect( 3.012345679 ).to_( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + expect_failure; + + ut3_develop.ut.expect( 3.012345679 ).not_to_be_within_pct( 1 ).of_(3); + expect_failure; + + ut3_develop.ut.expect( 3.012345679 ).not_to( ut3_develop.be_within_pct( 1 ).of_(3) ); + expect_failure; + + ut3_develop.ut.expect( 0.1 ).to_be_within_pct( 10 ).of_( 0 ); + expect_failure; end; procedure fail_for_number_not_within is From fd7ef9c14111a48e03fff7851f990c7192539170 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 3 Feb 2022 01:39:09 +0200 Subject: [PATCH 35/35] Fixed issues with precission of distance. `NATURAL` is a subtype of integer and cannot be used to express a decimal distace value. Improved tests coverage for various scenarios. --- source/expectations/ut_expectation.tpb | 8 ++-- source/expectations/ut_expectation.tps | 10 ++--- .../binary/test_to_be_within_pct.pkb | 42 +++++++++++-------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index cc5bfe0ca..dabe8fbff 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -694,7 +694,7 @@ create or replace type body ut_expectation as self.not_to( ut_contain(a_expected).negated() ); end; - member function to_be_within(a_dist natural) return ut_be_within is + 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); @@ -718,7 +718,7 @@ create or replace type body ut_expectation as return l_result; end; - member function to_be_within_pct(a_dist natural) return ut_be_within_pct is + 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); @@ -726,7 +726,7 @@ create or replace type body ut_expectation as return l_result; end; - member function not_to_be_within(a_dist natural) return ut_be_within is + 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); @@ -750,7 +750,7 @@ create or replace type body ut_expectation as return l_result; end; - member function not_to_be_within_pct(a_dist natural) return ut_be_within_pct is + 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); diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps index ce58fc2e0..86edc9cee 100644 --- a/source/expectations/ut_expectation.tps +++ b/source/expectations/ut_expectation.tps @@ -1,4 +1,4 @@ -create or replace type ut_expectation under ut_expectation_base( +create or replace type ut_expectation force under ut_expectation_base( /* utPLSQL - Version 3 Copyright 2016 - 2021 utPLSQL Project @@ -164,14 +164,14 @@ create or replace type ut_expectation under ut_expectation_base( member procedure 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 natural) return ut_be_within, + 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 natural) return ut_be_within_pct, - member function not_to_be_within(a_dist natural) 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 natural) return ut_be_within_pct + member function not_to_be_within_pct(a_dist number) return ut_be_within_pct ) not final / 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 index 5214b540c..da634d90e 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within_pct.pkb @@ -114,31 +114,31 @@ create or replace package body test_to_be_within_pct is procedure success_tests is begin - ut3_develop.ut.expect( 2.987654321 ).to_be_within_pct( 1 ).of_(3); + ut3_develop.ut.expect( 1 ).to_be_within_pct( 0.01 ).of_(1.0001); expect_success; - ut3_develop.ut.expect( 2.987654321 ).to_( ut3_develop.be_within_pct( 1 ).of_(3) ); + ut3_develop.ut.expect( 1.0001 ).to_( ut3_develop.be_within_pct( 0.01 ).of_(1) ); expect_success; - ut3_develop.ut.expect( 2.987654321 ).not_to_be_within_pct( 0.1 ).of_(3); + ut3_develop.ut.expect( 1.0002 ).not_to_be_within_pct( 0.01 ).of_(1); expect_success; - ut3_develop.ut.expect( 2.987654321 ).not_to( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + ut3_develop.ut.expect( 1 ).not_to( ut3_develop.be_within_pct( 0.01 ).of_(1.0002) ); expect_success; - ut3_develop.ut.expect( 3.012345679 ).to_be_within_pct( 1 ).of_(3); + ut3_develop.ut.expect( 1.0001 ).to_be_within_pct( -0.01 ).of_(1); expect_success; - ut3_develop.ut.expect( 3.012345679 ).to_( ut3_develop.be_within_pct( 1 ).of_(3) ); + ut3_develop.ut.expect( 1 ).to_( ut3_develop.be_within_pct( -0.01 ).of_(1.0001) ); expect_success; - ut3_develop.ut.expect( 3.012345679 ).not_to_be_within_pct( 0.1 ).of_(3); + ut3_develop.ut.expect( 1.00000001 ).not_to_be_within_pct( 0 ).of_(1); expect_success; - ut3_develop.ut.expect( 3.012345679 ).not_to( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + 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( 10 ).of_( 0 ); + 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 ); @@ -150,31 +150,37 @@ create or replace package body test_to_be_within_pct is procedure failed_tests is begin - ut3_develop.ut.expect( 2.987654321 ).to_be_within_pct( 0.1 ).of_(3); + ut3_develop.ut.expect( 1 ).not_to_be_within_pct( 0.01 ).of_(1.0001); expect_failure; - ut3_develop.ut.expect( 2.987654321 ).to_( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + ut3_develop.ut.expect( 1.0001 ).not_to( ut3_develop.be_within_pct( 0.01 ).of_(1) ); expect_failure; - ut3_develop.ut.expect( 2.987654321 ).not_to_be_within_pct( 1 ).of_(3); + ut3_develop.ut.expect( 1.0002 ).to_be_within_pct( 0.01 ).of_(1); expect_failure; - ut3_develop.ut.expect( 2.987654321 ).not_to( ut3_develop.be_within_pct( 1 ).of_(3) ); + ut3_develop.ut.expect( 1 ).to_( ut3_develop.be_within_pct( 0.01 ).of_(1.0002) ); expect_failure; - ut3_develop.ut.expect( 3.012345679 ).to_be_within_pct( 0.1 ).of_(3); + ut3_develop.ut.expect( 1.0001 ).not_to_be_within_pct( -0.01 ).of_(1); expect_failure; - ut3_develop.ut.expect( 3.012345679 ).to_( ut3_develop.be_within_pct( 0.1 ).of_(3) ); + ut3_develop.ut.expect( 1 ).not_to( ut3_develop.be_within_pct( -0.01 ).of_(1.0001) ); expect_failure; - ut3_develop.ut.expect( 3.012345679 ).not_to_be_within_pct( 1 ).of_(3); + ut3_develop.ut.expect( 1.00000001 ).to_be_within_pct( 0 ).of_(1); expect_failure; - ut3_develop.ut.expect( 3.012345679 ).not_to( ut3_develop.be_within_pct( 1 ).of_(3) ); + ut3_develop.ut.expect( 0 ).to_( ut3_develop.be_within_pct( 0.01 ).of_(0.000001) ); expect_failure; - ut3_develop.ut.expect( 0.1 ).to_be_within_pct( 10 ).of_( 0 ); + 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;