Specifying Tests with DECOR

Making Test Specifications

DECOR allows the specification and generation of tests for messages and documents specified in DECOR; especially HL7 messages and documents.

Tests are specified by stating a simple condition which a message either conforms to or not. The test tooling can then test whether a message fulfills the test requirements. Test specs require an XML file with a 'testset' root element, which will normally reside in apps/hl7[{some-collection}/test_xslt in eXist. Next we will describe the contents of the testset xml.

Content models are described in the following shorthand: X = {@a, @b?, c+, d*) meaning: element X contains 1 attribute a, optionally an attribute b, one or more elements c and zero or more elements d).

testset

This is the root element. It must contain @name.

<testset name="Colonoscopy report testset">

The content model of testset = {@name, @version?, release, test+}.

  • @name: a name for the testset
  • @version: the release of DECOR, it is for documentation purposes only (the DECOR information is retrieved through release/@uri)

release

Must contain @uri, which points to an XML transactionDataset (a transaction in a dataset-like view) retrieved with the RetrieveTransaction function. Preferably an archived version from apps/decor/release, which is fulle specified (i.e. all terminologyAssociations present, all concepts linked to templates etc.).

<testset name="Colonoscopy report testset">
<release uri="http://decor.nictiz.nl/decor/services/RetrieveTransaction?id=2.16.840.1.113883.2.4.3.36.77.4.401&amp;language=nl-NL&amp;version=2014-04-25T12:07:09&amp;format=xml"/>

Note:

  • format must be 'xml'
  • it should retrieve a transaction, not a dataset
  • preferably the 'version' query parameter is used.

test

The content model of test = {@id?, @name, @transactionRef, name+, desc+, suppliedConcepts}

  • @name is the identifier which is used in references
  • @transactionRef must point to a transaction. It is used for retrieval of Xpaths for concepts.

suppliedConcepts

suppliedConcepts = {concept*, assert*}

concept

concepts occur in two forms:

concept = {@ref, @multiplicity, @predicate?}

This form will require the concept which @ref points to, to occur in the tested message the number of times @multiplicity states.

<concept multiplicity="2" ref="2.16.840.1.113883.2.4.3.36.77.2.2.125059">
Incident must occur twice.</concept>

This would require the concept with @id '2.16.840.1.113883.2.4.3.36.77.2.2.125059' to occur twice in a tested message. The text in the concept clause is shown if the condition is not met.

If a predicate attribute is added (i.e. predicate="../hl7:code[@code='445872007']") then this predicate is applied to the node set before the occurrences are counted. In this case, only occurrences which have a parent with a code 445872007 are counted. For predicates:

  • use single quotes only,
  • do not include the outer square brackets, they will be supplied when the schematron is generated.

concept = {@ref, @occurrence?, @predicate?, @assert}

This form is used to require specific values in a concept item in a message.

<concept occurrence="2" assert="@code='9'" ref="2.16.840.1.113883.2.4.3.36.77.2.2.125070">Second incident must be of type "Perforation".</concept>

This would require the second occurrence of the concept with @id '2.16.840.1.113883.2.4.3.36.77.2.2.125070' to contain '9' in @code. The text in the concept clause is shown if the condition is not met. Having the text directly in the tested concept makes the tests readable and maintainable.

If the text contains quotes, they should be double ("...") quotes.

Other possibilities would be:

<concept occurrence="1" assert="@value='5'" ...</concept>
<concept occurrence="1" assert="@unit='mg'" ...</concept>
<concept occurrence="2" assert="@code='N01AH01'" ...</concept>

The counting of occurrences is document-wide at the moment. The test may contain a predicate, as with the multiplicities test. A concept test with an @assert should contain at least one of @occurrence or @predicate, and may contain both.

assert

This form is used for literal schematron tests.

<assert test="count(//hl7:templateId[@root='2.16.840.1.113883.2.4.6.10.90.900927'])=1">
The templateId with root="2.16.840.1.113883.2.4.6.10.90.900927" must occur once.</assert>

This is for schematron asserts, which are output 'as is' in a rule with context='/'. Use when the other mechanisms don't work. (In your local tests file, they should not be in the schematron namespace, but the default namespace, like everything in the tests file.)

Making the Test and Generating Schematron

A first draft of a testset can be made with apps/xis/modules/get-test-stub.xquery. This can be run in your own local eXist installation. Edit the necessary parameters:

let $lang       := 'nl-NL'
let $version    := '2014-04-25T12:07:09'
let $id         := '2.16.840.1.113883.2.4.3.36.77.4.401'

and run the XQuery to generate a testset with all tests for a specific transaction. All tests for multiplicities and assertions are generated, with prefilled texts, making the specification of tests much easier.

When testset is finished, generate schematron with apps/xis/modules/get-test-schematron.xquery. As before, edit the XQuery

let $testName := '*' 
let $testcoll := collection('/db/apps/hl7/peri20-20140416T160211/test_xslt')

