Skip to content

Commit 274af66

Browse files
committed
Added reporting of line where assertion has failed.
Addded separate example with demo of ut_documentation_reporter
1 parent 217c150 commit 274af66

11 files changed

Lines changed: 164 additions & 22 deletions

examples/RunAllExamples.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ prompt RunExampleTestAnnotationsHugePackage
2020
@@RunExampleTestAnnotationsHugePackage.sql
2121
prompt RunExpectations
2222
@@RunExpectations.sql
23+
prompt RunWithDocumentationReporter
24+
RunWithDocumentationReporter.sql

examples/RunExpectations.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--Suite Management packages are when developed will make this easier.
44
--Clear Screen
55
Set Serveroutput On Size Unlimited format truncated
6-
set linesize 1000
6+
set linesize 10000
77
set echo off
88
--install the example unit test packages
99
@@department.tps
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
Set Serveroutput On Size Unlimited format truncated
2+
set linesize 10000
3+
set echo off
4+
5+
create or replace package demo_doc_reporter1 is
6+
-- %suite(Demo of documentation reporter)
7+
-- %test(A passing test sample)
8+
procedure passing_test;
9+
-- %test
10+
procedure test_without_name;
11+
-- %test(A failing test exsample)
12+
procedure failing_test;
13+
-- %test
14+
procedure failing_no_name;
15+
-- %test(repoting exception)
16+
procedure failing_exception_raised;
17+
end;
18+
/
19+
20+
create or replace package body demo_doc_reporter1 is
21+
22+
procedure passing_test is begin null; end;
23+
24+
procedure test_without_name is
25+
begin
26+
ut.expect(1).to_(equal(1));
27+
end;
28+
29+
procedure failing_test is
30+
begin
31+
ut.expect(1).to_(equal(2));
32+
end;
33+
procedure failing_no_name is
34+
begin
35+
ut.expect(sysdate).to_(equal(to_char(sysdate)));
36+
end;
37+
procedure failing_exception_raised is
38+
l_date date;
39+
begin
40+
l_date := to_date('abcd');
41+
end;
42+
end;
43+
/
44+
45+
create or replace package demo_doc_reporter2 is
46+
-- %suite(A suite pacakge without body)
47+
-- %test(A test)
48+
procedure passing_test1;
49+
-- %test
50+
procedure passing_test2;
51+
end;
52+
/
53+
54+
create or replace package suite_package_without_name is
55+
-- %suite
56+
-- %test(A passing test sample)
57+
procedure passing_test1;
58+
-- %test(A passing test sample)
59+
procedure passing_test2;
60+
end;
61+
/
62+
63+
create or replace package body suite_package_without_name is
64+
65+
procedure passing_test1 is begin null; end;
66+
67+
procedure passing_test2 is
68+
begin
69+
ut.expect(1).to_(equal(1));
70+
end;
71+
end;
72+
/
73+
74+
begin
75+
ut_suite_manager.run_cur_schema_suites_static(ut_documentation_reporter(), a_force_parse_again => true);
76+
end;
77+
/
78+
79+
80+
drop package demo_doc_reporter2;
81+
drop package suite_package_without_name;
82+
drop package demo_doc_reporter1;

source/core/types/ut_assert_result.tpb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ create or replace type body ut_assert_result is
77
self.object_type := 0;
88
self.result := a_result;
99
self.error_message := a_error_message;
10+
self.caller_info := ut_assert_processor.who_called_expectation();
1011
return;
1112
end ut_assert_result;
1213

@@ -24,6 +25,7 @@ create or replace type body ut_assert_result is
2425
self.actual_type := a_actual_type;
2526
self.expected_value_string := a_expected_value_string;
2627
self.actual_value_string := a_actual_value_string;
28+
self.caller_info := ut_assert_processor.who_called_expectation();
2729
return;
2830
end ut_assert_result;
2931

