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

Skip to content

Commit fcfae1e

Browse files
authored
Merge pull request #129 from jgebal/feature/running_with_many_reporters
Feature/running with many reporters
2 parents 5a99775 + 4f91b64 commit fcfae1e

13 files changed

Lines changed: 572 additions & 111 deletions

File tree

client_source/sqlplus/ut_run.sql

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/**
2+
This script is designed to allow invocation of UTPLSQL with multiple reporters.
3+
It allows saving of outcomes into multiple output files.
4+
It also facilitates displaying on screen unit test results while the execution is still ongoing.
5+
Current limit of script parameters is 39
6+
7+
Scrip invocation:
8+
ut_run.sql user password database [ut_path|ut_paths] (-f=format [-o=output] [-s] ...)
9+
10+
Parameters:
11+
user - username to connect as
12+
password - password of the user
13+
database - database to connect to
14+
ut_path - a path(s) ot unit test(s) to be executed: user[.package[.procedure]]
15+
ut_paths - a comma separated list of ut_path (with no spaces in between)
16+
-f=format - reporter to be used for reporting
17+
-o=output - file name to save the output provided by the reporter.
18+
If defined, the output is not displayed on screen by default. This can be changed with the -s parameter.
19+
If not defined, then output will be displayed on screen, even if the parameter -s is not specified.
20+
If more than one -o parameter is specified for one -f parameter, the last one is taken into consideration.
21+
-s - Forces putting output to to screen for a given -f parameter.
22+
23+
Parameters -f, -o, -s are correlated. That is parameters -o and -s are defining outputs for -f.
24+
Examples of invocation using sqlplus from command line:
25+
26+
sqlplus /nolog @ut_run hr hr xe hr -f=ut_documentation_reporter -o=run.log -s -f=ut_teamcity_reporter -o=teamcity.xml
27+
28+
Unit tests will be be invoked with two reporters:
29+
- ut_documentation_reporter - this one will output to screen and into file "run.log"
30+
- ut_teamcity_reporter - this one will output to file "teamcity.xml"
31+
32+
sqlplus /nolog @ut_run hr hr xe hr -f=ut_documentation_reporter
33+
34+
Unit tests will be be invoked with ut_documentation_reporter as a format and the results will be printed to screen
35+
36+
*/
37+
38+
whenever sqlerror exit failure
39+
whenever oserror exit failure
40+
conn &1/&2@&3
41+
whenever sqlerror continue
42+
whenever oserror continue
43+
44+
set serveroutput on size unlimited format truncated
45+
set trimspool on
46+
set echo off
47+
set termout off
48+
set feedback off
49+
set pagesize 0
50+
set linesize 30000
51+
set long 30000
52+
set longchunksize 30000
53+
set verify off
54+
set heading off
55+
56+
set define off
57+
spool make_input_params_optional.sql.tmp
58+
declare
59+
l_sql_columns varchar2(4000);
60+
begin
61+
for i in 1 .. 100 loop
62+
dbms_output.put_line('column '||i||' new_value '||i);
63+
l_sql_columns := l_sql_columns ||'null as "'||i||'",';
64+
end loop;
65+
dbms_output.put_line('select '||rtrim(l_sql_columns, ',') ||' from dual where rownum = 0;');
66+
end;
67+
/
68+
spool off
69+
set define &
70+
71+
@@make_input_params_optional.sql.tmp
72+
73+
74+
--prepare executor scripts
75+
76+
set define off
77+
spool set_run_params.sql.tmp
78+
declare
79+
l_params varchar2(4000);
80+
begin
81+
for i in 1 .. 100 loop
82+
l_params := l_params || '''&&'||i||''',';
83+
end loop;
84+
dbms_output.put_line('exec ut_runner.set_run_params(ut_varchar2_list('||rtrim(l_params, ',')||'));' );
85+
end;
86+
/
87+
spool off
88+
set define &
89+
90+
91+
@@set_run_params.sql.tmp
92+
93+
94+
spool run_in_backgroung.sql.tmp
95+
declare
96+
l_output_type varchar2(256) := ut_runner.get_streamed_output_type_name();
97+
l_run_params ut_runner.t_run_params := ut_runner.get_run_params();
98+
procedure p(a_text varchar2) is
99+
begin
100+
dbms_output.put_line(a_text);
101+
end;
102+
begin
103+
p( 'set serveroutput on size unlimited format truncated');
104+
p( 'set trimspool on');
105+
p( 'set pagesize 0');
106+
p( 'set linesize 4000');
107+
p( 'spool ut_run.dbms_output.log');
108+
p( 'declare');
109+
p( ' v_reporter ut_reporter;');
110+
p( ' v_reporters_list ut_reporters_list := ut_reporters_list();');
111+
p( 'begin');
112+
for i in 1 .. cardinality(l_run_params.call_params) loop
113+
p(' v_reporter := '||l_run_params.call_params(i).ut_reporter_name||'('||l_output_type||'());');
114+
p(' v_reporter.output.output_id := '''||l_run_params.call_params(i).output_id||''';');
115+
p(' v_reporters_list.extend; v_reporters_list(v_reporters_list.last) := v_reporter;');
116+
end loop;
117+
p( ' ut.run( ut_varchar2_list('||l_run_params.ut_paths||'), ut_composite_reporter( v_reporters_list ) );');
118+
p( 'end;');
119+
p( '/');
120+
p( 'spool off');
121+
p( 'exit');
122+
end;
123+
/
124+
spool off
125+
126+
spool gather_data_from_outputs.sql.tmp
127+
declare
128+
l_output_type varchar2(256) := ut_runner.get_streamed_output_type_name();
129+
l_run_params ut_runner.t_run_params := ut_runner.get_run_params();
130+
l_need_spool boolean;
131+
procedure p(a_text varchar2) is
132+
begin
133+
dbms_output.put_line(a_text);
134+
end;
135+
begin
136+
p('declare l_date date := sysdate; begin loop exit when l_date < sysdate; end loop; end;');
137+
p('/');
138+
for i in 1 .. cardinality(l_run_params.call_params) loop
139+
p('set termout '||l_run_params.call_params(i).output_to_screen);
140+
l_need_spool := (l_run_params.call_params(i).output_file_name is not null);
141+
p(case when l_need_spool then 'spool '||l_run_params.call_params(i).output_file_name||chr(10) end||
142+
'select * from table( '||l_output_type||'().get_lines('''||l_run_params.call_params(i).output_id||''') );'||
143+
case when l_need_spool then chr(10)||'spool off' end);
144+
end loop;
145+
end;
146+
/
147+
148+
spool off
149+
set termout off
150+
set define #
151+
--try running on windows
152+
$ start sqlplus ##1/##2@##3 @run_in_backgroung.sql.tmp
153+
--try running on linus/unix
154+
! sqlplus ##1/##2@##3 @run_in_backgroung.sql.tmp &
155+
set define &
156+
set termout on
157+
--make sure we fetch row by row to indicate the progress
158+
set arraysize 1
159+
@gather_data_from_outputs.sql.tmp
160+
161+
set termout off
162+
--cleanup temporary sql files
163+
--try running on windows
164+
$ del *.sql.tmp
165+
--try running on linus/unix
166+
! rm *.sql.tmp
167+
set termout on
168+
169+
exit

source/core/types/ut_output_stream.tpb

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,46 @@ create or replace type body ut_output_stream as
22

33
overriding final member procedure close(self in out nocopy ut_output_stream) is
44
begin
5-
self.close( a_timeout_sec=>60 );
5+
self.close(a_timeout_sec => 60);
66
end;
77

8-
overriding final member function get_lines(a_output_id varchar2) return ut_varchar2_list pipelined is
8+
overriding final member function get_lines(a_output_id varchar2) return ut_varchar2_list
9+
pipelined is
10+
cursor l_cur is
11+
select column_value from table(self.get_lines(a_output_id, 60 * 60 * 4));
12+
l_col_value varchar2(32767);
913
begin
10-
for i in ( select column_value from table( self.get_lines(a_output_id, 60*60*4) ) ) loop
11-
pipe row(i.column_value);
14+
open l_cur;
15+
16+
-- open-fetch-close routine is used to prevent optimization as we need row by row quering
17+
loop
18+
fetch l_cur
19+
into l_col_value;
20+
exit when l_cur%notfound;
21+
pipe row(l_col_value);
1222
end loop;
23+
24+
close l_cur;
1325
return;
1426
end;
1527

16-
overriding final member function get_clob_lines(a_output_id varchar2) return ut_clob_list pipelined is
28+
overriding final member function get_clob_lines(a_output_id varchar2) return ut_clob_list
29+
pipelined is
30+
cursor l_cur is
31+
select column_value from table(self.get_clob_lines(a_output_id, 60 * 60 * 4));
32+
l_col_value clob;
1733
begin
18-
for i in ( select column_value from table( self.get_clob_lines(a_output_id, 60*60*4) ) ) loop
19-
pipe row(i.column_value);
34+
open l_cur;
35+
36+
-- open-fetch-close routine is used to prevent optimization as we need row by row quering
37+
loop
38+
fetch l_cur
39+
into l_col_value;
40+
exit when l_cur%notfound;
41+
pipe row(l_col_value);
2042
end loop;
43+
44+
close l_cur;
2145
return;
2246
end;
2347

source/core/ut_output_pipe_helper.pkb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ create or replace package body ut_output_pipe_helper is
137137
procedure buffer_and_send(a_output_id t_output_id, a_message_type integer, a_text t_pipe_item:= null) is
138138
l_is_successful boolean;
139139
begin
140-
buffer(a_output_id, a_message_type, a_text);
141-
l_is_successful := send_from_buffer(a_output_id);
140+
buffer(a_output_id, a_message_type, a_text);
141+
l_is_successful := send_from_buffer(a_output_id);
142142
end;
143143
---public
144144

source/core/ut_runner.pkb

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
create or replace package body ut_runner is
2+
3+
g_run_params t_run_params;
4+
5+
procedure run(a_paths in ut_varchar2_list, a_reporter in ut_reporter) is
6+
l_objects_to_run ut_objects_list;
7+
l_reporter ut_reporter := a_reporter;
8+
ut_running_suite ut_test_suite;
9+
begin
10+
ut_suite_manager.configure_execution_by_path(a_paths,l_objects_to_run);
11+
12+
if l_objects_to_run.count > 0 then
13+
l_reporter.before_run(a_suites => l_objects_to_run);
14+
for i in 1 .. l_objects_to_run.count loop
15+
16+
ut_running_suite := treat(l_objects_to_run(i) as ut_test_suite);
17+
ut_running_suite.do_execute(l_reporter);
18+
l_objects_to_run(i) := ut_running_suite;
19+
20+
end loop;
21+
l_reporter.after_run(a_suites => l_objects_to_run);
22+
end if;
23+
end;
24+
25+
26+
procedure run(a_path in varchar2, a_reporter in ut_reporter) is
27+
begin
28+
run(ut_varchar2_list(coalesce(a_path, sys_context('userenv', 'current_schema'))), a_reporter);
29+
end run;
30+
31+
procedure set_run_params(a_params ut_varchar2_list) is
32+
l_call_param t_call_param;
33+
l_call_params tt_call_params := tt_call_params();
34+
l_ut_paths varchar2(4000);
35+
l_force_out_to_screen boolean;
36+
begin
37+
for param in
38+
( with
39+
param_vals as(
40+
select regexp_substr(column_value,'-([fos])\=?(.*)',1,1,'c',1) param_type,
41+
regexp_substr(column_value,'-([fos])\=(.*)',1,1,'c',2) param_value
42+
from table(a_params)
43+
where column_value is not null)
44+
select param_type, param_value
45+
from param_vals
46+
where param_type is not null)
47+
loop
48+
if param.param_type = 'f' then
49+
l_call_params.extend;
50+
l_call_params(l_call_params.last) := l_call_param;
51+
l_call_params(l_call_params.last).ut_reporter_name := param.param_value;
52+
l_force_out_to_screen := false;
53+
elsif l_call_params.last is not null then
54+
if param.param_type = 'o' then
55+
l_call_params(l_call_params.last).output_file_name := param.param_value;
56+
if not l_force_out_to_screen then
57+
l_call_params(l_call_params.last).output_to_screen := 'off';
58+
end if;
59+
elsif param.param_type = 's' then
60+
l_call_params(l_call_params.last).output_to_screen := 'on';
61+
l_force_out_to_screen := true;
62+
end if;
63+
end if;
64+
end loop;
65+
66+
begin
67+
select ''''||replace(ut_paths,',',''',''')||''''
68+
into g_run_params.ut_paths
69+
from (select regexp_substr(column_value,'-p\=(.*)',1,1,'c',1) as ut_paths from table(a_params) )
70+
where ut_paths is not null;
71+
exception
72+
when no_data_found then
73+
g_run_params.ut_paths := 'user';
74+
when too_many_rows then
75+
raise_application_error(-20000, 'Parameter "-p=ut_paths" defined more than once. Only one "-p=ut_paths" parameter can be used.');
76+
end;
77+
for i in 1 .. cardinality(l_call_params) loop
78+
execute immediate 'begin :l_output_id := '||get_streamed_output_type_name()||'().generate_output_id(); end;'
79+
using out l_call_params(i).output_id;
80+
end loop;
81+
g_run_params.call_params := l_call_params;
82+
end set_run_params;
83+
84+
function get_run_params return t_run_params is
85+
begin
86+
return g_run_params;
87+
end;
88+
89+
function get_streamed_output_type_name return varchar2 is
90+
l_result varchar2(255);
91+
begin
92+
select type_name
93+
into l_result
94+
from user_types where supertype_name = 'UT_OUTPUT_STREAM';
95+
return lower(l_result);
96+
end;
97+
98+
end ut_runner;
99+
/

source/core/ut_runner.pks

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
create or replace package ut_runner authid definer is
2+
3+
type t_call_param is record (
4+
ut_reporter_name varchar2(4000),
5+
output_file_name varchar2(4000),
6+
output_to_screen varchar2(3) := 'on',
7+
output_id varchar2(4000)
8+
);
9+
10+
type tt_call_params is table of t_call_param;
11+
12+
type t_run_params is record(
13+
ut_paths varchar2(4000),
14+
call_params tt_call_params
15+
);
16+
17+
procedure run(a_path in varchar2, a_reporter in ut_reporter);
18+
19+
-- implementation to be changed
20+
procedure run(a_paths in ut_varchar2_list, a_reporter in ut_reporter);
21+
22+
23+
24+
----------------------------
25+
-- Client-side executor helper procedures and functions.
26+
27+
procedure set_run_params(a_params ut_varchar2_list);
28+
29+
function get_run_params return t_run_params;
30+
31+
function get_streamed_output_type_name return varchar2;
32+
33+
end ut_runner;
34+
/

0 commit comments

Comments
 (0)