Touchstone FHIR Testing
2.0.0 - current International flag

Touchstone FHIR Testing v2.0.0. This is the current published version. For a full list of available versions, see the Directory of published versions

Guidance

This section outlines important definitions and interpretations and requirements common to all AEGIS Touchstone Testing actors used in this guide. The conformance verbs used are defined in FHIR Conformance Rules.


Touchstone Placeholders

The Touchstone Placeholders are special predefined TestScript variables and may be used where standard TestScript variables are allowed: static fixtures and operation.params, operation.requestHeader.value, operation.url, and assert.value element values.

These Touchstone Placeholders fall into two (2) categories

  • Predefined User Unique Data Values
  • Functions for Dynamic Data Generation

Predefined User Unique Data Values

The predefined user unique data value placeholders are strings of varying lengths from 1 to 20 characters. They are defined of three (3) types:

  • Character only; for example, ${C6}
  • Digits only; for example, ${D9}
  • Characters + Digits; for example, ${CD14}

Users may view their assigned placeholder variable values in Touchstone via the user name menu item ${} My Placeholders.

Guaranteed Value Uniqueness - All predefined user unique data value placeholder values with a character length of 6 or more are guaranteed to be unique.

Functions for Dynamic Data Generation

There are three (3) available functional constructs for dynamic data generation:

  • CURRENTDATE and CURRENTDATETIME
  • DATE and DATETIME (relative to dynamic variable)
  • UUID, UUID-ST, UUID-NODASH and UUID-ST-NODASH
CURRENTDATE[TIME]

These function placeholder variables provide support for date and datetime values based on the current date (today) and current datetime (now). Optional comma separated offset arguments apply date and time arithmetic providing relative date and time generated values.

Syntax/Format ${<placeholder name>[, <datetime portion code>, <offset value>]} Where,

  • <placeholder name> is CURRENTDATE or CURRENTDATETIME
  • <datetime portion code> is the character indicating what portion of the date or datetime value will be offset. Valid characters are derived from the following Java SimpleDateFormat pattern string “yyMMddHHmmss”
  • <offset value> is the signed integer value used to adjust the date or time
  • <datetime portion code>, <offset value> may be repeated for more complex arithmetic

Examples

Placeholder Example Description
${CURRENTDATE} The current date (today)
${CURRENTDATETIME} The current date and time (today)
${CURRENTDATE,d,-10} The date 10 days before the current date
${CURRENTDATETIME,d,10} The date and time 10 days after the current date and time
${CURRENTDATE,y,-1} The date 1 year before the current date
${CURRENTDATETIME,H,10} The date and time 10 hours after the current date and time
DATE[TIME]

These function placeholder variables provide support for date and datetime values based on a dynamic variable user input date or datetime value. Optional comma separated offset arguments apply date and time arithmetic providing relative date and time generated values.

Syntax/Format ${<placeholder name>, <relative value>[, <datetime portion code>, <offset value>]} Where,

  • <placeholder name> is DATE or DATETIME
  • <relative value> is a dynamic variable defined in the current TestScript that holds the relative date or datetime value
    • The dynamic variable must be defined in TestScript without path/expression; its value will be entered by the user during Test Setup
  • <datetime portion code> is the character indicating what portion of the date or datetime value will be offset. Valid characters are derived from the following Java SimpleDateFormat pattern string “yyMMddHHmmss”
  • <offset value> is the signed integer value used to adjust the date or time
  • <datetime portion code>, <offset value> may be repeated for more complex arithmetic

Examples

Placeholder Example Description
${DATE, medicationDate} The value of the user entered medicationDate will be used as-is
${DATETIME, medicationDateTime} The value of the user entered medicationDateTime will be used as-is
${DATE, medicationDate, d, -10} The value of the user entered medicationDate minus 10 days will be used
${DATETIME, medicationDateTime, M, -1} The value of the user entered medicationDateTime minus 1 month will be used
UUID[-ST|-NODASH|-ST-NODASH]

These function placeholder variables provide support for generation of UUID values with predefined formatting.

Syntax/Format ${<placeholder name>} Where,

  • <placeholder name> is UUID, UUID-ST, UUID-NODASH or UUID-ST-NODASH

Examples