source/core/types/ut_assert_result.tps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ create or replace type ut_assert_result force under ut_object
77
actual_value_string varchar2(4000 char),
88
message varchar2(4000 char),
99
error_message varchar2(4000 char),
10+
caller_info varchar2(4000 char),
1011
constructor function ut_assert_result(self in out nocopy ut_assert_result, a_result integer, a_error_message varchar2, a_name varchar2 default null)
1112
return self as result,
1213
constructor function ut_assert_result(self in out nocopy ut_assert_result, a_name varchar2, a_additional_info varchar2, a_error_message varchar2,

source/core/types/ut_test.tpb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,8 @@ create or replace type body ut_test is
7070
-- dbms_utility.format_error_backtrace is 10g or later
7171
-- utl_call_stack package may be better but it's 12c but still need to investigate
7272
-- article with details: http://www.oracle.com/technetwork/issue-archive/2014/14-jan/o14plsql-2045346.html
73-
ut_utils.debug_log('testmethod failed-' || sqlerrm(sqlcode) || ' ' || dbms_utility.format_error_backtrace);
74-
75-
ut_assert_processor.report_error(sqlerrm(sqlcode) || ' ' || dbms_utility.format_error_backtrace);
73+
ut_utils.debug_log('test method failed-' || sqlerrm(sqlcode) || ' ' || dbms_utility.format_error_stack || dbms_utility.format_error_backtrace);
74+
ut_assert_processor.report_error( dbms_utility.format_error_stack || dbms_utility.format_error_backtrace );
7675
end;
7776
a_reporter.after_test_execute(self);
7877

@@ -92,8 +91,7 @@ create or replace type body ut_test is
9291
end if;
9392
ut_utils.debug_log('ut_test.execute failed-' || sqlerrm(sqlcode) || ' ' || dbms_utility.format_error_backtrace);
9493
-- most likely occured in setup or teardown if here.
95-
ut_assert_processor.report_error(sqlerrm(sqlcode) || ' ' || dbms_utility.format_error_stack);
96-
ut_assert_processor.report_error(sqlerrm(sqlcode) || ' ' || dbms_utility.format_error_backtrace);
94+
ut_assert_processor.report_error( dbms_utility.format_error_stack || dbms_utility.format_error_backtrace );
9795
end;
9896

9997
if self.rollback_type = ut_utils.gc_rollback_auto then

source/core/ut_assert_processor.pkb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,45 @@ create or replace package body ut_assert_processor as
111111

112112
end;
113113

114+
function get_source_definition_line(a_owner varchar2, a_object_name varchar2, a_line_no integer) return varchar2 is
115+
l_line varchar2(4000);
116+
begin
117+
execute immediate
118+
q'[select text from dba_source
119+
where owner = :a_owner and name = :a_object_name and line = :a_line_no
120+
-- skip the declarations, consider only definitions
121+
and type not in ('PACKAGE', 'TYPE') ]'
122+
into l_line using a_owner, a_object_name, a_line_no;
123+
return '"'||ltrim(rtrim( lower( l_line ), chr(10) ))||'"';
124+
exception
125+
when no_data_found then
126+
return null;
127+
end;
128+
129+
function who_called_expectation return varchar2 is
130+
l_call_stack varchar2(32767) := dbms_utility.format_call_stack();
131+
l_caller_stack_line varchar2(4000);
132+
l_caller_type_and_name varchar2(4000);
133+
l_line_no integer;
134+
l_owner varchar2(100);
135+
l_object_name varchar2(100);
136+
l_last_space_pos integer;
137+
l_object_delimiter_pos integer;
138+
c_expectation_search_pattern constant varchar2(50) := '(.*\.UT_EXPECTATION[A-Z0-9#_$]*\s)+(.*)\s';
139+
begin
140+
l_caller_stack_line := regexp_substr( l_call_stack, c_expectation_search_pattern, 1, 1, 'm', 2);
141+
l_line_no := to_number( trim( substr( l_caller_stack_line, 11, 10 ) ) );
142+
l_caller_type_and_name := substr( l_caller_stack_line, 23 );
143+
l_last_space_pos := instr( l_caller_type_and_name, ' ', -1 );
144+
l_object_delimiter_pos := instr( l_caller_type_and_name, '.' );
145+
if l_object_delimiter_pos > 0 then
146+
l_owner := substr( l_caller_type_and_name, l_last_space_pos + 1, l_object_delimiter_pos - l_last_space_pos - 1 );
147+
l_object_name := substr( l_caller_type_and_name, l_object_delimiter_pos + 1 );
148+
end if;
149+
return
150+
case when l_owner is not null and l_object_name is not null and l_line_no is not null then
151+
'at "'||l_owner||'.'||l_object_name||'", line '||l_line_no||' '||get_source_definition_line(l_owner, l_object_name, l_line_no)
152+
end;
153+
end;
114154
end;
115155
/

source/core/ut_assert_processor.pks

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,13 @@ create or replace package ut_assert_processor authid current_user as
2222

2323
procedure reset_nls_params;
2424

25+
-- function is looking at call stack
26+
-- and tries to figure out at which line of code
27+
-- in a unit test, the expectation was called
28+
-- if found, it returns a text:
29+
-- at: owner.name:line "source code line text"
30+
-- The text is to be consumed by expectation result
31+
function who_called_expectation return varchar2;
32+
2533
end;
2634
/

source/core/ut_utils.pkb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ create or replace package body ut_utils is
8181
case
8282
when l_len = 0 then gc_null_string
8383
when l_len <= gc_max_input_string_length then quote_string(rawtohex(a_value))
84-
else to_string( rawtohex(dbms_lob.substr(a_value, gc_overflow_substr_len)) )
84+
else quote_string( rawtohex(dbms_lob.substr(a_value, gc_overflow_substr_len)) )
8585
end;
8686
end;
8787

@@ -135,5 +135,10 @@ create or replace package body ut_utils is
135135
extract(second from(a_end_time - a_start_time));
136136
end;
137137

138+
function indent_lines(a_text varchar2, a_indent_size integer) return varchar2 is
139+
begin
140+
return replace( a_text, chr(10), chr(10) || lpad( ' ', a_indent_size ) );
141+
end;
142+
138143
end ut_utils;
139144
/

source/core/ut_utils.pks

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,7 @@ create or replace package ut_utils authid definer is
9090

9191
function time_diff(a_start_time timestamp with time zone, a_end_time timestamp with time zone) return number;
9292

93+
function indent_lines(a_text varchar2, a_indent_size integer) return varchar2;
94+
9395
end ut_utils;
9496
/

0 commit comments

Comments
 (0)