Skip to content

Commit

Permalink
[WIP] Ability to run expectations without test
Browse files Browse the repository at this point in the history
> TODO - documentation updates

Added ability to run expectations without tests.
Expectation, when executed without test is reporter straight to dbms_output.
So it is now possible to execute:

`exec ut.expect(1).to_equal(0);`

And get result:

```
FAILURE
  Actual: 1 (number) was expected to equal: 0 (number)
```

Resolves #956

Additionally:
- utPLSQL is now cleaning up the application_info after run.
- utPLSQL is setting session context during run, making it possible to access some of utPLSQL info within the test procedures directly.

Resolves #781

The information is provided in sys_context(`UT3_INFO`,...).

Following attributes are getting populated:
- Always:
    - RUN_PATHS
    - SUITE_DESCRIPTION
    - SUITE_PACKAGE
    - SUITE_PATH
    - SUITE_START_TIME
    - CURRENT_EXECUTABLE_NAME
    - CURRENT_EXECUTABLE_TYPE

- When running in suite context
    - CONTEXT_NAME
    - CONTEXT_PATH
    - CONTEXT_START_TIME
- After first executable in suite
    - TIME_IN_SUITE
- After first executable in suite context
    - TIME_IN_CONTEXT
- When running a test or before/after each/test
    - TEST_DESCRIPTION
    - TEST_NAME
    - TEST_START_TIME
- After first executable in test
    - TIME_IN_TEST
  • Loading branch information
jgebal committed Jul 2, 2019
1 parent eaff720 commit e172d40
Show file tree
Hide file tree
Showing 24 changed files with 899 additions and 46 deletions.
2 changes: 2 additions & 0 deletions .travis/install_utplsql_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ fi

"$SQLCLI" sys/$ORACLE_PWD@//$CONNECTION_STR AS SYSDBA <<SQL
alter session set plsql_optimize_level=0;
alter session set plsql_ccflags = 'SELF_TESTING_INSTALL:TRUE';
@${INSTALL_FILE} ${UT3_RELEASE_VERSION_SCHEMA}
exit
SQL
Expand Down
1 change: 1 addition & 0 deletions source/api/ut_runner.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ create or replace package body ut_runner is
else
ut_event_manager.add_listener( ut_documentation_reporter() );
end if;
ut_event_manager.add_listener( ut_session_info() );

ut_event_manager.trigger_event(ut_event_manager.gc_initialize);
ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info());
Expand Down
52 changes: 52 additions & 0 deletions source/core/session_context/ut_session_context.pkb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
create or replace package body ut_session_context as
/*
utPLSQL - Version 3
Copyright 2016 - 2019 utPLSQL Project

Licensed under the Apache License, Version 2.0 (the "License"):
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
$IF $$SELF_TESTING_INSTALL $THEN
gc_context_name constant varchar2(30) := ut_utils.ut_owner()||'_INFO';
$ELSE
gc_context_name constant varchar2(30) := 'UT3_INFO';
$END

procedure set_context(a_name varchar2, a_value varchar2) is
begin
dbms_session.set_context( gc_context_name, a_name, a_value );
end;

procedure clear_context(a_name varchar2) is
begin
dbms_session.clear_context( namespace => gc_context_name, attribute => a_name );
end;

procedure clear_all_context is
begin
dbms_session.clear_all_context( namespace => gc_context_name );
end;

function is_ut_run return boolean is
l_paths varchar2(32767);
begin
l_paths := sys_context(gc_context_name, 'RUN_PATHS');
return l_paths is not null;
end;

function get_namespace return varchar2 is
begin
return gc_context_name;
end;

end;
/
45 changes: 45 additions & 0 deletions source/core/session_context/ut_session_context.pks
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
create or replace package ut_session_context as
/*
utPLSQL - Version 3
Copyright 2016 - 2019 utPLSQL Project

Licensed under the Apache License, Version 2.0 (the "License"):
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
* Sets value of a context
*/
procedure set_context(a_name varchar2, a_value varchar2);

/*
* Clears value of a context
*/
procedure clear_context(a_name varchar2);

/*
* Clears entire context for utPLSQL run
*/
procedure clear_all_context;

/*
* Returns true, if session context UT3_INFO is not empty
*/
function is_ut_run return boolean;

/*
* Returns utPLSQL session context namespace name
*/
function get_namespace return varchar2;

