Skip to content

Commit

Permalink
Merge 45643e0 into f69d65c
Browse files Browse the repository at this point in the history
  • Loading branch information
lwasylow committed Dec 13, 2018
2 parents f69d65c + 45643e0 commit cd0fc62
Show file tree
Hide file tree
Showing 41 changed files with 3,156 additions and 1,211 deletions.
4 changes: 2 additions & 2 deletions docs/about/authors.md
Expand Up @@ -7,11 +7,11 @@
| ---------------- | --------------
| David Pyke | [Shoelace](https://github.com/Shoelace)
| Jacek Gebal | [jgebal](https://github.com/jgebal)
| Lukasz Wasylow | [lwasylow](https://github.com/lwasylow/)
| Pavel Kaplya | [Pazus](https://github.com/Pazus)
| Robert Love | [rlove](https://github.com/rlove)
| Vinicius Avellar | [viniciusam](https://github.com/viniciusam/)
| Samuel Nitsche | [pesse](https://github.com/pesse/)
| Lukasz Wasylow | [lwasylow](https://github.com/lwasylow/)
| Vinicius Avellar | [viniciusam](https://github.com/viniciusam/)



Expand Down
Binary file added docs/images/venn21.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/venn22.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
109 changes: 89 additions & 20 deletions docs/userguide/advanced_data_comparison.md
Expand Up @@ -6,7 +6,7 @@ utPLSQL expectations incorporates advanced data comparison options when comparin
- object type
- nested table and varray

Advanced data-comparison options are available for the [`equal`](expectations.md#equal) matcher.
Advanced data-comparison options are available for the [`equal`](expectations.md#equal) and [`include / contain`](expectations.md#include) matcher.

## Syntax

Expand All @@ -15,6 +15,10 @@ Advanced data-comparison options are available for the [`equal`](expectations.md
ut.expect( a_actual {data-type} ).not_to( equal( a_expected {data-type})[.extendend_option()[.extendend_option()[...]]]) );
ut.expect( a_actual {data-type} ).to_equal( a_expected {data-type})[.extendend_option()[.extendend_option()[...]]]);
ut.expect( a_actual {data-type} ).not_to_equal( a_expected {data-type})[.extendend_option()[.extendend_option()[...]]] );
ut.expect( a_actual {data-type} ).to_contain( a_expected {data-type})[.extendend_option()[.extendend_option()[...]]]);
ut.expect( a_actual {data-type} ).to_include( a_expected {data-type})[.extendend_option()[.extendend_option()[...]]]);
ut.expect( a_actual {data-type} ).not_to_include( a_expected {data-type})[.extendend_option()[.extendend_option()[...]]]);
ut.expect( a_actual {data-type} ).not_to_contain( a_expected {data-type})[.extendend_option()[.extendend_option()[...]]]);
```

`extended_option` can be one of:
Expand All @@ -23,62 +27,77 @@ Advanced data-comparison options are available for the [`equal`](expectations.md
- `exclude(a_items varchar2)` - item or comma separated list of items to exclude
- `include(a_items ut_varchar2_list)` - table of items to include
- `exclude(a_items ut_varchar2_list)` - table of items to exclude
- `unordered` - perform compare on unordered set of data, return only missing or actual
- `join_by(a_columns varchar2)` - columns or comma seperated list of columns to join two cursors by
- `unordered` - perform compare on unordered set of data, return only missing or actual, ***not supported for `include / contain`*** , as alternative `join_by` can be used
- `join_by(a_columns varchar2)` - columns or comma separated list of columns to join two cursors by
- `join_by(a_columns ut_varchar2_list)` - table of columns to join two cursors by

Each item in the comma separated list can be:
- a column name of cursor to be compared
- an attribute name of object type to be compared
- an attribute name of object type within a table of objects to be compared
- an [XPath](http://zvon.org/xxl/XPathTutorial/Output/example1.html) expression representing column/attribute
- Include and exclude option will not support implicit colum names that starts with single quota, or in fact any other special characters e.g. <, >, &

Each element in `ut_varchar2_list` nested table can be an item or a comma separated list of items.

When specifying column/attribute names, keep in mind that the names are **case sensitive**.

**XPath expressions with comma are not supported.**

## Excluding elements from data comparison

Consider the following example
Consider the following examples
```sql
procedure test_cursors_skip_columns is
procedure test_cur_skip_columns_eq is
l_expected sys_refcursor;
l_actual sys_refcursor;
begin
open l_expected for select 'text' ignore_me, d.* from user_tables d;
open l_actual for select sysdate "ADate", d.* from user_tables d;
ut.expect( l_actual ).to_equal( l_expected ).exclude( 'IGNORE_ME,ADate' );
end;

procedure test_cur_skip_columns_cn is
l_expected sys_refcursor;
l_actual sys_refcursor;
begin
open l_expected for select 'text' ignore_me, d.* from user_tables d;
open l_actual for select sysdate "ADate", d.* from user_tables d;
ut.expect( l_actual ).to_include( l_expected ).exclude( 'IGNORE_ME,ADate' );
end;
```

Columns 'ignore_me' and "ADate" will get excluded from cursor comparison.
The cursor data is equal, when those columns are excluded.
The cursor data is equal or includes expected, when those columns are excluded.

This option is useful in scenarios, when you need to exclude incomparable/unpredictable column data like CREATE_DATE of a record that is maintained by default value on a table column.

## Selecting columns for data comparison

Consider the following example
```sql
procedure include_columns_as_csv is
procedure include_col_as_csv_eq is
l_actual sys_refcursor;
l_expected sys_refcursor;
begin
open l_expected for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL from dual a connect by level < 4;
open l_actual for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL, a.* from all_objects a where rownum < 4;
ut.expect( l_actual ).to_equal( l_expected ).include( 'RN,A_Column,SOME_COL' );
end;

procedure include_col_as_csv_cn is
l_actual sys_refcursor;
l_expected sys_refcursor;
begin
open l_expected for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL from dual a connect by level < 4;
open l_actual for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL, a.* from all_objects a where rownum < 6;
ut.expect( l_actual ).to_contain( l_expected ).include( 'RN,A_Column,SOME_COL' );
end;
```

## Combining include/exclude options
You can chain the advanced options in an expectation and mix the `varchar2` with `ut_varchar2_list` arguments.
When doing so, the fianl list of items to include/exclude will be a concatenation of all items.
When doing so, the final list of items to include/exclude will be a concatenation of all items.

```sql
procedure include_columns_as_csv is
procedure include_col_as_csv_eq is
l_actual sys_refcursor;
l_expected sys_refcursor;
begin
Expand All @@ -89,6 +108,19 @@ begin
.include( ut_varchar2_list( 'A_Column', 'SOME_COL' ) )
.exclude( 'SOME_COL' );
end;

procedure include_col_as_csv_cn is
l_actual sys_refcursor;
l_expected sys_refcursor;
begin
open l_expected for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL from dual a connect by level < 4;
open l_actual for select rownum as rn, 'a' as "A_Column", 'Y' SOME_COL, a.* from all_objects a where rownum < 6;
ut.expect( l_actual ).to_contain( l_expected )
.include( 'RN')
.include( ut_varchar2_list( 'A_Column', 'SOME_COL' ) )
.exclude( 'SOME_COL' );
end;

```

Only the columns 'RN', "A_Column" will be compared. Column 'SOME_COL' is excluded.
Expand All @@ -101,6 +133,8 @@ Unordered option allows for quick comparison of two cursors without need of orde

Result of such comparison will be limited to only information about row existing or not existing in given set without actual information about exact differences.

**This option is not supported for `include / contain` matcher**



```sql
Expand Down Expand Up @@ -169,6 +203,33 @@ This will show you difference in row 'TEST' regardless of order.

Assumption is that join by is made by column name so that what will be displayed as part of results.

Consider this example using `contain / include `

```sql
procedure join_by_username_cn is
l_actual sys_refcursor;
l_expected sys_refcursor;
begin
open l_actual for select username, user_id from all_users;
open l_expected for select username, user_id from all_users
union all
select 'TEST' username, -610 user_id from dual;

ut.expect( l_actual ).to_contain( l_expected ).join_by('USERNAME');
end;
```

This will show you that one value is not included in actual set:

```sql
Actual: refcursor [ count = 43 ] was expected to include: refcursor [ count = 44 ]
Diff:
Rows: [ 1 differences ]
PK <USERNAME>TEST</USERNAME> - Missing <USER_ID>-610</USER_ID>
```



Join by options currently doesn't support nested table inside cursor comparison, however is still possible to compare a collection as a whole.

Example.
Expand Down Expand Up @@ -220,25 +281,33 @@ Diff:



***Please note that .join_by option will take longer to process due to need of parsing via primary keys.***

## Defining item lists in option
XPath expressions are deprecated. They are currently still supported but in future versions they can be removed completely. Please use a current standard of defining items filter.

**Please note that .join_by option will take longer to process due to need of parsing via primary keys.**

## Defining item as XPath
When using XPath expression, keep in mind the following:
When using item list expression, keep in mind the following:

- cursor columns are nested under `<ROW>` element
- object type attributes are nested under `<OBJECTY_TYPE>` element
- nested table and varray items type attributes are nested under `<ARRAY><OBJECTY_TYPE>` elements

Example of a valid XPath parameter to include columns: `RN`, `A_Column`, `SOME_COL` in data comparison.
Example of a valid parameter to include columns: `RN`, `A_Column`, `SOME_COL` in data comparison.
```sql
procedure include_columns_as_xpath is
procedure include_col_list_eq is
l_actual sys_refcursor;
l_expected sys_refcursor;
begin
open l_expected for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL from dual a connect by level < 4;
open l_actual for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL, a.* from all_objects a where rownum < 4;
ut.expect( l_actual ).to_equal( l_expected ).include( '/ROW/RN|/ROW/A_Column|/ROW/SOME_COL' );
ut.expect( l_actual ).to_equal( l_expected ).include( 'RN,A_Column,SOME_COL' );
end;

procedure include_col_list_eq is
l_actual sys_refcursor;
l_expected sys_refcursor;
begin
open l_expected for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL from dual a connect by level < 4;
open l_actual for select rownum as rn, 'a' as "A_Column", 'x' SOME_COL, a.* from all_objects a where rownum < 6;
ut.expect( l_actual ).to_include( l_expected ).include( 'RN,A_Column,SOME_COL' );
end;
```

0 comments on commit cd0fc62

Please sign in to comment.