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

Skip to content

Commit ecfaa61

Browse files
Implementation draft to the new characteristic --%throws(exception_number)
1 parent 6c8522f commit ecfaa61

10 files changed

Lines changed: 162 additions & 16 deletions

source/core/types/ut_executable.tpb

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ create or replace type body ut_executable is
2525
self.owner_name := a_context.object_owner;
2626
self.object_name := a_context.object_name;
2727
self.procedure_name := a_procedure_name;
28+
--self.expected_error_codes := treat(a_context as ut_test).expected_error_codes;
2829
return;
2930
end;
3031

@@ -59,23 +60,27 @@ create or replace type body ut_executable is
5960
return ut_metadata.form_name(owner_name, object_name, procedure_name);
6061
end;
6162

62-
member procedure do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base) is
63+
member procedure do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base,
64+
a_expected_error_codes in varchar2 := null) is
6365
l_completed_without_errors boolean;
6466
begin
65-
l_completed_without_errors := self.do_execute(a_item, a_listener);
67+
l_completed_without_errors := self.do_execute(a_item, a_listener, a_expected_error_codes);
6668
end do_execute;
6769

68-
member function do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base) return boolean is
70+
member function do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base,
71+
a_expected_error_codes in varchar2 := null) return boolean is
6972
l_statement varchar2(4000);
7073
l_status number;
7174
l_cursor_number number;
7275
l_owner varchar2(200) := self.owner_name;
7376
l_object_name varchar2(200) := self.object_name;
7477
l_procedure_name varchar2(200) := self.procedure_name;
78+
l_expected_except_message varchar2(4000);
7579