Placeholder Example Description
${UUID} A single generated UUID string value without the standard prefix; e.g., '3ed6eb79-fc68-443a-996f-08167f5bdef0'
${UUID-ST} A single generated UUID string value including the standard prefix; e.g., 'urn:uuid:3ed6eb79-fc68-443a-996f-08167f5bdef0'
${UUID-NODASH} A single generated UUID string value without the standard prefix and dash characters removed; e.g., '3ed6eb79fc68443a996f08167f5bdef0'
${UUID-ST-NODASH} A single generated UUID string value including the standard prefix and dash characters removed; e.g., 'urn:uuid:3ed6eb79fc68443a996f08167f5bdef0'

Usage

The Touchstone Placeholder, both predefined values and functions, are typically defined in static fixtures used as an operation request payload; for example, create or update. Touchstone’s TestScript Execution interface provides both a Raw and Resolved view of static fixtures where the pre and post test execution contents can be examined.

Raw Example - Patient.name, Patient.birthDate

<name>
  <use value="official"/>
  <family value="Smith${C7}"/>
  <given value="John${C6}"/>
  <birthDate value="${CURRENTDATE,d,-7}"/>
</name>

Resolved Example - Patient.name, Patient.birthDate

<name>
  <use value="official"/>
  <family value="SmithMqCERSQ"/>
  <given value="JohnXRCnsc"/>
  <birthDate value="2021-01-27"/>
</name>

Minimum ID (minimumID) Assert Processing

The FHIR specification’s definition of FHIR Testing contains a brief description within the Test search operation section on how a Test Engine is to evaluate and process a TestScript assert using the minimumId element. This description states:

<action>
	<assert>
		<minimumId value="F1"/>
		<sourceId value="R1"/>
	</assert>
</action>

Test engines will parse the 'body' of the F1 fixture and verify that each element and its value matches the corresponding element in the R1 response body. In other words, R1 is verified to be a 'superset' of F1. The resource id element in the body will be ignored during comparison. The headers will also be ignored.

