angoca / db2unit

db2unit is a testing framework for IBM DB2 SQL PL
https://angoca.github.io/db2unit/
GNU General Public License v3.0
11 stars 3 forks source link

Compare XML with a specific Path #96

Open angoca opened 9 years ago

angoca commented 9 years ago

Probably, the complete XML document does not need to be compare, but just a part of it.

The assertion should provide a path in the document

For a common path:

ASSERT_XML_EQUAL(XML, XML, VARCHAR)

For a different path:

ASSERT_XML_EQUAL(XML, VARCHAR, XML, VARCHAR)
dibdotdob commented 9 years ago

I've coded this enhancement though wanted to discuss the interface. The implementation / coding is cleaner / concise if procedure parameter defaults are used. Doing so means the one procedure can cater for no path, a common path, or different paths.

Proposed procedure interface:

ASSERT_XML_EQUAL(
  IN DOC1 XML
, IN DOC2 XML
, IN PATH1 CLOB DEFAULT NULL
, IN PATH2 CLOB DEFAULT NULL
)

Example call with no path:

CALL ASSERT_XML_EQUAL(DOC1, DOC2)

Example call with common path:

CALL ASSERT_XML_EQUAL(DOC1, DOC2, PATH1)

Example call with different paths:

CALL ASSERT_XML_EQUAL(DOC1, DOC2, PATH1, PATH2)
angoca commented 9 years ago

I find this approach very good!

This reduces the quantity of code, and the maintainability is better. By having default as /, it will take into account the whole document isn't it? Also, the existing code could be modified, and just more tests should be added in order to validate the extra parameters.

The only thing is that the API section in the wiki should explain this clearly.

dibdotdob commented 9 years ago

I've coded so that the QUERY_XML is called only if a value has been provided for PATH1 / PATH2. This will be more efficient ( IF...ELSE vs CALL ) when no path values have been given.

  IF (DOCUMENT1 IS NOT NULL AND DOCUMENT2 IS NOT NULL) THEN
    IF PATH1 IS NOT NULL THEN
      CALL QUERY_XML(DOCUMENT1, PATH1, SEQUENCE1);-- Path.
    ELSE
      SET SEQUENCE1 = DOCUMENT1;-- No path.
    END IF;
    IF PATH2 IS NOT NULL THEN
      CALL QUERY_XML(DOCUMENT2, PATH2, SEQUENCE2);-- Different path.
    ELSEIF PATH1 IS NOT NULL THEN
      CALL QUERY_XML(DOCUMENT2, PATH1, SEQUENCE2);-- Common path.
    ELSE
      SET SEQUENCE2 = DOCUMENT2;-- No path.
    END IF;
    SET EQUAL = DEEP_EQUAL(SEQUENCE1, SEQUENCE2);-- Compare.
  END IF;

Yes, existing code could be changed to make use of this approach. For example, procedures for asserts with message could be removed.

angoca commented 9 years ago

The messages are used for a description of the assertion. They provide a message in the report, and this helps to identify an error, when multiple assertions are called in a test.

More information about the assertions can be found there: https://github.com/angoca/db2unit/wiki/Custom-assert

Once the new assertions are included, the Cheat Sheet should reflect this.

dibdotdob commented 9 years ago

Sorry, but I didn't express myself very well. I meant to say that asserts with no message could be removed by providing a NULL default for the MESSAGE parameter. Though an issue with providing parameter defaults in that you have to use parm_name => pram_value notation for parameters without defaults defined after a parameter with a default. Moving the MESSAGE parameter to the end of the parameter list would address the issue to an extent. For example, a procedure defined like this:

ALTER MODULE DB2UNIT ADD
  PROCEDURE ASSERT_XML_EQUALS (
_IF __SQLSTATE_429BB _THEN
  IN EXPECTED CLOB,
  IN ACTUAL CLOB,
_ELSE
  IN EXPECTED XML,
  IN ACTUAL XML,
_END
  IN PATH1 CLOB DEFAULT NULL,
  IN PATH2 CLOB DEFAULT NULL,
  IN MESSAGE ANCHOR MAX_VALUES.MESSAGE_ASSERT DEFAULT NULL
  )

This one procedure could support a call with no message:

CALL DB2UNIT.ASSERT_XML_EQUALS(D1, D2, P1, P2); 

As well as a call with a message:

CALL DB2UNIT.ASSERT_XML_EQUALS(D1, D2, P1, P2, M); 

It can also support a call with message and no paths though would require using => notation for the MESSAGE parameter:

CALL DB2UNIT.ASSERT_XML_EQUALS(D1, D2, MESSAGE => M);

Alternatively the MESSAGE parameter could be kept at the beginning which would need procedure calls to change to use => for all parameters. For example, a call with no message or paths would be:

CALL DB2UNIT.ASSERT_XML_EQUALS(EXPECTED => D1, ACTUAL => D2);