Parameters

We checked for the presence of ‘ETag’ header earlier in the AssertHeader.groovy rule. If we wanted to also check for the presence of ‘LastModified’ header, we could create another rule definition and have the following assert in it:

response.assertHeaderNotEmpty('LastModified')

The code is the same as we used earlier. Only the header value is different. Creating a separate rule definition for each value that you expect in an exchange would lead to an explosive number of rule definitions in the system with lots of rule logic duplication. This is hard to maintain.

It is better to have a single rule definition (AssertHeader.groovy) and pass the header as a parameter.

Definition

Parameters are defined in the comments section of the Groovy rule definition after the description:

/*
   rule.summary=Response '${param.header}' header cannot be empty
   rule.description=Validates the '${param.header}' header in the response
   rule.param.header.required=true
*/

response.assertHeaderNotEmpty('${param.header}')

We’re defining the ‘header’ parameter and making it required. The system will check what rule parameters are required by a rule definition and will ensure that the test script has supplied them before evaluating the rule. We’re also using the parameter in the summary and description as ‘${param.header}’ so the summary and description on the TestScript Execution screen is based on the parameter supplied.

Replace the contents of AssertHeader.groovy with the code above, and re-upload and re-execute.

../../_images/upload-param-1.png

You should get the following error:

../../_images/missing-param-1_a1.png

That’s because we haven’t supplied the ‘header’ parameter from the test script yet. We’ll do that next.

Supplying params

According to the specification, we could supply the parameter in two ways in the test script:

  1. At the top of the test script within the rule declaration:

    ../../_images/param-declare-1b.png
  2. Within the rule-assertion in a test:

    ../../_images/param-declare-2b.png

You can use option 1 or 2 or both. Option 2 is useful when you need the parameter values in rule-assertion to override the ones supplied within the rule declaration. Let’s use the first option i.e. declare it within the rule declaration:

<extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-rule">
    <extension url="ruleId">
        <valueId value="assertETag"/>
    </extension>
    <extension url="path">
        <valueString value="../_reference/rule/AssertHeader.groovy"/>
    </extension>
    <extension url="param">
        <extension url="name">
            <valueString value="header"/>
        </extension>
        <extension url="value">
            <valueString value="ETag"/>
        </extension>
    </extension>
</extension>

Upload the test script and re-execute it. You should get the following result:

../../_images/param-ETag-results.png

We can now easily add the rule assertion for ‘Last-Modified’ header without modifying AssertHeader.groovy rule definition.

Add the following rule declaration to the test script after assertETag:

<extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-rule">
    <extension url="ruleId">
        <valueId value="assertLastModified"/>
    </extension>
    <extension url="path">
        <valueString value="../_reference/rule/AssertHeader.groovy"/>
    </extension>
    <extension url="param">
        <extension url="name">
            <valueString value="header"/>
        </extension>
        <extension url="value">
            <valueString value="Last-Modified"/>
        </extension>
    </extension>
</extension>

Add the following rule-asseriton to the test script after all the assertions:

<assert>
    <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-rule">
        <extension url="ruleId">
            <valueId value="assertLastModified"/>
        </extension>
    </extension>
    <warningOnly value="false" />
</assert>

Re-upload and re-execute. You should get the results below. Notice how the summaries and descriptions are customized for each parameter.


../../_images/customized_summ_descriptions.png

That’s because we used parameters in the summary and description:


../../_images/customized_summ_descriptions_params.png

Operator parameter

You can make the AssertHeader rule even more generic by passing the operator that the header value needs to be evaluated with.

Replace the contents of AssertHeader.groovy with the following:

/*
   rule.summary=${label.target} '${param.header}' header ${param.headerOperator}.
   rule.description=Confirm that '${param.header}' header ${param.headerOperator}.
   rule.param.header.required=true
   rule.param.headerExpectedValue.required=false
   rule.param.headerOperator.required=true
*/

