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.

Basic assertion

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.

Advanced assertion

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

EDIFACT assertion principles

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

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

XPath examples

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

/INVOIC/GRP2/NAD/C082/e3039

XPath expression to refer 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 all party identifiers in a message:

//NAD/C082/e3039

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

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

EDIFACT-to-XML transformation

Truugo transforms EDIFACT messages to XML before running the validation. Here you can see a simple example of EDIFACT-to-XML transformation.

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'

Transformed to XML:

<?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

Truugo function library helps you implement complicated assertions more efficiently:

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 functions for helping implementation
Example: IfThenElse()
Output
Function for formatting an error notice
Examples: getPath(), getLineNumber(), formatNumber()

Notation for calling Truugo functions:

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

Example of a test to check that CountryCode element contains a valid 2-letter ISO country code:

appFunction('validCountryCode', CountryCode)

Next take also a look at test assertion examples »