The basics of test assertion

A major part of case-specific restrictions for message structure and content can be specified using our no-code/low-code interface, the Subset Editor. More complex requirements, involving filtering, comparisons, external data files and calculations, can be covered as Truugo test assertions or using Schematron.

Test assertion is implemented using XPath 1.0 and Truugo function library.

Pseudo-code presentation of a basic assertion:

FOR EACH TARGET
IF EMPTY(PRECONDITION) OR PRECONDITION == TRUE THEN
IF PREDICATE == FALSE THEN
RETURN NOTICE
END IF
END IF
END FOR EACH
TARGET
Specifies the structure(s) to which a test assertion applies. The target must be an XML element or a list of XML elements. You can use pipe sign "|" to specify multiple targets for a test assertion. To setup a test assertion for XML attribute, use its parent element as a target: /Path/To/Element[@attributeX]
PRECONDITION (optional)
Can be used to apply a test assertion to certain target structure(s) or use case(s) only. If given, the predicate will be evaluated only when the precondition evaluates to true (boolean).
PREDICATE
Specifies the test for the target structure(s).
NOTICE
Descriptive (error) notice which is returned when the predicate test evaluates to false (boolean). You can use XPath function concat() to combine static and dynamic text to the notice.

In order to implement more complex assertions, you may need to add some extra ingredients to a basic assertion:

Pseudo-code presentation of an advanced assertion:

NAMESPACE_PREFIX = NAMESPACE_URI
GLOBAL_VAR_NAME = EXPRESSION
FOR EACH TARGET
LOCAL_VAR_NAME = EXPRESSION
IF EMPTY(PRECONDITION) OR PRECONDITION == TRUE THEN
IF PREDICATE == FALSE THEN
RETURN NOTICE
END IF
END IF
END FOR EACH
NAMESPACE PREFIX

Instead of using a namespace URI in your test assertions:

/my:very:long:namespace:uri:Order

You can define a namespace prefix, such as "doc", to keep XPath expressions shorter (more sensible):

/doc:Order
GLOBAL VARIABLE

A global variable is defined once per a test profile and can be reused in test assertions.

It is used mainly for the following purposes:

  • to setup a switch between loose and strict validation to decide assertions to be executed
  • to specify the use case based on the message data to decide assertions to be executed
  • to perform validation against an external data file (which is read into a variable)
LOCAL VARIABLE

A local variable is not just assertion-specific, it is specified per each target item. The value of a local variable is set within a target loop and thus it can be used as a part of the following expressions: Precondition, Predicate, Notice.

It is used mainly for the following purposes:

  • to split complex logic to sensible parts
  • to reuse calculated values, primarily in Predicate and Notice expressions
  • to use an item value as a filter (within square brackets) in an expression

Truugo transforms EDIFACT messages into XML syntax using the following naming principles:

MESSAGE ROOT
Tag <INVOIC> for the message type INVOIC (UNH.S009.0065)
SEGMENT GROUP
Tag <GRP2> for the segment group 2
SEGMENT
Tag <NAD> for the segment NAD
COMPOSITE
Tag <C082> for the composite C082
ELEMENT
Tag <e3035> for the element 3035

XPath examples

XPath expression to refer to all party identifiers on a header level:

/INVOIC/GRP2/NAD/C082/e3039

XPath expression to refer to all party identifiers on a header and a line level (see the pipe sign):

/INVOIC/GRP2/NAD/C082/e3039|/INVOIC/GRP21/GRP30/NAD/C082/e3039

XPath expression to refer to all party identifiers in a message:

//NAD/C082/e3039

XPath expression to refer to the buyer's party identifier only (using a filter):

/INVOIC/GRP2/NAD[e3035="BY"]/C082/e3039

Truugo transforms EDIFACT messages to XML syntax before running the validation.

Original EDIFACT message:

UNH+A123456+INVOIC:D:96A:UN'
BGM+380+787878+9'
DTM+3:20141022:102'
RFF+ON:555555'
NAD+BY+123456789::16++NORTHERN LIGHT FACTORY'
NAD+SE+333666999::16++MY WIDGET COMPANY'
LIN+1++1248:IN'
IMD+F++:::WIDGET'
QTY+47:200:EA'
MOA+203:224.20'
PRI+INV:1.121'
UNS+S'
MOA+39:224.20'
UNT+13+A123456'

After the EDIFACT-to-XML transformation:

<?xml version="1.0" encoding="UTF-8"?>
<INVOIC release="96A" version="D" syntax="3" codelist="UNSL.96A" separators=":+'">
<UNH>
<e0062>A123456</e0062>
<S009>
<e0065>INVOIC</e0065>
<e0052>D</e0052>
<e0054>96A</e0054>
<e0051>UN</e0051>
</S009>
</UNH>
...
<GRP2>
<NAD>
<e3035>BY</e3035>
<C082>
<e3039>123456789</e3039>
<e3055>16</e3055>
</C082>
<C080>
<e3036>NORTHERN LIGHT FACTORY</e3036>
</C080>
</NAD>
</GRP2>
...
</INVOIC>

Truugo function library makes it easier to implement complex assertions:

Boolean
Functions for checking whether a given value is valid
Examples: validIBAN(), validCountryCode(), validPattern()
Math
Functions for counting or calculating values
Examples: countSum(), countDistinctValues(), countDaysFromNow()
Misc
Special support functions to ease assertion implementation
Example: IfThenElse()
Output
Function for formatting an error notice
Examples: getPath(), getLineNumber(), formatNumber()

The notation for using Truugo functions:

appFunction('function_name', param1[, param2[, paramN]])

An example of how to check that a CountryCode element contains a valid 2-letter ISO country code:

appFunction('validCountryCode', CountryCode)

Next take also a look at test assertion examples »