TestScript Assertions¶
Assertions validate operation results. FHIR Frog supports all standard FHIR assertions with FHIRPath expressions.
Response Code Assertions¶
Basic Response Code¶
{
"assert": {
"description": "Confirm successful creation",
"response": "created",
"warningOnly": false
}
}
Specific Status Code¶
Resource Type Assertions¶
FHIRPath Assertions¶
Simple Expression¶
Value Comparison¶
{
"assert": {
"description": "Patient family name is Smith",
"expression": "Patient.name.family = 'Smith'"
}
}
Complex Expression¶
{
"assert": {
"description": "Patient has Medicare number",
"expression": "Patient.identifier.where(system='http://ns.electronichealth.net.au/id/medicare-number').exists()"
}
}
Header Assertions¶
{
"assert": {
"description": "Content-Type is FHIR JSON",
"headerField": "Content-Type",
"value": "application/fhir+json"
}
}
Minimum/Maximum ID¶
Assert resource ID format:
Navigation Assertions¶
Assert on specific response:
{
"assert": {
"description": "Search returned results",
"expression": "Bundle.entry.count() > 0",
"sourceId": "searchResponse"
}
}
Operator Assertions¶
Equals¶
Not Equals¶
Contains¶
In/Not In¶
Warning-Only Assertions¶
Non-failing assertions for informational purposes:
{
"assert": {
"description": "Preferred: Patient should have email",
"expression": "Patient.telecom.where(system='email').exists()",
"warningOnly": true
}
}
Bundle Assertions¶
Search Results¶
{
"assert": {
"description": "Search found exactly one patient",
"expression": "Bundle.entry.count() = 1",
"sourceId": "searchResponse"
}
}
Transaction Results¶
{
"assert": {
"description": "All transaction entries succeeded",
"expression": "Bundle.entry.all(response.status.startsWith('20'))",
"sourceId": "transactionResponse"
}
}
Validation Assertions¶
Profile Conformance¶
{
"assert": {
"description": "Patient conforms to AU Core",
"validateProfileId": "http://hl7.org.au/fhir/core/StructureDefinition/au-core-patient"
}
}
Assertion Patterns¶
Existence Check¶
{
"assert": {
"expression": "Patient.identifier.exists()",
"description": "Patient must have at least one identifier"
}
}
Count Check¶
{
"assert": {
"expression": "Patient.name.count() >= 1",
"description": "Patient must have at least one name"
}
}
Value Set Check¶
{
"assert": {
"expression": "Patient.gender in ('male' | 'female' | 'other' | 'unknown')",
"description": "Gender must be valid code"
}
}
Reference Check¶
{
"assert": {
"expression": "Observation.subject.reference.startsWith('Patient/')",
"description": "Observation must reference a Patient"
}
}
Best Practices¶
- Always include descriptions - Makes failures easier to understand
- Use FHIRPath for complex logic - More powerful than simple operators
- Test positive and negative cases - Don't just test success paths
- Use warningOnly sparingly - Only for truly optional validations
- Assert on sourceId - When checking specific responses in multi-operation tests
Common Patterns¶
CRUD Assertions¶
// Create
{"assert": {"responseCode": "201"}}
{"assert": {"expression": "Patient.id.exists()"}}
// Read
{"assert": {"responseCode": "200"}}
{"assert": {"resource": "Patient"}}
// Update
{"assert": {"responseCode": "200"}}
// Delete
{"assert": {"responseCode": "204"}}
Update can also be 201
FHIR Frog reports whatever HTTP status the server actually returned for an update
operation — usually 200, but 201 is equally valid FHIR ("create via update": a PUT
to a resource ID that doesn't exist yet). If your TestScript targets an ID that may not
already exist, assert response = "created" (or responseCode = "201") instead of
assuming 200.
Search Assertions¶
{"assert": {"responseCode": "200"}}
{"assert": {"resource": "Bundle"}}
{"assert": {"expression": "Bundle.type = 'searchset'"}}
{"assert": {"expression": "Bundle.entry.count() > 0"}}
Next Steps¶
- Variables - Extract values for reuse
- Operations - Available operations