Skip to content

TestScript Overview

TestScript is a FHIR resource that defines a set of tests to execute against a FHIR server. FHIR Frog provides complete TestScript execution support.

Use TestScript Shorthand (TSH)

While TestScripts can be written in JSON or XML, we recommend using TSH (TestScript Shorthand) for a much more concise and readable syntax. TSH is designed to eventually merge into FSH.

What is a TestScript?

A TestScript defines:

  • Fixtures - Test data to use
  • Variables - Values extracted from responses
  • Setup - Operations to run before tests
  • Tests - The actual test cases
  • Teardown - Cleanup operations

Basic Structure

TestScript: ExampleTest
Status: #draft

Fixture: patient from "sample-patient.json"

Setup:
  * operation create Patient from patient

Test: "Verify patient created"
  * operation read Patient/${patientId}
  * assert responseCode = 200

Teardown:
  * operation delete Patient/${patientId}
{
  "resourceType": "TestScript",
  "id": "example",
  "name": "ExampleTest",
  "status": "draft",
  "fixture": [],
  "variable": [],
  "setup": {},
  "test": [],
  "teardown": {}
}

Execution Flow

Diagram

Simple Example

TestScript: PatientCreate
Title: "Test creating a patient"
Status: #draft

Fixture: patient from "sample-patient.json"

Test: "Create patient"
  * operation create Patient from patient as createResponse
  * assert responseCode = 201
  * assert resource = Patient
{
  "resourceType": "TestScript",
  "id": "patient-create",
  "name": "PatientCreate",
  "status": "draft",
  "description": "Test creating a patient",
  "fixture": [{
    "id": "patient",
    "resource": {
      "reference": "sample-patient"
    }
  }],
  "test": [{
    "name": "Create patient",
    "action": [
      {
        "operation": {
          "type": {"code": "create"},
          "resource": "Patient",
          "sourceId": "patient",
          "responseId": "create-response"
        }
      },
      {
        "assert": {
          "response": "created",
          "sourceId": "create-response"
        }
      }
    ]
  }]
}

Key Concepts

Operations

Operations perform FHIR interactions:

  • create - POST a resource
  • read - GET a resource by ID
  • update - PUT a resource
  • delete - DELETE a resource
  • search - Search for resources
  • transaction - Execute a transaction bundle

See Operations for details.

Assertions

Assertions validate responses:

  • response - Check HTTP status code
  • responseCode - Specific status code
  • resource - Validate resource type
  • expression - FHIRPath expression
  • validateProfileId - Profile validation

See Assertions for details.

Variables

Variables extract and reuse values:

{
  "variable": [{
    "name": "patientId",
    "expression": "Patient.id",
    "sourceId": "create-response"
  }]
}

Use with ${variableName} syntax:

{
  "operation": {
    "type": {"code": "read"},
    "resource": "Patient",
    "params": "${patientId}"
  }
}

See Variables for details.

Fixtures

Fixtures provide test data:

{
  "fixture": [{
    "id": "patient",
    "autocreate": false,
    "autodelete": false,
    "resource": {
      "reference": "sample-patient"
    }
  }]
}

Reference points to a file in src/test/resources/fhir/ (without .json extension).

See Fixtures for details.

Complete CRUD Example

{
  "resourceType": "TestScript",
  "id": "patient-crud",
  "name": "PatientCRUD",
  "status": "draft",
  "fixture": [{
    "id": "patient",
    "resource": {"reference": "sample-patient"}
  }],
  "variable": [{
    "name": "patientId",
    "expression": "Patient.id",
    "sourceId": "create-response"
  }],
  "setup": {
    "action": [
      {
        "operation": {
          "type": {"code": "create"},
          "resource": "Patient",
          "sourceId": "patient",
          "responseId": "create-response"
        }
      },
      {
        "assert": {
          "response": "created",
          "sourceId": "create-response"
        }
      }
    ]
  },
  "test": [
    {
      "name": "Read patient",
      "action": [
        {
          "operation": {
            "type": {"code": "read"},
            "resource": "Patient",
            "params": "${patientId}",
            "responseId": "read-response"
          }
        },
        {
          "assert": {
            "response": "okay",
            "sourceId": "read-response"
          }
        },
        {
          "assert": {
            "resource": "Patient",
            "sourceId": "read-response"
          }
        }
      ]
    },
    {
      "name": "Update patient",
      "action": [
        {
          "operation": {
            "type": {"code": "update"},
            "resource": "Patient",
            "sourceId": "patient",
            "responseId": "update-response"
          }
        },
        {
          "assert": {
            "response": "okay",
            "sourceId": "update-response"
          }
        }
      ]
    },
    {
      "name": "Search patient",
      "action": [
        {
          "operation": {
            "type": {"code": "search"},
            "resource": "Patient",
            "params": "?family=Smith",
            "responseId": "search-response"
          }
        },
        {
          "assert": {
            "response": "okay",
            "sourceId": "search-response"
          }
        },
        {
          "assert": {
            "resource": "Bundle",
            "sourceId": "search-response"
          }
        }
      ]
    }
  ],
  "teardown": {
    "action": [{
      "operation": {
        "type": {"code": "delete"},
        "resource": "Patient",
        "params": "${patientId}"
      }
    }]
  }
}

Best Practices

1. Use Descriptive IDs

"responseId": "create-response"  // Good
"responseId": "response1"        // Bad

2. One Assertion Per Action

"action": [
  {"operation": {...}},
  {"assert": {"response": "okay"}},
  {"assert": {"resource": "Patient"}}
]

3. Always Clean Up

"teardown": {
  "action": [{
    "operation": {
      "type": {"code": "delete"},
      "params": "${patientId}"
    }
  }]
}

4. Extract Variables Early

"setup": {
  "action": [
    {"operation": {..., "responseId": "create-response"}},
    // Variable extracted automatically after operation
  ]
}
{
  "operation": {
    "type": {"code": "transaction"},
    "sourceId": "bundle-with-patient-and-observation"
  }
}

Running TestScripts

JUnit

@TestTemplate
@TestScriptSource("fhir/patient-crud.json")
void testPatientCrud() {
}

CLI

fhir-frog patient-crud.json --server http://localhost:8080/fhir

Maven

<execution>
  <goals><goal>test</goal></goals>
  <configuration>
    <testScript>patient-crud.json</testScript>
  </configuration>
</execution>

Next Steps