7680
l_completed_without_errors boolean := true;
7781
l_start_transaction_id varchar2(250);
78-
l_end_transaction_id varchar2(250);
82+
l_end_transaction_id varchar2(250);
83+
7984
procedure save_dbms_output is
8085
l_status number;
8186
l_line varchar2(32767);
@@ -93,6 +98,25 @@ create or replace type body ut_executable is
9398
dbms_lob.writeappend(self.serveroutput,1,chr(10));
9499
end loop;
95100
end save_dbms_output;
101+
102+
function build_failed_expec_errnum(a_error_stack in varchar2, a_expected_error_codes in varchar) return varchar is
103+
l_actual_error_no integer;
104+
l_fail_message varchar2(4000);
105+
begin
106+
if a_error_stack is null then
107+
l_fail_message := 'Expected exceptions '||a_expected_error_codes||' but nothing was raised.';
108+
else
109+
l_actual_error_no := regexp_substr(a_error_stack, '^ORA(-[0-9]+)',subexpression=>1);
110+
111+
if a_expected_error_codes = l_actual_error_no then
112+
l_fail_message := null;
113+
else
114+
l_fail_message := 'Expected exceptions '''||a_expected_error_codes||''' got '''||l_actual_error_no||'''.';
115+
end if;
116+
end if;
117+
118+
return l_fail_message;
119+
end;
96120
begin
97121
if self.is_defined() then
98122
l_start_transaction_id := dbms_transaction.local_transaction_id(true);
@@ -139,6 +163,20 @@ create or replace type body ut_executable is
139163

140164
save_dbms_output;
141165

166+
167+
if a_expected_error_codes is not null then
168+
l_expected_except_message := build_failed_expec_errnum(self.error_stack, a_expected_error_codes);
169+
170+
if l_expected_except_message is not null then
171+
ut_expectation_processor.add_expectation_result(
172+
ut_expectation_result(ut_utils.tr_failure, null, l_owner||'.'||l_object_name||'.'||l_procedure_name||' '||l_expected_except_message, false)
173+
);
174+
end if;
175+
176+
self.error_stack := null;
177+
self.error_backtrace := null;
178+
end if;
179+
142180
l_completed_without_errors := (self.error_stack||self.error_backtrace) is null;
143181

144182
--listener - after call to executable

source/core/types/ut_executable.tps

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ create or replace type ut_executable authid current_user as object(
2929
member function is_valid(self in out nocopy ut_executable) return boolean,
3030
member function is_defined return boolean,
3131
member function form_name return varchar2,
32-
member procedure do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base),
32+
member procedure do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base,
33+
a_expected_error_codes in varchar2 := null),
3334
/**
3435
* executes the defines executable
3536
* returns true if executed without exceptions
3637
* returns false if exceptions were raised
3738
*/
38-
member function do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base) return boolean,
39+
member function do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item, a_listener in out nocopy ut_event_listener_base,
40+
a_expected_error_codes in varchar2 := null) return boolean,
3941
member function get_error_stack_trace return varchar2
4042
) final
4143
/

source/core/types/ut_expectation_result.tpb

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

19-
constructor function ut_expectation_result(self in out nocopy ut_expectation_result, a_status integer, a_description varchar2, a_message clob)
19+
constructor function ut_expectation_result(self in out nocopy ut_expectation_result, a_status integer, a_description varchar2, a_message clob,
20+
a_include_caller_info boolean := true)
2021
return self as result is
2122
begin
2223
self.status := a_status;
2324
self.description := a_description;
2425
self.message := a_message;
25-
if self.status = ut_utils.tr_failure then
26+
if self.status = ut_utils.tr_failure and a_include_caller_info then
2627
self.caller_info := ut_expectation_processor.who_called_expectation(dbms_utility.format_call_stack());
2728
end if;
2829
return;

source/core/types/ut_expectation_result.tps

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ create or replace type ut_expectation_result authid current_user as object(
3333
* The information about the line of code that invoked the expectation
3434
*/
3535
caller_info varchar2(32767),
36-
constructor function ut_expectation_result(self in out nocopy ut_expectation_result, a_status integer, a_description varchar2, a_message clob)
36+
constructor function ut_expectation_result(self in out nocopy ut_expectation_result, a_status integer, a_description varchar2, a_message clob,
37+
a_include_caller_info boolean := true)
3738
return self as result,
3839
member function get_result_clob(self in ut_expectation_result) return clob,
3940
member function get_result_lines(self in ut_expectation_result) return ut_varchar2_list,

source/core/types/ut_test.tpb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ create or replace type body ut_test as
2020
self in out nocopy ut_test, a_object_owner varchar2 := null, a_object_name varchar2, a_name varchar2, a_description varchar2 := null,
2121
a_path varchar2 := null, a_rollback_type integer := null, a_disabled_flag boolean := false,
2222
a_before_each_proc_name varchar2 := null, a_before_test_proc_name varchar2 := null,
23-
a_after_test_proc_name varchar2 := null, a_after_each_proc_name varchar2 := null
23+
a_after_test_proc_name varchar2 := null, a_after_each_proc_name varchar2 := null,
24+
a_expected_error_codes varchar2 := null
2425
) return self as result is
2526
begin
2627
self.self_type := $$plsql_unit;
@@ -32,6 +33,7 @@ create or replace type body ut_test as
3233
self.after_each := ut_executable(self, a_after_each_proc_name, ut_utils.gc_after_each);
3334
self.all_expectations := ut_expectation_results();
3435
self.failed_expectations := ut_expectation_results();
36+
self.expected_error_codes := a_expected_error_codes;
3537
return;
3638
end;
3739

@@ -92,7 +94,7 @@ create or replace type body ut_test as
9294

9395
if l_completed_without_errors then
9496
-- execute the test
95-
self.item.do_execute(self, a_listener);
97+
self.item.do_execute(self, a_listener, self.expected_error_codes);
9698

9799
end if;
98100
-- perform cleanup regardless of the test or setup failure

source/core/types/ut_test.tps

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,16 @@ create or replace type ut_test under ut_suite_item (
5555
* Will get populated on exceptions in before-all calls
5656
*/
5757
parent_error_stack_trace varchar2(4000),
58+
/**
59+
*Holds the expected error codes separated by comma when the user use the annotation throws
60+
*/
61+
expected_error_codes varchar2(4000),
5862
constructor function ut_test(
5963
self in out nocopy ut_test, a_object_owner varchar2 := null, a_object_name varchar2, a_name varchar2, a_description varchar2 := null,
6064
a_path varchar2 := null, a_rollback_type integer := null, a_disabled_flag boolean := false,
6165
a_before_each_proc_name varchar2 := null, a_before_test_proc_name varchar2 := null,
62-
a_after_test_proc_name varchar2 := null, a_after_each_proc_name varchar2 := null
66+
a_after_test_proc_name varchar2 := null, a_after_each_proc_name varchar2 := null,
67+
a_expected_error_codes varchar2 := null
6368
) return self as result,
6469
member function is_valid(self in out nocopy ut_test) return boolean,
6570
member procedure set_beforeeach(self in out nocopy ut_test, a_before_each_proc_name varchar2),

source/core/ut_suite_builder.pkb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ create or replace package body ut_suite_builder is
4141

4242
l_beforetest_procedure varchar2(250 char);
4343
l_aftertest_procedure varchar2(250 char);
44+
45+
l_expected_error_codes varchar2(4000);
46+
4447
l_rollback_type integer;
4548
l_displayname varchar2(4000);
4649
function is_last_annotation_for_proc(a_annotations ut_annotations, a_index binary_integer) return boolean is
@@ -71,7 +74,6 @@ create or replace package body ut_suite_builder is
7174
end if;
7275

7376
elsif l_is_suite then
74-
7577
l_proc_name := a_object.annotations(i).subobject_name;
7678

7779
if a_object.annotations(i).name = 'beforeeach' and l_default_setup_proc is null then
@@ -82,14 +84,14 @@ create or replace package body ut_suite_builder is
8284
l_suite_setup_proc := l_proc_name;
8385
elsif a_object.annotations(i).name = 'afterall' and l_suite_teardown_proc is null then
8486
l_suite_teardown_proc := l_proc_name;
85-
86-
8787
elsif a_object.annotations(i).name = 'disabled' then
8888
l_test_disabled := true;
8989
elsif a_object.annotations(i).name = 'beforetest' then
9090
l_beforetest_procedure := a_object.annotations(i).text;
9191
elsif a_object.annotations(i).name = 'aftertest' then
9292
l_aftertest_procedure := a_object.annotations(i).text;
93+
elsif a_object.annotations(i).name = 'throws' then
94+
l_expected_error_codes := a_object.annotations(i).text;
9395
elsif a_object.annotations(i).name in ('displayname','test') then
9496
l_displayname := a_object.annotations(i).text;
9597
if a_object.annotations(i).name = 'test' then
@@ -113,13 +115,15 @@ create or replace package body ut_suite_builder is
113115
,a_rollback_type => coalesce(l_rollback_type, l_suite_rollback)
114116
,a_disabled_flag => l_test_disabled
115117
,a_before_test_proc_name => l_beforetest_procedure
116-
,a_after_test_proc_name => l_aftertest_procedure);
118+
,a_after_test_proc_name => l_aftertest_procedure
119+
,a_expected_error_codes => l_expected_error_codes);
117120

118121
l_is_test := false;
119122
l_test_disabled := false;
120123
l_aftertest_procedure := null;
121124
l_beforetest_procedure := null;
122125
l_rollback_type := null;
126+
l_expected_error_codes := null;
123127
end if;
124128

125129
end if;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
create or replace package body test_annot_throws_exception
2+
is
3+
procedure create_package is
4+
pragma autonomous_transaction;
5+
6+
l_package_spec VARCHAR2(32737);
7+
l_package_body VARCHAR2(32737);
8+
begin
9+
l_package_spec := '
10+
create package annotated_package_with_throws is
11+
--%suite(Dummy package to test annotation throws)
12+
13+
--%test(Throws one exception)
14+
--%throws(-20145)
15+
procedure raised_same_exception;
16+
17+
--%test(Throws one exception)
18+
--%throws(-20144)
19+
procedure raised_diff_exception;
20+
end;
21+
';
22+
23+
l_package_body := '
24+
create package body annotated_package_with_throws is
25+
procedure raised_same_exception is
26+
begin
27+
raise_application_error(-20145, ''Test error'');
28+
end;
29+
30+
procedure raised_diff_exception is
31+
begin
32+
raise_application_error(-20143, ''Test error'');
33+
end;
34+
end;
35+
';
36+
37+
execute immediate l_package_spec;
38+
execute immediate l_package_body;
39+
end;
40+
41+
procedure drop_package is
42+
pragma autonomous_transaction;
43+
44+
l_drop_statment VARCHAR2(32737);
45+
begin
46+
l_drop_statment := 'drop package annotated_package_with_throws';
47+
execute immediate l_drop_statment;
48+
end;
49+
50+
procedure throws_same_annotated_except is
51+
l_result VARCHAR2(32737);
52+
begin
53+
--Act
54+
select column_value
55+
into l_result
56+
from table(ut3.ut.run('annotated_package_with_throws.raised_same_exception', ut3.ut_documentation_reporter()))
57+
where regexp_like(column_value, '^([0-9]+) tests, [0-9]+ failed, [0-9]+ errored, [0-9]+ disabled, [0-9]+ warning\(s\)$');
58+
59+
--Assert
60+
ut.expect(l_result).to_equal('1 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s)');
61+
end;
62+
63+
procedure throws_diff_annotated_except is
64+
l_result VARCHAR2(32737);
65+
begin
66+
--Act
67+
select column_value
68+
into l_result
69+
from table(ut3.ut.run('annotated_package_with_throws.raised_diff_exception', ut3.ut_documentation_reporter()))
70+
where regexp_like(column_value, '^([0-9]+) tests, [0-9]+ failed, [0-9]+ errored, [0-9]+ disabled, [0-9]+ warning\(s\)$');
71+
72+
--Assert
73+
ut.expect(l_result).to_equal('1 tests, 1 failed, 0 errored, 0 disabled, 0 warning(s)');
74+
end;
75+
end;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
create or replace package test_annot_throws_exception
2+
is
3+
--%suite(annotations- throws)
4+
5+
--%beforeall
6+
procedure create_package;
7+
8+
--%afterall
9+
procedure drop_package;
10+
11+
--%test(Gives success when annotated number exception is thrown)
12+
procedure throws_same_annotated_except;
13+
14+
--%test(Gives failure when the raised exception is different that the annotated one)
15+
procedure throws_diff_annotated_except;
16+
end;

test/install_tests.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ whenever oserror exit failure rollback
2929
@@core/expectations/test_expect_to_be_null.pks
3030
@@test_ut_runner.pks
3131
@@core/annotations/test_annotation_manager.pks
32+
@@core/annotations/test_annot_throws_exception.pks
3233
@@core/test_ut_suite.pks
3334
@@core/test_ut_test.pks
3435

@@ -48,6 +49,7 @@ whenever oserror exit failure rollback
4849
@@core/expectations/test_expect_to_be_null.pkb
4950
@@test_ut_runner.pkb
5051
@@core/annotations/test_annotation_manager.pkb
52+
@@core/annotations/test_annot_throws_exception.pkb
5153
@@core/test_ut_suite.pkb
5254
@@core/test_ut_test.pkb
5355

0 commit comments

Comments
 (0)