Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
48abf1a
Initial checkin
lwasylow Jun 1, 2020
7041912
added expectation
lwasylow Jun 2, 2020
13d86b6
Adding more methods
lwasylow Jun 2, 2020
caeeb30
Adding contain and not contain
lwasylow Jun 2, 2020
8ff4f6b
Adding code and tests,.
lwasylow Jun 6, 2020
89cb0bc
Fixingtoo long names
lwasylow Jun 6, 2020
a5481ac
fixing issue
lwasylow Jun 6, 2020
9ee0e75
Update documentation and tests
lwasylow Jun 7, 2020
a660208
First code corrections
lwasylow Jun 14, 2020
ada1ea4
Resolving another comment
lwasylow Jun 14, 2020
fe1b0cb
Updating issues
lwasylow Jun 14, 2020
013db74
Update tble
lwasylow Jun 14, 2020
b5c73b4
Separated into two different matchers
jgebal Jun 19, 2020
2e721da
CHECKPOINT
lwasylow Jun 19, 2020
fbc0f26
Merge branch 'feature/rework_matcher' of https://github.com/utPLSQL/u…
lwasylow Jun 19, 2020
f182430
Update uninstall
lwasylow Jun 19, 2020
e3fb2d7
Update progress
lwasylow Jun 19, 2020
322e0a1
Making code a bit more readable
lwasylow Jun 19, 2020
ff15596
Added tests for `be_within_pct`
jgebal Jun 20, 2020
3cae9a2
Fixed test issue
jgebal Jun 20, 2020
22549db
Fixed stacktrace for failed expectations on chained matchers.
jgebal Jun 21, 2020
1d771a5
Update timestamps
lwasylow Jun 25, 2020
363c333
Fixed and simplified matcher
jgebal Jun 27, 2020
0ea8925
Fixed native dynamic SQL types compatibility for 11g
jgebal Jun 28, 2020
7c01afb
Fixed native dynamic SQL types compatibility for 11g
jgebal Jun 28, 2020
66d92fc
Merge branch 'develop' into feature/rework_matcher
jgebal Jan 28, 2022
590fb38
Improving test stability (flaky tests)
jgebal Jan 28, 2022
5e2642a
Removing reference to ut3_develop schema.
jgebal Jan 28, 2022
ed06e33
Relaxed sql-injection check to work with 11g2
jgebal Jan 28, 2022
38f3cbc
Fixed issues with comparison of dates&timestamps using interval year-…
jgebal Jan 30, 2022
86e84c8
Improving code coverage.
jgebal Jan 31, 2022
718ac0d
Improved test stability.
jgebal Jan 31, 2022
6dbef20
Fixing build process to build using develop branch as testing framewo…
jgebal Jan 31, 2022
25b55b4
Improving test coverage.
jgebal Jan 31, 2022
5b5a5c0
Improving matcher documentation
jgebal Jan 31, 2022
7fec0f9
Added tests for 0 value of actual and expected and actual greater tha…
jgebal Feb 2, 2022
fd7ef9c
Fixed issues with precission of distance. `NATURAL` is a subtype of i…
jgebal Feb 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Adding code and tests,.
  • Loading branch information
lwasylow committed Jun 6, 2020
commit 8ff4f6bbf847bab652a1628aa68abc140655d7fe
25 changes: 25 additions & 0 deletions source/core/ut_utils.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
lwasylow marked this conversation as resolved.
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;
/
9 changes: 8 additions & 1 deletion source/core/ut_utils.pks
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Comment thread
lwasylow marked this conversation as resolved.

end ut_utils;
/
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
104 changes: 104 additions & 0 deletions source/expectations/matchers/ut_be_within.tpb
Original file line number Diff line number Diff line change
@@ -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
Comment thread
lwasylow marked this conversation as resolved.
Outdated
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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the following datatypes are missing:

  • timestamp
  • timestamp with timezone
  • timestamp with local timezone

We could also add support for intervals, so users could have:

  ut.expect( interval '2' days ).to_be_within(interval '1' second').of_(interval '2' days);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if that's right. It's a hit against logic as interval words itself describe the distance and have no meaning without of relative point. Distonace of the distance feel counter intuitive to me.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if I use interval as a column to measure duration.
Ant I expect some duration to be 1 hour +/- 5 minutes?
This seems perfectly valid.
In that sense we're saying it sould take 1 hour with 5 minutes tolerance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this discussion should be in issue rather than in PR

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
Comment thread
lwasylow marked this conversation as resolved.
Outdated
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
Comment thread
lwasylow marked this conversation as resolved.
Outdated
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
Comment thread
lwasylow marked this conversation as resolved.
l_result varchar2(32767);
begin
return (self as ut_matcher).failure_message_when_negated(a_actual) || ': '|| expected.to_string_report();
end;

end;
/
Comment thread
lwasylow marked this conversation as resolved.
Outdated
38 changes: 38 additions & 0 deletions source/expectations/matchers/ut_be_within.tps
Original file line number Diff line number Diff line change
@@ -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,
Comment thread
lwasylow marked this conversation as resolved.
Outdated
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
/
2 changes: 1 addition & 1 deletion source/expectations/matchers/ut_matcher.tps
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
57 changes: 32 additions & 25 deletions source/expectations/ut_expectation.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Comment thread
lwasylow marked this conversation as resolved.
Outdated
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;
/
16 changes: 7 additions & 9 deletions source/expectations/ut_expectation.tps
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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),
Expand Down Expand Up @@ -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
/
44 changes: 44 additions & 0 deletions source/expectations/ut_expectation_base.tpb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
create or replace type body ut_expectation_base as
Comment thread
lwasylow marked this conversation as resolved.
/*
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;
/
Comment thread
lwasylow marked this conversation as resolved.
Outdated
25 changes: 25 additions & 0 deletions source/expectations/ut_expectation_base.tps
Original file line number Diff line number Diff line change
@@ -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),
Comment thread
lwasylow marked this conversation as resolved.
member procedure not_to(self in ut_expectation_base, a_matcher ut_matcher_base)
) not final
/
Comment thread
lwasylow marked this conversation as resolved.
Outdated
Loading