F1 can be statically defined or it can be the [responseId](http://hl7.org/fhir/testscript-definitions.html#TestScript.setup.action.operation.responseId) for another operation. If [sourceId](http://hl7.org/fhir/testscript-definitions.html#TestScript.setup.action.assert.sourceId) is not specified, then test engines will use the response of the last operation.

This is a high-level functional description that does not provide sufficient information regarding the required definition of how the detailed comparison is to be performed. In order to provide more clarity the Touchstone implementation of the minimumId assert comparison logic now provides the following structural comparison of the minimumId fixture and the fixture being evaluated behaviors:

  • Attribute or element ordering - If the comparison encounters an order mismatch of an attribute or element between the minimumId fixture and the fixture being evaluated, this does not result in an error as long as the path to the attribute or element matches.
    • This is particularly important when comparing JSON formatted fixtures where attribute order is not significant.
    • For example, the following two fixtures are considered to be matching:
      {
        name: "hello",
        title: "goodbye"
      }
      
      {
        title: "goodbye",
        name: "hello"
      }
      
  • Array value ordering - The order of an array of the same attribute or element is allowed to differ in the comparison; also, additional attribute or element instances are allowed in between the minimumId fixture attribute or element instances such that the index can differ.
    • For example, the following two fixtures are considered equal even though the order of array elements differs:
      min fixture:
      {
        names: ["hello", "goodbye"]
      }
      
      compare fixture:
      {
        names: ["goodbye", "hello"]
      }
      
    • For example, these fixtures would match even though there are extra values:
      min fixture:
      {
        names: ["hello", "goodbye"]
      }
      
      compare1 fixture:
      {
        names: ["hello", "greeting", "goodbye"]
      }
      
      compare2 fixture:
      {
        names: ["greeting", "hello", "goodbye"]
      }
      
      compare3 fixture:
      {
        names: ["hello", "goodbye", "greeting"]
      }
      
  • Duplicate attributes or elements - When the minimumId fixture has duplicate attributes or elements (in a JSON attribute array or XML repeated element) the fixture being evaluated must have the same number of duplicated attributes or elements.
    • For example, the following two fixtures would not match as the compare fixture does not have the same number of duplicate repeating attributes as the min fixture:
      min fixture:
      {
        names: ["hello", "hello"]
      }
      
      compare1 fixture:
      {
        names: ["hello"]
      }
      
  • Comparison results - The comparison results now include ALL inconsistencies between the minimumId fixture and the fixture being evaluated (previously only the first mismatch was reported back to the user).

  • Attribute or element present regardless of value - The ability to allow for the existence of an attribute or element regardless of its value is possible with the XML syntax but not JSON due to the JSON requirement that an attribute value must be present.
    • For example, this minimumId fixture XML element without a value will match any same named XML element in the fixture being evaluated regardless of its value:
      <novalueelement/>
      
    • This concept cannot be expressed in JSON syntax.

Rule and RuleSet Extensions

The TestScript rule and ruleset extensions can be used to reference complex validation logic that goes beyond what the basic TestScript assert element supports. As such, rules are recommended only when a TestScript assert cannot be used in its basic form.

The Touchstone Rules-Engine supports rules written in the following languages:

  • Groovy
  • XSLT
  • Schematron

The Touchstone online user guide on TestScript Authoring - Rule Authoring provides comprehensive documentation on the definition and use of rules and rulesets.

Support for additional languages may be added in the future. Unless you plan on executing test scripts against a test system that only supports XML, it is highly recommended to write rules in Groovy as XSLT and Schematron rules can only be evaluated against requests and responses whose content is in XML while Groovy supports JSON as well.


HL7 V2 Message Support

Touchstone includes support for testing HL7 V2 Message exchange using MLLP (Minimum Lower Layer Protocol). When TestScript operations are processed and asserts evaluated for HL7 V2 messages, the FHIR test engine is restricted to the following behaviors.

TestScript Operations

The TestScript.setup.action.operation and TestScript.test.action.operation definition is constrained to the following behaviors when executing an HL7 V2 message:

V2 Message Behavior Operation Element Description
Support type The operation code type that will be executed
Ignore resource Resource type
Support label Tracking/logging operation label
Support description Tracking/reporting operation description
Ignore accept Mime type to accept in the payload of the response, with charset etc.
Ignore contentType Mime type of the request payload contents, with charset etc.
Support destination Server responding to the request
Support encodeRequestUrl [Always 'false' for MLLP protocol] Whether or not to send the request url in encoded format
Ignore method delete | get | options | patch | post | put | head
Support origin Server initiating the request
Ignore params Explicitly defined path parameters
Ignore requestHeader Each operation can have one or more header elements
Ignore field HTTP header field name
Ignore value HTTP headerfield value
Support requestId Fixture Id of mapped request
Support responseId Fixture Id of mapped response
Support sourceId Fixture Id of body for PUT and POST requests
Ignore targetId Id of fixture used for extracting the [id], [type], and [vid] for GET requests
Support url Request URL
TestScript Operation “encodeRequestUrl”

The TestScript operation “encodeRequestUrl” is a required (1..1 cardinaality) element that defines whether an HTTP request url is encoded or not. When an HL7 V2 message is sent via MLLP. the “encodeRequestUrl” element value MUST be ‘false’.

TestScript Operation “url”

The TestScript operation “url” is designed to override the auto-generated HTTP request url. Whether the HL7 V2 message is sent via MLLP or HTTP, the use of the “url” element is still a valid construct to override the destination location / endpoint.

TestScript Operation FHIR and HTTP Specific Elements - Ignored

Ignored. The TestScript operation “resource”, “accept”, “contentType”, “method”, “params”, “requestHeader.field”, “requestHeader.value” and “targetId” are specific to the HL7 FHIR and HTTP specifications.

TestScript Asserts

The TestScript.setup.action.assert and TestScript.test.action.assert definition is constrained to the following behaviors when evaluating an HL7 V2 message:

V2 Message Behavior Assert Element Description
Support label Tracking/logging assertion label
Support description Tracking/reporting assertion description
Support direction response | request
Support compareToSourceId Id of the source fixture to be evaluated
Support compareToSourceExpression The V2 Path expression to evaluate against the source fixture
Ignore compareToSourcePath XPath or JSONPath expression to evaluate against the source fixture
Ignore contentType Mime type to compare against the 'Content-Type' header
Support expression The V2 Path expression to be evaluated
Ignore headerField HTTP header field name
Ignore minimumId Fixture Id of minimum content resource
Ignore navigationLinks Perform validation on navigation links?
Support operator equals | notEquals | in | notIn | greaterThan | lessThan | empty | notEmpty | contains | notContains | eval
Ignore path XPath or JSONPath expression
Ignore requestMethod delete | get | options | patch | post | put | head
Ignore requestURL Request URL comparison value
Ignore resource Resource type
Ignore response okay | created | noContent | notModified | bad | forbidden | notFound | methodNotAllowed | conflict | gone | preconditionFailed | unprocessable
Ignore responseCode HTTP response code to test
Support sourceId Fixture Id of source expression or headerField
Support validateProfileId Profile Id of validation profile reference
Support value The value to compare to
Support warningOnly Will this assert produce a warning only on error?
TestScript Assert operator comparison behavior

The TestScript assert “operator” element typically requires a path or expression element value that evaluates the XML or JSON FHIR content as the source of comparison. Since the HL7 V2 message is in a text format, its contents can be directly compared without any pathing language expression. The following example assert demonstrates this behavior:

<assert>
  <description value="Confirm an HL7 V2 ACK message was received"/>
  <direction value="response"/>
  <operator value="contains"/>
  <value value="ACK"/>
</assert>
TestScript Assert “expression”

The TestScript author may still use the assert “expression” elements to obtain the source value for comparison.

The TestScript assert “expression” elements, compareToSourceExpression and expression, require an HL7 V2 message path expression language evaluator. In the case of FHIR there is FHIRPath. Support for HL7 V2 message path expressions has been implemented through the use of the HAPI HL7v2 libraries. Please see section HL7 V2 Message Path Expression Syntax below for details.

TestScript Assert “validateProfileId”

HL7 V2 message validation services are currently implemented using the HAPI HL7v2 libraries. While there is a concept of V2 message profiling, the current implementation of the HL7 V2 message validation service does not support their use.

The TestScript assert.validationProfileId element requires a TestScript.profile.id value in order for the FHIR test engine to perform this assert’s evaluation. In order to provide a TestScript.profile.id without a corresponding profile reference the FHIR test engine will ignore any defined profile reference associated with the TestScript.profile.id.

Since the TestScript.profile.reference will be ignored, the recommended definition of the TestScript.profile will simply define a TestScript.profile.display value. Here is an example that can be used:

<profile id="hl7v2validate">
  <display value="Placeholder for HL7 V2 validation assert"/>
</profile>

The corresponding assert with the validatorProfileId will then be:

<assert>
  <description value="Validate the HL7 V2 message received"/>
  <direction value="response"/>
  <validatorProfileId value="hl7v2validate"/>
</assert>

TestScript Author Note - The profile.id value of “hl7v2validate” can be any valid id value; for example, “foo”. The only requirement is that the profile.id value and assert.validatorProfileId values are the same.

TestScript Assert FHIR and HTTP Specific Elements - Ignored

Ignored. The TestScript assert “compareToSourcePath”, “contentType”, “headerField”, “navigationLinks”, “path”, “requestMethod”, “requestURL”, “resource”, “response” and “responseCode” are specific to the HL7 FHIR and HTTP specifications.

HL7 V2 Message Path Expression Syntax

A V2 message path defines a specific segmentID, field number and component / sub-component within the field using the following syntax.

Syntax/Format SEG[(a)]-b[(c)[-d[-e]]]

Where,

  • SEG is the segmentID.
  • (a) is an optional segment repetition, zero(0) based. If a is not given, a defaults to zero(0).
  • b is the field number. Numbering starts at one(1) which represents the first field after the segmentID.
    • MSH Segment Only - Numbering for the MSH segment only starts at two(2) for the first field after the “MSH” segmentID.
  • (c) is an optional field number repetition, zero(0) based. If c is not given, c defaults to zero(0).
  • d is the component number within the given field. Numbering starts at one(1).
  • e is the sub-component number within the given component. Numbering starts at one(1).

Example V2 Message

MSH|^~\&|MS4_AZ|UNV|PREMISE|UNV|20180301010000||ADT^A04|IHS-20180301010000.00120|P|2.3
EVN|A04|20180301010000
PID|1||||BUNNY^BUGS^RABBIT^^^MS||19830215|M|||1234 LOONEY RD^APT A^CRAIGMONT^ID^83523^USA|||||||111-11-1111|111-11-1111
PV1|1|E|ED^^^UNV|C|||999-99-9999^MUNCHER^CHANDRA^ANDRIA^MD^DR|888-88-8888^SMETHERS^ANNETTA^JONI^MD^DR||||||7||||REF||||||||||||||||||||||||||20180301010000
Z01|abc~cba|def|ghi
Z01|123^999|456|789
V2 Path Evaluated Value(s)
MSH-4 UNV
PID-5 BUNNY
PID-5-2 BUGS
PID-5-2,PID-5-1 BUGS,BUNNY
Z01-1 abc
Z01(0)-1(1) cba
Z01(1)-1-2 999

HL7 V3 Message Support

Touchstone includes support for testing HL7 V3 Message exchange using HTTP / SOAP. When TestScript operations are processed and asserts evaluated for HL7 V3 messages, the FHIR test engine is restricted to the following behaviors.

TestScript Operations

The TestScript.setup.action.operation and TestScript.test.action.operation definition is constrained to the following behaviors when executing an HL7 V3 message:

V3 Message Behavior Operation Element Description
Support type The operation code type that will be executed
Ignore resource Resource type
Support label Tracking/logging operation label
Support description Tracking/reporting operation description
Support accept [See accept and contentType below] Mime type to accept in the payload of the response, with charset etc.
Support contentType [See accept and contentType below] Mime type of the request payload contents, with charset etc.
Support destination Server responding to the request
Support encodeRequestUrl Whether or not to send the request url in encoded format
Support method [V3 allowed values] post | put
Support origin Server initiating the request
Support params Explicitly defined path parameters
Support requestHeader Each operation can have one or more header elements
Support field HTTP header field name
Support value HTTP headerfield value
Support requestId Fixture Id of mapped request
Support responseId Fixture Id of mapped response
Support sourceId Fixture Id of body for PUT and POST requests
Ignore targetId Id of fixture used for extracting the [id], [type], and [vid] for GET requests
Support url Request URL
TestScript Operation “accept” and “contentType”

The TestScript operation “accept” and “contentType” element coded values xml, json are converted to the corresponding FHIR mime types application/fhir+xml, application/fhir+json by the Test Engine. The HL7 V3 message payload / body uses the mime type of application/xml. Therefore, the TestScript author must override the use of the TestScript operation “accept” and “contentType” elements with the use of the explicit “requestHeader” element:

<requestHeader>
  <field value="Accept"/>
  <value value="application/xml"/>
</requestHeader>
<requestHeader>
  <field value="Content-Type"/>
  <value value="application/xml"/>
</requestHeader>
TestScript Operation “method”

The TestScript operation “method” element allows the TestScript author to override the default HTTP method used by Touchstone acting as the client system or the external client system in a Peer-to-Peer test execution. The default HTTP method for an HL7 V3 message request is POST with an HL7 V3 message payload / body. The HTTP PUT is the only other method that supports a message payload / body. So, the TestScript operation “method” element value is restricted to “post” and “put”.

TestScript Operation FHIR Specific Elements - Ignored

Ignored. The TestScript operation “resource” and “targetId” are specific to the HL7 FHIR specification.

TestScript Asserts

The TestScript.setup.action.assert and TestScript.test.action.assert definition is constrained to the following behaviors when evaluating an HL7 V3 message:

V3 Message Behavior Assert Element Description
Support label Tracking/logging assertion label
Support description Tracking/reporting assertion description
Support direction response | request
Support compareToSourceId Id of the source fixture to be evaluated
Ignore compareToSourceExpression The FHIRPath expression to evaluate against the source fixture
Support compareToSourcePath XPath expression to evaluate against the source fixture
Support contentType Mime type to compare against the 'Content-Type' header
Ignore expression The FHIRPath expression to be evaluated
Support headerField HTTP header field name
Support minimumId Fixture Id of minimum content resource
Ignore navigationLinks Perform validation on navigation links?
Support operator equals | notEquals | in | notIn | greaterThan | lessThan | empty | notEmpty | contains | notContains | eval
Support path XPath expression
Support requestMethod [V3 allowed values] post | put
Support requestURL Request URL comparison value
Ignore resource Resource type
Support response okay | created | noContent | notModified | bad | forbidden | notFound | methodNotAllowed | conflict | gone | preconditionFailed | unprocessable
Support responseCode HTTP response code to test
Support sourceId Fixture Id of source expression or headerField
Support validateProfileId Profile Id of validation profile reference
Support value The value to compare to
Support warningOnly Will this assert produce a warning only on error?
TestScript Assert “path”

The TestScript assert “path” elements, compareToSourcePath and path, normally allow for eith XPath or JSONPath expressions. HL7 V3 messages are restricted to XML so, the only allowed path language for HL7 V3 messages is XPath.

TestScript Assert “validateProfileId”

HL7 V3 message validation services are currently pending.

The TestScript assert.validationProfileId element requires a TestScript.profile.id value in order for the FHIR test engine to perform this assert’s evaluation. In order to provide a TestScript.profile.id without a corresponding profile reference the FHIR test engine will ignore any defined profile reference associated with the TestScript.profile.id.

Since the TestScript.profile.reference will be ignored, the recommended definition of the TestScript.profile will simply define a TestScript.profile.display value. Here is an example that can be used:

<profile id="hl7v3validate">
  <display value="Placeholder for HL7 V3 validation assert"/>
</profile>

The corresponding assert with the validatorProfileId will then be:

<assert>
  <description value="Validate the HL7 V2 message received"/>
  <direction value="response"/>
  <validatorProfileId value="hl7v3validate"/>
</assert>

TestScript Author Note - The profile.id value of “hl7v3validate” can be any valid id value; for example, “foo”. The only requirement is that the profile.id value and assert.validatorProfileId values are the same.

TestScript Assert FHIR Specific Elements - Ignored

Ignored. The TestScript assert “compareToSourceExpression”, “expression”, “navigationLinks” and “resource” are specific to the HL7 FHIR specification.


OAuth2 Capabilities

Touchstone has the ability for a user to create and use a Test System that is OAuth2 enabled, and with that comes new features that are important to take note of when it comes to Test Executions performed against a Test System that has an OAuth2 Authorization service connected to it.

TestScript Extensions

With the addition of a more robust OAuth2, SMART-on-FHIR and Bulk Data support into Touchstone, there are new extensions under the TestScript.test and TestScript.test.operation elements to support the manual control of test execution behavior and execution of the various OAuth2 authorization flows that are available to test script authors.

Pre-defined Fixture Ids

With the addition of a more robust OAuth2 environment into Touchstone, there are new fixtures, and values under those fixtures, that are available to test script authors.

  • One new fixture is the dest1SmartConfig (dest2SmartConfig, dest3SmartConfig, etc.). The fixture allows the test script author to access different variables coming from the JSON document that is at the .well-known/smart-configuration.json endpoint. It acts the same as retrieving variables from the capabilities statement. For example, to use dest1SmartConfig to retrieve the Client ID, you would use the sourceId and path in the testscript as sourceId = dest1SmartConfig, path = $.clientId.

  • Test Systems have special Oauth2 values that can be be retrieved by test script authors. The fixtures have a naming convention of dest1SystemConfig, dest2SystemConfig, origin1SystemConfig, origin2SystemConfig, etc. These fixtures have the following attributes:

Attribute Name Description
name The Test System name
fullName The Organization name + the Test System name
baseUrl The Base URL of the Test System
supportsSmartOnFhir Set to true if the Test System supports SMART on FHIR, false if it does not
oauth2GrantType The Grant Type of the OAuth2 enables Test System, either Authorization Code or Client Credentials
clientId The Client ID of the Test System that is registered with the OAuth2 server.
clientSecret The Client Secret of the Test System that is registered with the OAuth2 server.
authEndpoint The Authorization Endpoint for the Test System.
tokenEndpoint The Token Endpoint for the Test System.
registerEndpoint The Registration Endpoint for the Test System.
introspectEndpoint The Introspection Endpoint for the Test System.
revocationEndpoint The Revocation Endpoint for the Test System.
scopesSupported The scopes that allowed for the server access to certain user scopes
  • Another set of fixtures that can be used by the user in the test scripts are oauth2AuthzRequest and oauth2AuthzRedirect. These two fixtures are used to access parts of the last OAuth2 Authroization Request sent to the OAuth2 server and the last OAuth2 Authorization response returned from the server.

Base64Encoding

Touchstone is configured to use a Base64Encoding on the operation.requestHeader.value when it includes Basic + A Single Space “ “ ahead of the value and when the operation.requestHeader.name is equal to Authorization in your Testscript executions. This is done for security and is the explanation as to why an Authorization value in the header will be different from the one that was originally coded.


Bulk Data Capabilities

Touchstone has the ability for a user to create and use a Test System that supports the Bulk Data specification. Touchstone provides additional features that provide support for the evaluation and validation of the NDJSON returned files.

NDJSON File Evalutation and Validation

The Bulk Data specification defines a new FHIR extended operation $export which generates bulk data output files containing multiple FHIR resources using the NDJSON format for FHIR - application/fhir+ndjson.

Evaluation and validation of this NDJSON format for FHIR requires extended capabilities be implemented on the FHIR Test Engine and extended definitions within the FHIR TestScript resource. Touchstone has implemented these extended capabilities through the use of NDJSON Assertion Prefix syntax within the values of the following TestScript elements:

  • TestScript.profile.reference
  • TestScript.test.action.assert.expression
  • TestScript.test.action.assert.path
  • TestScript.test.action.assert.resource

NDJSON Assertion Prefix Syntax and Usage

NDJSON Assertion Prefix syntax is specified within curly braces proceeding the normal expected content of these element values and is composed of 3 optional parts:

{ Evaluation-Operator | Filter-Index-Range | Filter-Path } Regular-Assert

The NDJSON Assertion Prefix syntax is applied in 4 stages:

  1. Filter-Path evaluation. Example: .name[?(@.family=='Gracia')] - all Patients whose name.family is 'Gracia'. A resource is included if the JSON-Path evaluation results in a Truthy value (exists and is not false). If no Filter-Path is specified then all resources filter through.
  2. Filter-Index-Range. Example: 1-10 - include resources indexed 1 through 10 in the assertion evaluation. If Filter-Index-Range is not specified then all resources filter through. If Filter-Path is specified then Filter-Index-Range operates on the resources that made it through the Filter-Path and not the original resources.
  3. Regular-Assert. The Profile/Expression/Path/Resource evaluation on resources that made it past 1 and 2. Example: Patient (if assertion is resource).
  4. Evaluation-Operator. 'any' or 'all' - If 'any' operator is used then overall assertion evaluation passes if a single resource passes. The default is 'all'.
TestScript Example

The following TestScript provides a comprehensive list of asserts that show various usage examples of the NDJSON Assertion Prefix Syntax.

Here are some portions from this TestScript illustrating key examples of the NDJSON Assertion Prefix syntax.

TestScript.profile.reference

Using the NDJSON Assertion Prefix syntax in the TestScript.profile.reference element allows for specific profile definitions with this syntax to be used in any assert.validateProfileId evaluation; i.e. where the FHIR Validation Engine is invoked. The syntax stages are applied in the same sequence where the FHIR Validation Engine invocation is executed a step 3 Regular-Assert.

Here are three (3) profile definitions and corresponding asserts showing the use of each optional NDJSON Assertion Prefix syntax item.

  1. { Evaluation-Operator 'any' } Regular-Assert
    <profile id="resource-profile-for-any">
      <!-- Assert passes as long as any resource in the NDJSON contents validates successfully against the FHIR Patient profile. -->
      <reference value="{any}http://hl7.org/fhir/StructureDefinition/Patient"/>
    </profile>
    ...
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Validate that the returned resource conforms to the corresponding FHIR resource profile."/>
        <direction value="response"/>
        <validateProfileId value="resource-profile-for-any"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  2. { Filter-Index-Range } Regular-Assert
    <profile id="resource-profile-for-first">
      <!-- Assert passes as long as the first five (5) resources in the NDJSON contents validates successfully against the FHIR Patient profile. -->
      <reference value="{1-5}http://hl7.org/fhir/StructureDefinition/Patient"/>
    </profile>
    ...
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Validate that the returned resource conforms to the corresponding FHIR resource profile."/>
        <direction value="response"/>
        <validateProfileId value="resource-profile-for-first"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  3. { Filter-Path } Regular-Assert
    <profile id="resource-profile-for-Gracia">
      <!-- Assert passes as long as the those resources where name.family equals 'Garcia' in the NDJSON contents validates successfully against the FHIR Patient profile. -->
      <reference value="{.name[?(@.family=='Gracia')]}http://hl7.org/fhir/StructureDefinition/Patient"/>
    </profile>
    ...
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Validate that the returned resource conforms to the corresponding FHIR resource profile."/>
        <direction value="response"/>
        <validateProfileId value="resource-profile-for-Gracia"/>
        <warningOnly value="false"/>
      </assert>
    </action>
TestScript.test.action.assert.expression

The following asserts show the use of various combinations of the NDJSON Assertion Prefix syntax items within the assert.expression element. Please refer to each assert.description element for details of expected behavior.

  1. { Evaluation-Operator 'any' } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as any resource in the NDJSON contents contains a Patient.name.family value in 'Allen,Gracia'"/>
        <direction value="response"/>
        <expression value="{any}Patient.name.family"/>
        <operator value="in"/>
        <value value="Allen,Gracia"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  2. { Evaluation-Operator 'all' } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as all resource in the NDJSON contents contain a Patient.name.family value equal to 'Allen'"/>
        <direction value="response"/>
        <expression value="{all}Patient.name.family"/>
        <operator value="equals"/>
        <value value="Allen"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  3. { Filter-Index-Range } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as the first three (3) resources in the NDJSON contents contain a Patient.name.family value in 'McKay,Gracia,Allen'"/>
        <direction value="response"/>
        <expression value="{1-3}Patient.name.family"/>
        <operator value="in"/>
        <value value="McKay,Gracia,Allen"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  4. { Filter-Path } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as the resources in the NDJSON contents that contain a name.family value equal to 'Allen' contain a Patient.name.given value in 'Carol,G'"/>
        <direction value="response"/>
        <expression value="{.name[?(@.family=='Allen')]}Patient.name.given"/>
        <operator value="in"/>
        <value value="Carol,G"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  5. { Filter-Index-Range | Filter-Path } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as the first three (3) resources in the NDJSON contents that contain a name.family value equal to 'McKay' contain a Patient.name.given value equal to 'George'"/>
        <direction value="response"/>
        <expression value="{1-3 | .name[?(@.family=='McKay')]}Patient.name.given"/>
        <operator value="equals"/>
        <value value="George"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  6. { Evaluation-Operator 'any' | Filter-Index-Range | Filter-Path } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as the any of the first three (3) resources in the NDJSON contents that contain a name.family value equal to 'McKay' contain a Patient.name.given value equal to 'George'"/>
        <direction value="response"/>
        <expression value="{any | 1-3 | .name[?(@.family=='McKay')]}Patient.name.given"/>
        <operator value="equals"/>
        <value value="George"/>
        <warningOnly value="false"/>
      </assert>
    </action>
TestScript.test.action.assert.path

The following asserts show the use of various combinations of the NDJSON Assertion Prefix syntax items within the assert.path element. Please refer to each assert.description element for details of expected behavior.

  1. { Evaluation-Operator 'any' } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as any resource in the NDJSON contents contains a generalPractitioner.reference value"/>
        <direction value="response"/>
        <operator value="equals"/>
        <path value="{any}generalPractitioner.reference"/>
        <value value="Practitioner/2"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  2. { Filter-Index-Range } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as the 2-5 resources in the NDJSON contents contain a generalPractitioner.reference value that contains 'Practitioner'"/>
        <direction value="response"/>
        <operator value="contains"/>
        <path value="{2-5}generalPractitioner.reference"/>
        <value value="Practitioner/"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  3. { Filter-Path } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as the resources in the NDJSON contents that contain a generalPractitioner.reference value equal to 'Practitioner/3' contain a name.family value equal to 'Allen'"/>
        <direction value="response"/>
        <operator value="equals"/>
        <path value="{generalPractitioner[?(@.reference=='Practitioner/3')]}name.family"/>
        <value value="Allen"/>
        <warningOnly value="false"/>
      </assert>
    </action>
TestScript.test.action.assert.resouce

The following asserts show the use of various combinations of the NDJSON Assertion Prefix syntax items within the assert.resource element. Please refer to each assert.description element for details of expected behavior.

WARNING - THE USE OF THE NDJSON Assertion Prefix SYNTAX WITHIN THE assert.resource ELEMENT PREVENTS THE CONTAINING TESTSCRIPT RESOURCE FROM VALIDATING ON UPLOAD TO TOUCHSTONE.

  1. { Evaluation-Operator 'any' } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as any resource in the NDJSON contents is a FHIR Patient resource type"/>
        <direction value="response"/>
        <resource value="{any}Patient"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  2. { Filter-Index-Range } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as the first five (5) resources in the NDJSON contents is a FHIR Patient resource type"/>
        <direction value="response"/>
        <resource value="{1-5}Patient"/>
        <warningOnly value="false"/>
      </assert>
    </action>
  3. { Filter-Path } Regular-Assert
    <action>
      <assert>
        <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-stopTestOnFail">
          <valueBoolean value="false"/>
        </extension>
        <description value="Assert passes as long as all the resources in the NDJSON contents that contain a name.family value equal to 'Gracia' is a FHIR Patient resource type"/>
        <direction value="response"/>
        <resource value="{.name[?(@.family=='Gracia')]}Patient"/>
        <warningOnly value="false"/>
      </assert>
    </action>