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

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
- Fixed minor typos, formatting and issues with expectation results.
- Changed how stack trace is reported on expectations to provide more information to the user.
- Fixed expectation messages for successful results
- moved `to_be_empty` / `not_to_be_empty` to base `ut_expectation` type as it's available for `clob`/`blob` types too.
- added-back grant on `ut_matcher` to allow for passing various matchers by users.
- fixed issue with misleading message: `All rows are different as the columns position is not matching` when comparing a null collection/cursor
{WIP] Updates to documentation for expectations.
  • Loading branch information
jgebal committed Jul 8, 2019
commit d932f757c65ba49c14a39a3939c6e5e9b1e1c93e
1,231 changes: 741 additions & 490 deletions docs/userguide/expectations.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion source/core/types/ut_expectation_result.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ create or replace type body ut_expectation_result is
self.self_type := $$plsql_unit;
self.status := a_status;
self.description := a_description;
self.message := a_message;
self.message := a_message;
if self.status = ut_utils.gc_failure and a_include_caller_info then
self.caller_info := ut_expectation_processor.who_called_expectation(dbms_utility.format_call_stack());
end if;
Expand Down
56 changes: 43 additions & 13 deletions source/core/ut_expectation_processor.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ create or replace package body ut_expectation_processor as
for i in 1 .. l_results.count loop
dbms_output.put_line( ' ' || l_results(i) );
end loop;
if a_expectation_result.caller_info is not null then
dbms_output.put_line( ut_utils.indent_lines( a_expectation_result.caller_info, 2, true) );
end if;
end if;
end;

Expand Down Expand Up @@ -147,28 +150,55 @@ create or replace package body ut_expectation_processor as