end;
/
199 changes: 199 additions & 0 deletions source/core/session_context/ut_session_info.tpb
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
create or replace type body ut_session_info as
/*
utPLSQL - Version 3
Copyright 2016 - 2019 utPLSQL Project

Licensed under the Apache License, Version 2.0 (the "License"):
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

constructor function ut_session_info(self in out nocopy ut_session_info) return self as result is
begin
self.self_type := $$plsql_unit;
dbms_application_info.read_client_info( client_info );
dbms_application_info.read_module( module, action );
return;
end;

-- run hooks
member procedure before_calling_run(self in out nocopy ut_session_info, a_run in ut_run) is
begin
ut_session_context.set_context( 'run_paths', ut_utils.to_string( ut_utils.table_to_clob( a_run.run_paths,',' ), null ) );
dbms_application_info.set_module( 'utPLSQL', null );
end;

member procedure after_calling_run(self in out nocopy ut_session_info, a_run in ut_run) is
begin
ut_session_context.clear_context( 'run_paths' );
dbms_application_info.set_module( module, action );
dbms_application_info.set_client_info( client_info );
end;

-- suite hooks
member procedure before_calling_suite(self in out nocopy ut_session_info, a_suite in ut_logical_suite) is
begin
if a_suite is not of (ut_suite_context) then
suite_start_time := a_suite.start_time;
ut_session_context.set_context( 'suite_path', a_suite.path );
ut_session_context.set_context( 'suite_package', a_suite.object_owner||'.'||a_suite.object_name );
ut_session_context.set_context( 'suite_description', a_suite.description );
ut_session_context.set_context( 'suite_start_time', ut_utils.to_string(suite_start_time) );
dbms_application_info.set_module( 'utPLSQL', a_suite.object_name );
else
context_start_time := a_suite.start_time;
ut_session_context.set_context( 'context_name', a_suite.name );
ut_session_context.set_context( 'context_path', a_suite.path);
ut_session_context.set_context( 'context_description', a_suite.description );
ut_session_context.set_context( 'context_start_time', ut_utils.to_string(context_start_time) );
end if;
end;

member procedure after_calling_suite(self in out nocopy ut_session_info, a_suite in ut_logical_suite) is
begin
if a_suite is not of (ut_suite_context) then
ut_session_context.clear_context( 'suite_package' );
ut_session_context.clear_context( 'suite_path' );
ut_session_context.clear_context( 'suite_description' );
ut_session_context.clear_context( 'suite_start_time' );
ut_session_context.clear_context( 'time_in_suite' );
suite_start_time := null;
else
ut_session_context.clear_context( 'context_name' );
ut_session_context.clear_context( 'context_path' );
ut_session_context.clear_context( 'context_description' );
ut_session_context.clear_context( 'context_start_time' );
ut_session_context.clear_context( 'time_in_context' );
context_start_time := null;
end if;
end;


member procedure before_calling_test(self in out nocopy ut_session_info, a_test in ut_test) is
begin
test_start_time := a_test.start_time;
ut_session_context.set_context( 'test_name', a_test.object_owner||'.'||a_test.object_name||'.'||a_test.name );
ut_session_context.set_context( 'test_description', a_test.description );
ut_session_context.set_context( 'test_start_time', ut_utils.to_string(test_start_time) );
end;

member procedure after_calling_test (self in out nocopy ut_session_info, a_test in ut_test) is
begin
ut_session_context.clear_context( 'test_name' );
ut_session_context.clear_context( 'test_description' );
ut_session_context.clear_context( 'test_start_time' );
ut_session_context.clear_context( 'time_in_test' );
test_start_time := null;
end;

member procedure before_calling_executable(self in out nocopy ut_session_info, a_executable in ut_executable) is
begin
ut_session_context.set_context( 'current_executable_type', a_executable.executable_type );
ut_session_context.set_context(
'current_executable_name',
a_executable.owner_name||'.'||a_executable.object_name||'.'||a_executable.procedure_name
);
dbms_application_info.set_client_info( a_executable.procedure_name );
if suite_start_time is not null then
ut_session_context.set_context( 'time_in_suite', current_timestamp - suite_start_time );
if context_start_time is not null then
ut_session_context.set_context( 'time_in_context', current_timestamp - context_start_time );
end if;
if test_start_time is not null then
ut_session_context.set_context( 'time_in_test', current_timestamp - test_start_time );
end if;
end if;
end;

member procedure after_calling_executable(self in out nocopy ut_session_info, a_executable in ut_executable) is
begin
ut_session_context.clear_context( 'current_executable_type' );
ut_session_context.clear_context( 'current_executable_name' );
dbms_application_info.set_client_info( null );
end;

member procedure on_finalize(self in out nocopy ut_session_info, a_run in ut_run) is
begin
dbms_application_info.set_client_info( client_info );
dbms_application_info.set_module( module, action );
ut_session_context.clear_all_context();
end;

overriding member function get_supported_events return ut_varchar2_list is
begin
return ut_varchar2_list(
ut_event_manager.gc_before_run,
ut_event_manager.gc_before_suite,
ut_event_manager.gc_before_test,
ut_event_manager.gc_before_before_all,
ut_event_manager.gc_before_before_each,
ut_event_manager.gc_before_before_test,
ut_event_manager.gc_before_test_execute,
ut_event_manager.gc_before_after_test,
ut_event_manager.gc_before_after_each,
ut_event_manager.gc_before_after_all,
ut_event_manager.gc_after_run,
ut_event_manager.gc_after_suite,
ut_event_manager.gc_after_test,
ut_event_manager.gc_after_before_all,
ut_event_manager.gc_after_before_each,
ut_event_manager.gc_after_before_test,
ut_event_manager.gc_after_test_execute,
ut_event_manager.gc_after_after_test,
ut_event_manager.gc_after_after_each,
ut_event_manager.gc_after_after_all,
ut_event_manager.gc_finalize
);
end;

overriding member procedure on_event( self in out nocopy ut_session_info, a_event_name varchar2, a_event_item ut_event_item) is
begin
case
when a_event_name in (
ut_event_manager.gc_before_before_all,
ut_event_manager.gc_before_before_each,
ut_event_manager.gc_before_before_test,
ut_event_manager.gc_before_test_execute,
ut_event_manager.gc_before_after_test,
ut_event_manager.gc_before_after_each,
ut_event_manager.gc_before_after_all
)
then before_calling_executable(treat(a_event_item as ut_executable));
when a_event_name in (
ut_event_manager.gc_after_before_all,
ut_event_manager.gc_after_before_each,
ut_event_manager.gc_after_before_test,
ut_event_manager.gc_after_test_execute,
ut_event_manager.gc_after_after_test,
ut_event_manager.gc_after_after_each,
ut_event_manager.gc_after_after_all
)
then after_calling_executable(treat(a_event_item as ut_executable));
when a_event_name = ut_event_manager.gc_before_test
then self.before_calling_test(treat(a_event_item as ut_test));
when a_event_name = ut_event_manager.gc_after_test
then self.after_calling_test(treat(a_event_item as ut_test));
when a_event_name = ut_event_manager.gc_after_suite
then after_calling_suite(treat(a_event_item as ut_logical_suite));
when a_event_name = ut_event_manager.gc_before_suite
then before_calling_suite(treat(a_event_item as ut_logical_suite));
when a_event_name = ut_event_manager.gc_before_run
then before_calling_run(treat(a_event_item as ut_run));
when a_event_name = ut_event_manager.gc_after_run
then after_calling_run(treat(a_event_item as ut_run));
when a_event_name = ut_event_manager.gc_finalize
then on_finalize(treat(a_event_item as ut_run));
else null;
end case;
end;

end;
/
52 changes: 52 additions & 0 deletions source/core/session_context/ut_session_info.tps
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
create or replace type ut_session_info under ut_event_listener (
/*
utPLSQL - Version 3
Copyright 2016 - 2019 utPLSQL Project

Licensed under the Apache License, Version 2.0 (the "License"):
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

module varchar2(4000),
action varchar2(4000),
client_info varchar2(4000),
suite_start_time timestamp,
context_start_time timestamp,
test_start_time timestamp,
constructor function ut_session_info(self in out nocopy ut_session_info) return self as result,

member procedure before_calling_run(self in out nocopy ut_session_info, a_run in ut_run),
member procedure after_calling_run (self in out nocopy ut_session_info, a_run in ut_run),

member procedure before_calling_suite(self in out nocopy ut_session_info, a_suite in ut_logical_suite),
member procedure after_calling_suite(self in out nocopy ut_session_info, a_suite in ut_logical_suite),

member procedure before_calling_executable(self in out nocopy ut_session_info, a_executable in ut_executable),
member procedure after_calling_executable (self in out nocopy ut_session_info, a_executable in ut_executable),

member procedure before_calling_test(self in out nocopy ut_session_info, a_test in ut_test),
member procedure after_calling_test (self in out nocopy ut_session_info, a_test in ut_test),

member procedure on_finalize(self in out nocopy ut_session_info, a_run in ut_run),

/**
* Returns the list of events that are supported by particular implementation of the reporter
*/
overriding member function get_supported_events return ut_varchar2_list,

/**
* Delegates execution of event into individual reporting procedures
*/
overriding member procedure on_event( self in out nocopy ut_session_info, a_event_name varchar2, a_event_item ut_event_item)

) final
/
4 changes: 0 additions & 4 deletions source/core/types/ut_executable.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ create or replace type body ut_executable is
begin
l_start_transaction_id := dbms_transaction.local_transaction_id(true);

-- report to application_info
ut_utils.set_client_info(self.procedure_name);

--listener - before call to executable
ut_event_manager.trigger_event('before_'||self.executable_type, self);

Expand Down Expand Up @@ -173,7 +170,6 @@ create or replace type body ut_executable is
if l_start_transaction_id != l_end_transaction_id or l_end_transaction_id is null then
a_item.add_transaction_invalidator(self.form_name());
end if;
ut_utils.set_client_info(null);

return l_completed_without_errors;

Expand Down
Loading

0 comments on commit e172d40

Please sign in to comment.