to make it point to the right collection. This should be the collection which contains your testsets. Best practice is to use /apps/hl7/{my-project}/test_xslt/ for the collection. After running it, the collection should contain a schematron file for each test. This schematron can be saved to disk to make the SVRL version of the schematron for inclusion in the test engine (not described here).

An example of a generated schematron file:

<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
<!--Schematron generated 2014-05-01T18:04:19.911+02:00, for: rivmsp-test-1-lokatie, transaction: 2.16.840.1.113883.2.4.3.36.77.4.101, version: 2014-04-25T12:07:09-->
    <sch:ns uri="urn:hl7-org:v3" prefix="hl7"/>
    <sch:ns uri="http://www.w3.org/2001/XMLSchema-instance" prefix="xsi"/>
    <sch:ns uri="urn:oid:2.16.840.1.113883.2.4.6.10.35.81" prefix="lab"/>
    <sch:ns uri="http://www.w3.org/XML/1998/namespace" prefix="xml"/>
    <sch:pattern id="Occurs">
        <sch:rule context="/">
 	 	<!--Diepste punt insertie moet precies 1 keer voorkomen.-->
            <sch:assert role="error" test="count(/hl7:ClinicalDocument/hl7:component/hl7:structuredBody/hl7:component[hl7:section[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.204']]]/hl7:section/hl7:entry[hl7:act[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.320']]]/hl7:act/hl7:entryRelationship[hl7:observation[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.330']]]/hl7:observation/hl7:value[not(@negationInd=&#34;true&#34;)])=1">Diepste punt insertie moet 1 keer voorkomen.</sch:assert>
 	 	<!--Laesie (coloscopiecentrum) moet precies 0 keer voorkomen.-->
            <sch:assert role="error" test="count(/hl7:ClinicalDocument/hl7:component/hl7:structuredBody/hl7:component[hl7:section[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.205']]]/hl7:section/hl7:entry[hl7:act[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.333']]]/hl7:act[not(@negationInd=&#34;true&#34;)])=0">Laesie (coloscopiecentrum) moet 0 keer voorkomen.</sch:assert>
        </sch:rule>
    </sch:pattern>
    <sch:pattern id="Values">
        <sch:rule context="/">
 	 	<!--Coecum intubatie[1]  moet aan @value='false' voldoen.-->
            <sch:assert role="error" test="(/hl7:ClinicalDocument/hl7:component/hl7:structuredBody/hl7:component[hl7:section[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.204']]]/hl7:section/hl7:entry[hl7:act[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.320']]]/hl7:act/hl7:entryRelationship[hl7:observation[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.329']]]/hl7:observation/hl7:value)[1]/@value='false'">Coecum intubatie moet "onwaar" zijn.</sch:assert>
 	 	<!--Reden coecum niet bereikt[1]  moet aan @code='11' voldoen.-->
            <sch:assert role="error" test="(/hl7:ClinicalDocument/hl7:component/hl7:structuredBody/hl7:component[hl7:section[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.204']]]/hl7:section/hl7:entry[hl7:act[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.320']]]/hl7:act/hl7:entryRelationship[hl7:observation[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.343']]]/hl7:observation/hl7:value)[1]/@code='11'">Reden coecum niet bereikt moet "Klinische toestand van de patient" zijn.</sch:assert>
 	 	<!--Diepste punt insertie[1]  moet aan @code='362166007' voldoen.-->
            <sch:assert role="error" test="(/hl7:ClinicalDocument/hl7:component/hl7:structuredBody/hl7:component[hl7:section[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.204']]]/hl7:section/hl7:entry[hl7:act[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.320']]]/hl7:act/hl7:entryRelationship[hl7:observation[hl7:templateId[@root='2.16.840.1.113883.2.4.3.36.10.330']]]/hl7:observation/hl7:value)[1]/@code='362166007'">Diepste punt insertie moet "Sigmoid" zijn.</sch:assert>
        </sch:rule>
    </sch:pattern>
</sch:schema>

Generating HTML documentation

The XQuery in apps/xis/modules/get-test-description.xquery can be used to generate HTML documentation of the tests. Again, edit the XQuery to point to your {my-project}-tests.xml, and run it to generate a HTML page which describes all test requirements. This will contain all the texts inside testset/test/suppliedConcepts/concept.

Best practice is to have the text inside the test/concept contain a functional description of the requirement, and have @assert contain the technical description. I.e.

<concept occurrence="2" assert="@code='N01AH01'"
  ref="2.16.840.1.113883.2.4.3.36.77.2.2.140090">Medication [2] must be "Fentanyl".</concept>

describe in concept text what is wanted (the tester should enter 'Fentanyl' in UI of the tested application), and state in @assert what code is required in the (HL7) message.

More information on testing in ART-DECOR

For more information on testing in ART-DECOR, see XIS_maintenance.