function who_called_expectation(a_call_stack varchar2) return varchar2 is
l_caller_stack_line varchar2(4000);
l_call_stack varchar2(4000);
l_line_no integer;
l_owner varchar2(1000);
l_object_name varchar2(1000);
l_object_full_name varchar2(1000);
l_result varchar2(4000);
-- in 12.2 format_call_stack reportes not only package name, but also the procedure name
-- when 11g and 12c reports only package name
c_expectation_search_pattern constant varchar2(500) :=
'(.*\.(UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+(.*)';
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);
end;
function cut_address_columns( a_stack varchar2 ) return varchar2 is
begin
return regexp_replace( a_stack, '^(0x)?[0-9a-f]+\s+', '', 1, 0, 'm' );
end;
function cut_framework_stack( a_stack varchar2 ) return varchar2 is
begin
return regexp_replace(
a_stack,
'[0-9]+\s+anonymous\s+block\s+[0-9]+\s+package\s+body\s+sys\.dbms_sql(\.execute)?\s+[0-9]+\s+[0-9_$#a-z ]+\.ut_executable.*',
'',
1, 1, 'mni'
);
end;
function format_stack( a_stack varchar2 ) return varchar2 is
begin
return regexp_replace(
a_stack,
'([0-9]+)\s+(.* )?((anonymous block)|(([0-9_$#a-z]+\.[0-9_$#a-z]+(\.([0-9_$#a-z])+)?)))',
'at "\3", line \1', 1, 0, 'i'
);
end;
begin
l_caller_stack_line := regexp_substr( a_call_stack, c_expectation_search_pattern, 1, 1, 'm', 4);
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 );
l_call_stack := format_stack( l_call_stack );
l_caller_stack_line := regexp_substr(l_call_stack,'^(.*)');
if l_caller_stack_line like '%.%' then
l_line_no := to_number( regexp_substr(l_caller_stack_line,'(0x)?[0-9a-f]+\s+(\d+)',subexpression => 2) );
l_owner := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.([A-Za-z0-9$#_]|\.)+',subexpression => 1);
l_object_name := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.([A-Za-z0-9$#_]+)',subexpression => 2);
l_object_full_name := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.(([A-Za-z0-9$#_]|\.)+)',subexpression => 2);
if l_owner is not null and l_object_name is not null and l_line_no is not null then
l_result := 'at "' || l_owner || '.' || l_object_full_name || '", line '|| l_line_no || ' '
|| ut_metadata.get_source_definition_line(l_owner, l_object_name, l_line_no);
end if;
l_line_no := to_number( regexp_substr( l_caller_stack_line, ', line (\d+)', subexpression => 1 ) );
l_owner := regexp_substr( l_caller_stack_line, 'at "([A-Za-z0-9$#_]+)\.(([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_]+))?)", line (\d+)', subexpression => 1 );
l_object_name := regexp_substr( l_caller_stack_line, 'at "([A-Za-z0-9$#_]+)\.(([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_]+))?)", line (\d+)', subexpression => 3 );
l_result :=
l_caller_stack_line || ' ' || rtrim(ut_metadata.get_source_definition_line(l_owner, l_object_name, l_line_no),chr(10))
|| replace( l_call_stack, l_caller_stack_line );
else
l_result := l_call_stack;
end if;
return l_result;
return rtrim(l_result,chr(10));
end;

procedure add_warning(a_messsage varchar2) is
Expand Down
1 change: 1 addition & 0 deletions source/create_grants.sql
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ grant execute on &&ut3_owner..ut_expectation_compound to &ut3_user;
grant execute on &&ut3_owner..ut_expectation_json to &ut3_user;

--matchers
grant execute on &&ut3_owner..ut_matcher to &ut3_user;
grant execute on &&ut3_owner..ut_be_between to &ut3_user;
grant execute on &&ut3_owner..ut_be_empty to &ut3_user;
grant execute on &&ut3_owner..ut_be_false to &ut3_user;
Expand Down
1 change: 1 addition & 0 deletions source/create_synonyms.sql
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ create &action_type. synonym &ut3_user.ut_expectation_compound for &&ut3_owner..
create &action_type. synonym &ut3_user.ut_expectation_json for &&ut3_owner..ut_expectation_json;

--matchers
create &action_type. synonym &ut3_user.ut_matcher for &&ut3_owner..ut_matcher;
create &action_type. synonym &ut3_user.be_between for &&ut3_owner..be_between;
create &action_type. synonym &ut3_user.be_empty for &&ut3_owner..be_empty;
create &action_type. synonym &ut3_user.be_false for &&ut3_owner..be_false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ create or replace package body ut_compound_data_helper is
begin
return 'SQL exception thrown when fetching data from cursor:'||
ut_utils.remove_error_from_stack(sqlerrm,ut_utils.gc_xml_processing)||chr(10)||
ut_expectation_processor.who_called_expectation(a_error_stack)||
ut_expectation_processor.who_called_expectation(a_error_stack)||chr(10)||
'Check the query and data for errors.';
end;

Expand Down
8 changes: 6 additions & 2 deletions source/expectations/data_values/ut_compound_data_value.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ create or replace type body ut_compound_data_value as
limitations under the License.
*/

member function get_elements_count_info return varchar2 is
begin
return case when elements_count is null then ' [ null ]' else ' [ count = '||elements_count||' ]' end;
end;

overriding member function get_object_info return varchar2 is
begin
return self.data_type||' [ count = '||self.elements_count||' ]';
return self.data_type||get_elements_count_info();
end;

overriding member function is_null return boolean is
Expand All @@ -37,7 +42,6 @@ create or replace type body ut_compound_data_value as
end;

overriding member function to_string return varchar2 is
l_results ut_utils.t_clob_tab;
l_result clob;
l_result_string varchar2(32767);
begin
Expand Down
3 changes: 2 additions & 1 deletion source/expectations/data_values/ut_compound_data_value.tps
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ create or replace type ut_compound_data_value force under ut_data_value(
* Holds name for the type of compound
*/
compound_type varchar2(50),


member function get_elements_count_info return varchar2,
overriding member function get_object_info return varchar2,
overriding member function is_null return boolean,
overriding member function is_diffable return boolean,
Expand Down
2 changes: 1 addition & 1 deletion source/expectations/data_values/ut_data_value.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ create or replace type body ut_data_value as
l_result := l_result || chr(10);
end if;
else
l_result := self.to_string() || ' ' || l_info || ' ';
l_result := self.to_string() || ' ' || l_info;
end if;
return l_result;
end;
Expand Down
2 changes: 1 addition & 1 deletion source/expectations/data_values/ut_data_value_anydata.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ create or replace type body ut_data_value_anydata as

overriding member function get_object_info return varchar2 is
begin
return self.data_type || case when self.compound_type = 'collection' then ' [ count = '||self.elements_count||' ]' else null end;
return self.data_type || case when self.compound_type = 'collection' then self.get_elements_count_info() end;
end;

member function get_extract_path(a_data_value anydata) return varchar2 is
Expand Down
7 changes: 4 additions & 3 deletions source/expectations/data_values/ut_data_value_json.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ create or replace type body ut_data_value_json as
ut_utils.append_to_clob(l_result, l_results);

end if;


l_result_string := ut_utils.to_string(l_result,null);

if l_result != empty_clob() then
l_result_string := chr(10) || 'Diff:' || ut_utils.to_string(l_result,null);
end if;
dbms_lob.freetemporary(l_result);
return l_result_string;
end;
Expand Down
11 changes: 6 additions & 5 deletions source/expectations/data_values/ut_data_value_refcursor.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ create or replace type body ut_data_value_refcursor as
a_match_options.ordered_columns()
);

if l_column_diffs.count > 0 then
if l_column_diffs is not empty then
ut_utils.append_to_clob(l_result,chr(10) || 'Columns:' || chr(10));
l_other_cols := remove_incomparable_cols( l_other_cols, l_column_diffs );
l_self_cols := remove_incomparable_cols( l_self_cols, l_column_diffs );
Expand Down Expand Up @@ -267,8 +267,8 @@ create or replace type body ut_data_value_refcursor as
l_results(l_results.last) := get_diff_message(l_row_diffs(i),a_match_options.unordered);
end loop;
ut_utils.append_to_clob(l_result,l_results);
else
l_message:= chr(10)||'Rows: [ all different ]'||chr(10)||' All rows are different as the columns position is not matching.';
elsif l_column_diffs is not empty then
l_message:= chr(10)||'Rows: [ all different ]'||chr(10)||' All rows are different as the columns position is not matching.';
ut_utils.append_to_clob( l_result, l_message );
end if;
else
Expand All @@ -287,8 +287,9 @@ create or replace type body ut_data_value_refcursor as
end if;

end if;

l_result_string := ut_utils.to_string(l_result,null);
if l_result != empty_clob() then
l_result_string := chr(10) || 'Diff:' || ut_utils.to_string(l_result,null);
end if;
dbms_lob.freetemporary(l_result);
return l_result_string;
end;
Expand Down
3 changes: 1 addition & 2 deletions source/expectations/matchers/ut_contain.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ create or replace type body ut_contain as
begin
if self.expected.data_type = a_actual.data_type and self.expected.is_diffable then
l_result :=
'Actual: '||a_actual.get_object_info()||' '||self.description()||': '||self.expected.get_object_info()
|| chr(10) || 'Diff:'
'Actual: '||a_actual.get_object_info()||self.description()||': '||self.expected.get_object_info()
|| treat(expected as ut_data_value_refcursor).diff( a_actual, self.options );
else
l_result := (self as ut_matcher).failure_message(a_actual) || ': '|| self.expected.to_string_report();
Expand Down
19 changes: 9 additions & 10 deletions source/expectations/matchers/ut_equal.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,15 @@ create or replace type body ut_equal as
begin
if self.expected.data_type = a_actual.data_type and self.expected.is_diffable then
l_result :=
'Actual: '||a_actual.get_object_info()||' '||self.description()||': '||self.expected.get_object_info()
|| chr(10) || 'Diff:' ||
case
when self.expected is of (ut_data_value_refcursor) then
treat(expected as ut_data_value_refcursor).diff( a_actual, options )
when self.expected is of (ut_data_value_json) then
treat(expected as ut_data_value_json).diff( a_actual, options )
else
expected.diff( a_actual, options )
end;
'Actual: '||a_actual.get_object_info()||self.description()||': '||self.expected.get_object_info()
||case
when self.expected is of (ut_data_value_refcursor) then
treat(expected as ut_data_value_refcursor).diff( a_actual, options )
when self.expected is of (ut_data_value_json) then
treat(expected as ut_data_value_json).diff( a_actual, options )
else
expected.diff( a_actual, options )
end;
else
l_result := (self as ut_matcher).failure_message(a_actual) || ': '|| self.expected.to_string_report();
end if;
Expand Down
4 changes: 2 additions & 2 deletions source/expectations/matchers/ut_matcher.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ create or replace type body ut_matcher as

member function description return varchar2 is
begin
return 'was expected to '||name();
return ' was expected to '||name();
end;

member function description_when_negated return varchar2 is
begin
return 'was expected not to '||name();
return ' was expected not to '||name();
end;

member function error_message(a_actual ut_data_value) return varchar2 is
Expand Down
10 changes: 10 additions & 0 deletions source/expectations/ut_expectation.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ create or replace type body ut_expectation as
self.not_to( ut_be_false() );
end;

member procedure to_be_empty(self in ut_expectation) is
begin
self.to_( ut_be_empty() );
end;

member procedure not_to_be_empty(self in ut_expectation) is
begin
self.not_to( ut_be_empty() );
end;

member procedure to_equal(self in ut_expectation, a_expected anydata, a_nulls_are_equal boolean := null) is
begin
self.to_( ut_equal(a_expected, a_nulls_are_equal) );
Expand Down
3 changes: 3 additions & 0 deletions source/expectations/ut_expectation.tps
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ create or replace type ut_expectation authid current_user as object(
member procedure not_to_be_true(self in ut_expectation),
member procedure not_to_be_false(self in ut_expectation),

member procedure to_be_empty(self in ut_expectation),
member procedure not_to_be_empty(self in ut_expectation),

-- this is done to provide strong type comparison. other comporators should be implemented in the type-specific classes
member procedure to_equal(self in ut_expectation, a_expected anydata, a_nulls_are_equal boolean := null),
member procedure to_equal(self in ut_expectation, a_expected anydata, a_exclude varchar2, a_nulls_are_equal boolean := null),
Expand Down
10 changes: 0 additions & 10 deletions source/expectations/ut_expectation_compound.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,6 @@ create or replace type body ut_expectation_compound as
return;
end;

member procedure to_be_empty(self in ut_expectation_compound) is
begin
self.to_( ut_be_empty() );
end;

member procedure not_to_be_empty(self in ut_expectation_compound) is
begin
self.not_to( ut_be_empty() );
end;

member procedure to_have_count(self in ut_expectation_compound, a_expected integer) is
begin
self.to_( ut_have_count(a_expected) );
Expand Down
2 changes: 0 additions & 2 deletions source/expectations/ut_expectation_compound.tps
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ create or replace type ut_expectation_compound force under ut_expectation(

constructor function ut_expectation_compound(self in out nocopy ut_expectation_compound, a_actual_data ut_data_value, a_description varchar2) return self as result,

member procedure to_be_empty(self in ut_expectation_compound),
member procedure not_to_be_empty(self in ut_expectation_compound),
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),

Expand Down
10 changes: 0 additions & 10 deletions source/expectations/ut_expectation_json.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,6 @@ create or replace type body ut_expectation_json as
return;
end;

member procedure to_be_empty(self in ut_expectation_json) is
begin
self.to_( ut_be_empty() );
end;

member procedure not_to_be_empty(self in ut_expectation_json) is
begin
self.not_to( ut_be_empty() );
end;

member function to_equal(a_expected json_element_t, a_nulls_are_equal boolean := null) return ut_expectation_json is
l_result ut_expectation_json := self;
begin
Expand Down
2 changes: 0 additions & 2 deletions source/expectations/ut_expectation_json.tps
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ create or replace type ut_expectation_json under ut_expectation(

constructor function ut_expectation_json(self in out nocopy ut_expectation_json, a_actual_data ut_data_value, a_description varchar2) return self as result,

member procedure to_be_empty(self in ut_expectation_json),
member procedure not_to_be_empty(self in ut_expectation_json),
member function to_equal(a_expected json_element_t , a_nulls_are_equal boolean := null) return ut_expectation_json,
member function not_to_equal(a_expected json_element_t , a_nulls_are_equal boolean := null) return ut_expectation_json,
member procedure to_have_count(self in ut_expectation_json, a_expected integer),
Expand Down
Loading