Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:utPLSQL/utPLSQL into feature/vs_…
Browse files Browse the repository at this point in the history
…pure_sql
  • Loading branch information
lwasylow committed Nov 21, 2018
2 parents 9c8e048 + 80ff76c commit ab36eb2
Show file tree
Hide file tree
Showing 139 changed files with 4,142 additions and 2,569 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -15,6 +15,7 @@ node_modules/
utPLSQL_latest_release/
utPLSQL-cli/
development/env.sh
development/*.jar
*.log

# exclusions based on artifacts created via actions documented in CONTRIBUTING.md
Expand Down
8 changes: 6 additions & 2 deletions CONTRIBUTING.md
Expand Up @@ -89,14 +89,18 @@ export CONNECTION_STR=127.0.0.1:1521/xe # Adjust the connect string
export ORACLE_PWD=oracle # Adjust your local SYS password
```

### Download Oracle JDBC drivers

Download `ojdbc8-xxx.jar` and `orai18n-xxx.jar` from [Oracle](https://www.oracle.com/technetwork/database/features/jdbc/jdbc-ucp-122-3110062.html).
Place them in `development` directory of the project.


### Download utPLSQL release sources and utplsq-cli

The below script is fetching latest release version from utPLSQL repository. Latest release version is used for self-testing.
```bash
development/refresh_sources.sh
```
> **Important notice:**
> You'll have to provide the ojdbc.jar in the folder utPLSQL-cli/lib manually due to Oracle licensing restrictions.

### Setup local database for utPLSQL development

Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
v3.1.3-develop
v3.1.4-develop
1 change: 1 addition & 0 deletions development/refresh_sources.sh
Expand Up @@ -16,3 +16,4 @@ curl -Lk -o utPLSQL-cli.zip https://github.com/utPLSQL/utPLSQL-cli/releases/down
# unzip utPLSQL-cli and remove the zip file
unzip utPLSQL-cli.zip && chmod u+x utPLSQL-cli/bin/utplsql && rm utPLSQL-cli.zip

cp development/*.jar utPLSQL-cli/lib/
3 changes: 2 additions & 1 deletion development/releasing.md
Expand Up @@ -9,7 +9,8 @@ To create a release:
- wait for th build to complete successfully
- merge the release branch to master and wait for master build to complete successfully
- create a release from the master branch using [github releases page](https://github.com/utPLSQL/utPLSQL/releases) and populate release description using information found on the issues and pull requests since previous release.
To find issues closed after certain date use [advanced filters](https://help.github.com/articles/searching-issues-and-pull-requests/#search-by-open-or-closed-state)
To find issues closed after certain date use [advanced filters](https://help.github.com/articles/searching-issues-and-pull-requests/#search-by-open-or-closed-state).
Example: [`is:issue closed:>2018-07-22`](https://github.com/utPLSQL/utPLSQL/issues?utf8=%E2%9C%93&q=is%3Aissue+closed%3A%3E2018-07-22+)

The following will happen:
- build executed on branch `release/vX.Y.Z-[something]` updates files `sonar-project.properties`, `VERSION` with project version derived from the release branch name
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Expand Up @@ -10,6 +10,7 @@ The framework follows industry standards and best patterns of modern Unit Testin
- [Expectations](userguide/expectations.md)
- [Advanced data comparison](userguide/advanced_data_comparison.md)
- [Running unit tests](userguide/running-unit-tests.md)
- [Querying for test suites](userguide/querying_suites.md)
- [Testing best pracitces](userguide/best-practices.md)
- [Upgrade utPLSQL](userguide/upgrade.md)
- Reporting
Expand Down
96 changes: 96 additions & 0 deletions docs/userguide/expectations.md
Expand Up @@ -445,6 +445,8 @@ utPLSQL is capable of comparing compound data-types including:
- Cursors, nested table and varray types are compared as **ordered lists of elements**. If order of elements differ, expectation will fail.
- Comparison of compound data is data-type aware. So a column `ID NUMBER` in a cursor is not the same as `ID VARCHAR2(100)`, even if they both hold the same numeric values.
- Comparison of cursor columns containing `DATE` will only compare date part **and ignore time** by default. See [Comparing cursor data containing DATE fields](#comparing-cursor-data-containing-date-fields) to check how to enable date-time comparison in cursors.
- Comparison of cursor returning `TIMESTAMP` **columns** against cursor returning `TIMESTAMP` **bind variables** requires variables to be casted to proper precision. This is an Oracle SQL - PLSQL compatibility issue and usage of CAST is the only known workaround for now.
See [Comparing cursor data containing TIMESTAMP bind variables](#comparing-cursor-data-containing-timestamp-bind-variables) for examples.
- To compare nested table/varray type you need to convert it to `anydata` by using `anydata.convertCollection()`
- To compare object type you need to convert it to `anydata` by using `anydata.convertObject()`
- It is possible to compare PL/SQL records, collections, varrays and associative arrays. To compare this types of data, use cursor comparison feature of utPLSQL and TABLE operator in SQL query
Expand Down Expand Up @@ -749,6 +751,100 @@ In the above example:
- The test `get_events_for_date_range` will succeed, as the `l_expected_bad_date` cursor contains different date-time then the cursor returned by `get_events` function call.
- The test `bad_test` will fail, as the column `event_date` will get compared as DATE without TIME.

### Comparing cursor data containing TIMESTAMP bind variables

To properly compare `timestamp` column data returned by cursor against bind variable data from another cursor, a conversion needs to be done.

This applies to `timestamp`,`timestamp with timezone`, `timestamp with local timezone` data types.

Example below illustrates usage of `cast` operator to assure appropriate precision is applied on timestamp bind-variables in cursor result-set
```sql
drop table timestamps;
create table timestamps (
ts3 timestamp (3),
ts6 timestamp (6),
ts9 timestamp (9)
);

create or replace package timestamps_api is
procedure load (
i_timestamp3 timestamps.ts3%type,
i_timestamp6 timestamps.ts6%type,
i_timestamp9 timestamps.ts9%type
);
end;
/

create or replace package body timestamps_api is
procedure load (
i_timestamp3 timestamps.ts3%type,
i_timestamp6 timestamps.ts6%type,
i_timestamp9 timestamps.ts9%type
)
is
begin
insert into timestamps (ts3, ts6, ts9)
values (i_timestamp3, i_timestamp6, i_timestamp9);
end;
end;
/


create or replace package test_timestamps_api is
-- %suite

-- %test(Loads data into timestamps table)
procedure test_load;
end;
/

create or replace package body test_timestamps_api is
procedure test_load is
l_time timestamp(9);
l_expected sys_refcursor;
l_actual sys_refcursor;
begin
--Arrange
l_time := systimestamp;

open l_expected for
select
cast(l_time as timestamp(3)) as ts3,
cast(l_time as timestamp(6)) as ts6,
cast(l_time as timestamp(9)) as ts9
from dual;

--Act
timestamps_api.load (
l_time, l_time, l_time
);

--Assert
open l_actual for
select ts3, ts6, ts9
from timestamps;

ut.expect (l_actual).to_equal (l_expected);

end;
end;
/

begin
ut.run ('test_timestamps_api');
end;
/
```

The execution of the above runs successfully
```
test_timestamps_api
Loads data into timestamps table [.046 sec]
Finished in .048181 seconds
1 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s)
```


# Negating a matcher
Expectations provide a very convenient way to perform a check on a negated matcher.
Expand Down
83 changes: 83 additions & 0 deletions docs/userguide/querying_suites.md
@@ -0,0 +1,83 @@
# Qyerying for test suites


## Obtaining information about suites

utPLSQL framework provides ability to read inforamtion about unit test suites that exist in a schema.

Pipelined table function `ut_runner.get_suites_info(a_owner, a_package_name)` allows you to retrieve information about:

- all suites that exist in a given user/schema
- individual test suite pacakage

Querying the data from function provides the follwing details:

- `object_owner` - the owner of test suite packages
- `object_name` - the name of test suite package
- `item_name` - the name of suite/test
- `item_description` - the description of suite/suite item
- `item_type` - the type of item (UT_SUITE/UT_SUITE_CONTEXT/UT_TEST/UT_LOGICAL_SUITE)
- `item_line_no` - line_number where annotation identifying the item exists
- `path` - suitepath of the item
- `disabled_flag` - (0/1) indicator if item is disabled by --%disabled annotation

To get list of all test suites in current schema
```sql
select * from table(ut_runner.get_suites_info()) where item_type = 'UT_SUITE';
```

To get list of all tests for test suite `TEST_STUFF` in current user schema
```sql
select * from table(ut_runner.get_suites_info(USER, 'TEST_STUFF')) where item_type = 'UT_TEST';
```

To get a full information about suite `TEST_STUFF` including suite description, all contexts and tests in a suite
```sql
select * from table(ut_runner.get_suites_info(USER, 'TEST_STUFF')) where item_type = 'UT_TEST';
```

## Checking if schema contains tests

Function `ut_runner.has_suites(a_owner)` returns boolean value indicating if given schema contains test suites.

Example:
```sql
begin
if ut_runner.has_suites(USER) then
dbms_output.put_line( 'User '||USER||' owns test suites' );
else
dbms_output.put_line( 'User '||USER||' does not own test suites' );
end if;
end;
```

## Checking if package is a test suite

Function `ut_runner.is_suite(a_owner, a_package_name) ` returns boolean value indicating if given package is a test suites.

Example:
```sql
begin
if ut_runner.is_suite(USER,'TEST_STUFF') then
dbms_output.put_line( 'Package '||USER||'.TEST_STUFF is a test suite' );
else
dbms_output.put_line( 'Package '||USER||'.TEST_STUFF is not a test suite' );
end if;
end;
```

## Checking if procedure is a test within a suite

Function `ut_runner.is_test(a_owner, a_package_name, a_procedure_name) ` returns boolean value indicating if given package is a test suites.

Example:
```sql
begin
if ut_runner.is_test(USER,'TEST_STUFF','A_TEST_TO_CHECK_STUFF') then
dbms_output.put_line( 'Procedure '||USER||'.TEST_STUFF.A_TEST_TO_CHECK_STUFF is a test' );
else
dbms_output.put_line( 'Procedure '||USER||'.TEST_STUFF.A_TEST_TO_CHECK_STUFF is not a test' );
end if;
end;
```

8 changes: 4 additions & 4 deletions docs/userguide/reporters.md
Expand Up @@ -42,7 +42,7 @@ Example outputs from documentation reporter.
# JUnit reporter

Most of continuous integration servers (like Jenkins) are capable of consuming unit test execution results in [JUnit](https://en.wikipedia.org/wiki/JUnit) format.
The `ut_junit_reporter` in earlier version referred as ut_xunit_reporter is producing outcomes as JUnit-compatible XML unit test report, that can be used by CI servers to display their custom reports and provide metrics (like tests execution trends).
The `ut_junit_reporter` in earlier version referred as `ut_xunit_reporter` is producing outcomes as JUnit-compatible XML unit test report, that can be used by CI servers to display their custom reports and provide metrics (like tests execution trends).
Please note that in previous versions it was called ut_xunit_reporter and for backward compatibility that name still exists.

Invocation of tests with JUnit reporter.
Expand All @@ -63,7 +63,7 @@ Example of failure report details

# Teamcity reporter

[Teamcity](https://www.jetbrains.com/teamcity/) is a CI server by Jetbrains. It supports XUnit reporting and additionally has it's own format of reporting that allows tracking of progress of a CI step/task as it executes.
[Teamcity](https://www.jetbrains.com/teamcity/) is a CI server by Jetbrains. It supports JUnit reporting and additionally has it's own format of reporting that allows tracking of progress of a CI step/task as it executes.
The TeamCity format developed by Jetbrains is supported by utPLSQL with `ut_teamcity_reporter`.

Invocation of tests with Teamcity reporter.
Expand All @@ -74,11 +74,11 @@ The `ut_teamcity_reporter` doesn't accept any arguments.

Example of unit test report from Teamcity CI server.

![xunit_reporter_outputs](../images/teamcity_report_example.png)
![junit_reporter_outputs](../images/teamcity_report_example.png)

Example of failure report details

![xunit_reporter_outputs](../images/teamcity_report_example_errors.png)
![junit_reporter_outputs_errors](../images/teamcity_report_example_errors.png)


# Sonar test reporter
Expand Down
44 changes: 39 additions & 5 deletions docs/userguide/running-unit-tests.md
@@ -1,12 +1,12 @@
# Running tests

The utPLSQL framework provides two main entry points to run unit tests from within the database:
utPLSQL framework provides two main entry points to run unit tests from within the database:

- `ut.run` procedures and functions
- `ut_runner.run` procedures

These two entry points differ in purpose and behavior.
Most of the time you will want to use `ut.run` as `ut_runner` is designed for API integration and does not output the results to the screen directly.
Most of the time you will want to use `ut.run` as `ut_runner.run` is designed for API integration and does not display the results to the screen.

# Running from CI servers and command line

Expand Down Expand Up @@ -123,14 +123,34 @@ You can execute any set of tests with any of the predefined reporters.

```sql
begin
ut.run('hr.test_apply_bonus', ut_xunit_reporter());
ut.run('hr.test_apply_bonus', ut_junit_reporter());
end;
```
Executes all tests from package _HR.TEST_APPLY_BONUS_ and provide outputs to DBMS_OUTPUT using the XUnit reporter.
Executes all tests from package _HR.TEST_APPLY_BONUS_ and provide outputs to DBMS_OUTPUT using the JUnit reporter.


For details on build-in reporters look at [reporters documentation](reporters.md).

## Keeping uncommited data after test-run

utPLSQL by default runs tests in autonomous transaction and performs automatic rollback to assure that tests do not impact one-another and do not have impact on the current session in your IDE.

If you would like to keep your uncommited data persisted after running tests, you can do so by using `a_force_manual_rollback` flag.
Setting this flag to true has following side-effects:

- test execution is done in current transaction - if while running tests commit or rollback is issued your current session data will get commited too.
- automatic rollback is forced to be disabled in test-run even if it was explicitly enabled by using annotation `--%rollback(manual)

Example invocation:
```sql
begin
ut.run('hr.test_apply_bonus', a_force_manual_rollback => true);
end;
```


This option is not anvailable when running tests using `ut.run` as a table function.

## ut.run functions

The `ut.run` functions provide exactly the same functionality as the `ut.run` procedures.
Expand All @@ -140,7 +160,7 @@ Functions provide output as a pipelined stream and therefore need to be executed

Example.
```sql
select * from table(ut.run('hr.test_apply_bonus', ut_xunit_reporter()));
select * from table(ut.run('hr.test_apply_bonus', ut_junit_reporter()));
```

# ut_runner.run procedures
Expand All @@ -158,3 +178,17 @@ The concept is pretty simple.
- as a separate thread, start `ut_runner.run` and pass reporters with previously defined output_ids.
- for each reporter start a separate thread and read outputs from the `ut_output_buffer.get_lines` table function by providing the output_id defined in the main thread.

# Reports characterset encoding

To get properly encoded reports, when running utPLSQL with HTML/XML reports on data containing national characters you need to provide your client character set when calling `ut.run` functions and procedures.

If you run your tests using `utPLSQL-cli`, this is done automatically and no action needs to be taken.

To make sure that the reports will display your national characters properly when running from IDE like SQLDeveloper/TOAD/SQLPlus or sqlcl you need to provide the charaterset manualy to `ut.run`.

Example call with characterset provided:
```sql
begin
ut.run('hr.test_apply_bonus', ut_junit_reporter(), a_client_character_set => 'Windows-1251');
end;
```
2 changes: 0 additions & 2 deletions examples/RunDeveloperExamples.sql
Expand Up @@ -6,8 +6,6 @@ set linesize 1000

exec ut_ansiconsole_helper.color_enabled(true);
--developer examples
prompt RunExampleComplexSuiteWithCustomReporter
@@developer_examples/RunExampleComplexSuiteWithCustomReporter.sql
prompt RunExampleTestSuiteWithCustomReporter
@@developer_examples/RunExampleTestSuiteWithCustomReporter.sql
prompt RunExampleTestAnnotationsParsingTimeHugePackage
Expand Down

0 comments on commit ab36eb2

Please sign in to comment.