Skip to content

Commit d932f75

Browse files
committed
- 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.
1 parent 99bae42 commit d932f75

30 files changed

Lines changed: 920 additions & 606 deletions

docs/userguide/expectations.md

Lines changed: 741 additions & 490 deletions
Large diffs are not rendered by default.

source/core/types/ut_expectation_result.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ create or replace type body ut_expectation_result is
2424
self.self_type := $$plsql_unit;
2525
self.status := a_status;
2626
self.description := a_description;
27-
self.message := a_message;
27+
self.message := a_message;
2828
if self.status = ut_utils.gc_failure and a_include_caller_info then
2929
self.caller_info := ut_expectation_processor.who_called_expectation(dbms_utility.format_call_stack());
3030
end if;

source/core/ut_expectation_processor.pkb

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ create or replace package body ut_expectation_processor as
9090
for i in 1 .. l_results.count loop
9191
dbms_output.put_line( ' ' || l_results(i) );
9292
end loop;
93+
if a_expectation_result.caller_info is not null then
94+
dbms_output.put_line( ut_utils.indent_lines( a_expectation_result.caller_info, 2, true) );
95+
end if;
9396
end if;
9497
end;
9598

@@ -147,28 +150,55 @@ create or replace package body ut_expectation_processor as
147150

148151
function who_called_expectation(a_call_stack varchar2) return varchar2 is
149152
l_caller_stack_line varchar2(4000);
153+
l_call_stack varchar2(4000);
150154
l_line_no integer;
151155
l_owner varchar2(1000);
152156
l_object_name varchar2(1000);
153-
l_object_full_name varchar2(1000);
154157
l_result varchar2(4000);
155158
-- in 12.2 format_call_stack reportes not only package name, but also the procedure name
156159
-- when 11g and 12c reports only package name
157-
c_expectation_search_pattern constant varchar2(500) :=
158-
'(.*\.(UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+(.*)';
160+
function cut_header_and_expectations( a_stack varchar2 ) return varchar2 is
161+
begin
162+
return regexp_substr( a_stack, '(.*\.(UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+((.|\s)*)', 1, 1, 'm', 4);
163+
end;
164+
function cut_address_columns( a_stack varchar2 ) return varchar2 is
165+
begin
166+
return regexp_replace( a_stack, '^(0x)?[0-9a-f]+\s+', '', 1, 0, 'm' );
167+
end;
168+
function cut_framework_stack( a_stack varchar2 ) return varchar2 is
169+
begin
170+
return regexp_replace(
171+
a_stack,
172+
'[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.*',
173+
'',
174+
1, 1, 'mni'
175+
);
176+
end;
177+
function format_stack( a_stack varchar2 ) return varchar2 is
178+
begin
179+
return regexp_replace(
180+
a_stack,
181+
'([0-9]+)\s+(.* )?((anonymous block)|(([0-9_$#a-z]+\.[0-9_$#a-z]+(\.([0-9_$#a-z])+)?)))',
182+
'at "\3", line \1', 1, 0, 'i'
183+
);
184+
end;
159185
begin
160-
l_caller_stack_line := regexp_substr( a_call_stack, c_expectation_search_pattern, 1, 1, 'm', 4);
186+
l_call_stack := cut_header_and_expectations( a_call_stack );
187+
l_call_stack := cut_address_columns( l_call_stack );
188+
l_call_stack := cut_framework_stack( l_call_stack );
189+
l_call_stack := format_stack( l_call_stack );
190+
l_caller_stack_line := regexp_substr(l_call_stack,'^(.*)');
161191
if l_caller_stack_line like '%.%' then
162-
l_line_no := to_number( regexp_substr(l_caller_stack_line,'(0x)?[0-9a-f]+\s+(\d+)',subexpression => 2) );
163-
l_owner := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.([A-Za-z0-9$#_]|\.)+',subexpression => 1);
164-
l_object_name := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.([A-Za-z0-9$#_]+)',subexpression => 2);
165-
l_object_full_name := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.(([A-Za-z0-9$#_]|\.)+)',subexpression => 2);
166-
if l_owner is not null and l_object_name is not null and l_line_no is not null then
167-
l_result := 'at "' || l_owner || '.' || l_object_full_name || '", line '|| l_line_no || ' '
168-
|| ut_metadata.get_source_definition_line(l_owner, l_object_name, l_line_no);
169-
end if;
192+
l_line_no := to_number( regexp_substr( l_caller_stack_line, ', line (\d+)', subexpression => 1 ) );
193+
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 );
194+
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 );
195+
l_result :=
196+
l_caller_stack_line || ' ' || rtrim(ut_metadata.get_source_definition_line(l_owner, l_object_name, l_line_no),chr(10))
197+
|| replace( l_call_stack, l_caller_stack_line );
198+
else
199+
l_result := l_call_stack;
170200
end if;
171-
return l_result;
201+
return rtrim(l_result,chr(10));
172202
end;
173203

174204
procedure add_warning(a_messsage varchar2) is

source/create_grants.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ grant execute on &&ut3_owner..ut_expectation_compound to &ut3_user;
7575
grant execute on &&ut3_owner..ut_expectation_json to &ut3_user;
7676

7777
--matchers
78+
grant execute on &&ut3_owner..ut_matcher to &ut3_user;
7879
grant execute on &&ut3_owner..ut_be_between to &ut3_user;
7980
grant execute on &&ut3_owner..ut_be_empty to &ut3_user;
8081
grant execute on &&ut3_owner..ut_be_false to &ut3_user;

source/create_synonyms.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ create &action_type. synonym &ut3_user.ut_expectation_compound for &&ut3_owner..
9191
create &action_type. synonym &ut3_user.ut_expectation_json for &&ut3_owner..ut_expectation_json;
9292

9393
--matchers
94+
create &action_type. synonym &ut3_user.ut_matcher for &&ut3_owner..ut_matcher;
9495
create &action_type. synonym &ut3_user.be_between for &&ut3_owner..be_between;
9596
create &action_type. synonym &ut3_user.be_empty for &&ut3_owner..be_empty;
9697
create &action_type. synonym &ut3_user.be_false for &&ut3_owner..be_false;

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ create or replace package body ut_compound_data_helper is
608608
begin
609609
return 'SQL exception thrown when fetching data from cursor:'||
610610
ut_utils.remove_error_from_stack(sqlerrm,ut_utils.gc_xml_processing)||chr(10)||
611-
ut_expectation_processor.who_called_expectation(a_error_stack)||
611+
ut_expectation_processor.who_called_expectation(a_error_stack)||chr(10)||
612612
'Check the query and data for errors.';
613613
end;
614614

source/expectations/data_values/ut_compound_data_value.tpb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ create or replace type body ut_compound_data_value as
1616
limitations under the License.
1717
*/
1818

19+
member function get_elements_count_info return varchar2 is
20+
begin
21+
return case when elements_count is null then ' [ null ]' else ' [ count = '||elements_count||' ]' end;
22+
end;
23+
1924
overriding member function get_object_info return varchar2 is
2025
begin
21-
return self.data_type||' [ count = '||self.elements_count||' ]';
26+
return self.data_type||get_elements_count_info();
2227
end;
2328

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

3944
overriding member function to_string return varchar2 is
40-
l_results ut_utils.t_clob_tab;
4145
l_result clob;
4246
l_result_string varchar2(32767);
4347
begin

source/expectations/data_values/ut_compound_data_value.tps

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ create or replace type ut_compound_data_value force under ut_data_value(
3939
* Holds name for the type of compound
4040
*/
4141
compound_type varchar2(50),
42-
42+
43+
member function get_elements_count_info return varchar2,
4344
overriding member function get_object_info return varchar2,
4445
overriding member function is_null return boolean,
4546
overriding member function is_diffable return boolean,

source/expectations/data_values/ut_data_value.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ create or replace type body ut_data_value as
5959
l_result := l_result || chr(10);
6060
end if;
6161
else
62-
l_result := self.to_string() || ' ' || l_info || ' ';
62+
l_result := self.to_string() || ' ' || l_info;
6363
end if;
6464
return l_result;
6565
end;

source/expectations/data_values/ut_data_value_anydata.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ create or replace type body ut_data_value_anydata as
1818

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

2424
member function get_extract_path(a_data_value anydata) return varchar2 is

0 commit comments

Comments
 (0)