targetMessage.assertHeader(param.header, param.headerExpectedValue, param.headerOperator);

See Bindings for explanation on what targetMessage means.

Re-upload and re-execute. You should get the following error:

../../_images/missing-param-operator_a1.png

Notice that there are two new parameters that can be supplied from the test script. One is required and the other optional:

../../_images/param_headerOperator.png

Replace the rule references in Patient-server-id-json.xml test script with the changes below. Notice the addition of headerOperator parameter to both rule declarations:

<extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-rule">
    <extension url="ruleId">
        <valueId value="assertETag"/>
    </extension>
    <extension url="path">
        <valueString value="../_reference/rule/AssertHeader.groovy"/>
    </extension>
    <extension url="param">
        <extension url="name">
            <valueString value="header"/>
        </extension>
        <extension url="value">
            <valueString value="ETag"/>
        </extension>
    </extension>
    <extension url="param">
        <extension url="name">
            <valueString value="headerOperator"/>
        </extension>
        <extension url="value">
            <valueString value="notEmpty"/>
        </extension>
    </extension>
</extension>
<extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-rule">
    <extension url="ruleId">
        <valueId value="assertLastModified"/>
    </extension>
    <extension url="path">
        <valueString value="../_reference/rule/AssertHeader.groovy"/>
    </extension>
    <extension url="param">
        <extension url="name">
            <valueString value="header"/>
        </extension>
        <extension url="value">
            <valueString value="Last-Modified"/>
        </extension>
    </extension>
    <extension url="param">
        <extension url="name">
            <valueString value="headerOperator"/>
        </extension>
        <extension url="value">
            <valueString value="notEmpty"/>
        </extension>
    </extension>
</extension>

Re-upload and re-execute. You should see the results below:

../../_images/etag-and-lastModified-passes.png

You can refer to Header Rule API for details on header assertions.

Expected parameter

Let’s replace the existing assertion for response code in Patient-server-id-json.xml test script with an assertion rule. This is not recommended practice as it’s best to resort to rule-assertions when existing TestScript asserts do not meet your needs. We’re doing this for demonstration purposes.

Create a new rule definition called AssertResponseCode.groovy and copy the following contents into it:

/*
   rule.summary=Response status code ${param.responseCodeOperator} ${param.responseCode}.
   rule.description=Confirm that response status code ${param.responseCodeOperator} ${param.responseCode}.
   rule.param.responseCode.required=true
   rule.param.responseCodeOperator.required=true
*/

targetMessage.assertResponseCode(param.responseCode, param.responseCodeOperator)

The responseCode and responseCodeOperator parameters above are required and have to be supplied by the test script. The responseCode is the expected value in the response.

Add the following rule declaration before the assertETag rule declaration:

<extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-rule">
    <extension url="ruleId">
        <valueId value="assertResponseCode"/>
    </extension>
    <extension url="path">
        <valueString value="../_reference/rule/AssertResponseCode.groovy"/>
    </extension>
</extension>

Replace the existing rule assert for response code with the following:

<assert>
    <extension url="http://touchstone.aegis.net/touchstone/fhir/testing/StructureDefinition/testscript-assert-rule">
        <extension url="ruleId">
            <valueId value="assertResponseCode"/>
        </extension>
        <extension url="param">
            <extension url="name">
                <valueString value="responseCode"/>
            </extension>
            <extension url="value">
                <valueString value="200,201"/>
            </extension>
        </extension>
        <extension url="param">
            <extension url="name">
                <valueString value="responseCodeOperator"/>
            </extension>
            <extension url="value">
                <valueString value="in"/>
            </extension>
        </extension>
    </extension>
    <warningOnly value="false" />
</assert>

Notice that this time, we’re supplying the parameters with the rule assert instead of the rule declaration.

Re-upload and re-execute. You should see the following results:


../../_images/statusCode-etag-and-lastModified-passes.png

You can refer to Response Code Rule API for details on response code assertions.