nooks and crannies: lessons from fhir server testing · 2020. 8. 30. · 4 fhir server...
TRANSCRIPT
![Page 1: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/1.jpg)
HL7®, FHIR® and the flame Design mark are the registered trademarks of Health Level Seven International and are used with permission.
HL7 FHIR DevDays 2020, Virtual Edition US, June 15–18, 2020 | @HL7 @FirelyTeam | #fhirdevdays | www.devdays.com/us
Nooks and Crannies: Lessons from FHIR Server Testing
Lee Surprenant, IBM
![Page 2: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/2.jpg)
1
Traditional testing pyramid
source:https://james-willett.com/2016/09/the-evolution-of-the-testing-pyramid/
![Page 3: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/3.jpg)
2
Our focus today(but applicable to all levels)
Community Test Tools• AEGIS Touchstone• Inferno
![Page 4: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/4.jpg)
3
FHIR Server components
serialization/deserialization of resources (JSON and XML)
schema (primary), constraints (secondary), and terminology
storing and retrieving resources
1. extraction / indexing2. search query
FHIR Model
Validation
Search
Persistence
interceptors, extended operations, etc.Logic
![Page 5: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/5.jpg)
4
FHIR Server example-driven component tests
FHIR Model
Validation
Search
Persistence
Logic
Round-trip resources from files to objects and back
Positive and negative example validation (core spec and profiles / implementation guides)
Simulate extraction of search parameters and search on each parameter defined in the base spec
Round-trip each resource to the database
Test against all variations of resources; look for NullPointerException and similar logic errors
![Page 6: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/6.jpg)
5
Sources for test data
• Core specification• Synthea• Implementation-guide specific /
Connectathon resources• http://hl7.org/fhir/us/carin-
bb/2020Feb/Examples.html• https://github.com/HL7-
DaVinci/pdex-plan-net-sample-data• …
• IBM-generated examples
![Page 7: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/7.jpg)
6
com.ibm.fhir:fhir-examples
• Java module that packages many examples in a single jar• 2 Classes on top:• com.ibm.fhir.examples.ExamplesUtil• com.ibm.fhir.examples.Index
![Page 8: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/8.jpg)
7
IBM-generated examples
Three flavors:1. minimal2. complete-mock3. complete-absent
Also “basic-search”examples (time permitting)
![Page 9: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/9.jpg)
8
Hypothetical…private static void printActivePatientSurnames(List<Patient> patients) {
for (Patient patient : patients) {
if (patient.getActive().getValue()) {
for (HumanName name : patient.getName()) {
if (name.getFamily() != null) {
System.out.println(name.getFamily().getValue());
}
}
}
}
}
![Page 10: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/10.jpg)
9
Minimal (Patient){
"resourceType": "Patient",
"meta": {
"tag": [
{
"code": "ibm/minimal"
}
]
}
}
json/ibm/minimal/Patient-1.json
![Page 11: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/11.jpg)
10
Minimal (Patient){
"resourceType": "Patient",
"meta": {
"tag": [
{
"code": "ibm/minimal"
}
]
}
}
json/ibm/minimal/Patient-1.json
private static void printActivePatientSurnames(List<Patient> patients) {
for (Patient patient : patients) {
if (patient.getActive().getValue()) {
for (HumanName name : patient.getName()) {
if (name.getFamily() != null) {
System.out.println(name.getFamily().getValue());
}
}
}
}
}
![Page 12: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/12.jpg)
11
NullPointerException
![Page 13: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/13.jpg)
12
Null checkingprivate static void printActivePatientSurnames(List<Patient> patients) {
for (Patient patient : patients) {
if (patient.getActive().getValue()) {
for (HumanName name : patient.getName()) {
if (name.getFamily() != null) {
System.out.println(name.getFamily().getValue());
}
}
}
}
}
![Page 14: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/14.jpg)
13
Null checkingprivate static void printActivePatientSurnames(List<Patient> patients) {
for (Patient patient : patients) {
if (patient.getActive() != null && patient.getActive().getValue()) {
for (HumanName name : patient.getName()) {
if (name.getFamily() != null) {
System.out.println(name.getFamily().getValue());
}
}
}
}
}
![Page 15: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/15.jpg)
14
Minimal (Observation){
"resourceType": "Observation",
"meta": …
"_status": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
},
"code": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
} json/ibm/minimal/Observation-1.json
![Page 16: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/16.jpg)
15
Complete-mock{
"resourceType": "Patient",
"meta": …
"identifier": [
{
"use": "official",
"type": {
"coding": [
{
"system": "z6qLT3jgB9",
"version": "aZWQtezZjY",
"code": "7J8uWBfh5a",
"display": "TFEvRt3UO0",
"userSelected": true
… json/ibm/complete-mock/Patient-1.json
![Page 17: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/17.jpg)
16
Complete-mock{
"resourceType": "Patient",
"meta": …
"identifier": [
{
"use": "official",
"type": {
"coding": [
{
"system": "z6qLT3jgB9",
"version": "aZWQtezZjY",
"code": "7J8uWBfh5a",
"display": "TFEvRt3UO0",
"userSelected": true
…
![Page 18: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/18.jpg)
17
Complete-mock codes and choice types{
"resourceType": "Patient",
"meta": …
"identifier": …
"active": true,
"gender": "other",
"deceasedBoolean": true,
…
{
"resourceType": "Patient",
"meta": …
"identifier": …
"active": true,
"gender": "unknown",
"deceasedDateTime": "2020-03-12T00:11:56.829-04:00",
…
json/ibm/complete-mock/Patient-1.json json/ibm/complete-mock/Patient-2.json
![Page 19: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/19.jpg)
18
Complete-absent{
"resourceType": "Patient",
"meta": …
"identifier": [{
"_use": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
}, …
"_active": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
},json/ibm/complete-absent/Patient-1.json
![Page 20: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/20.jpg)
19
Complete-absent{
"resourceType": "Patient",
"meta": …
"identifier": [{
"_use": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
}, …
"_active": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
},json/ibm/complete-absent/Patient-1.json
private static void printActivePatientSurnames(List<Patient> patients) {
for (Patient patient : patients) {
if (patient.getActive() != null && patient.getActive().getValue()) {
for (HumanName name : patient.getName()) {
if (name.getFamily() != null) {
System.out.println(name.getFamily().getValue());
}
}
}
}
}
![Page 21: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/21.jpg)
20
NullPointerException
![Page 22: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/22.jpg)
21
Primitive extensions (XML)<Patient xmlns="http://hl7.org/fhir">
<meta> …
<name>
<family>
<extensionurl="http://hl7.org/fhir/StructureDefinition/data-absent-reason">
<valueCode value="unknown"/>
</extension>
</family>
<given>
<extensionurl="http://hl7.org/fhir/StructureDefinition/data-absent-reason">
<valueCode value="unknown"/>
</extension>
</given>
…
<Patient xmlns="http://hl7.org/fhir">
<meta> …
<name>
<family value="Donald"/>
<given value="Duck"/>
<given value="D"/>
</name>
…
![Page 23: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/23.jpg)
22
Primitive extensions (JSON){
"resourceType": "Patient",
"meta": …
"name": [{
"_family": {
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
},
"given": [null],
"_given": [{
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}]
{
"resourceType": "Patient",
"meta": …
"name": [{
"family": "Donald",
"given": [
"Duck",
"D"
]
}],
…
![Page 24: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/24.jpg)
23
Null checkingprivate static void printActivePatientSurnames(List<Patient> patients) {
for (Patient patient : patients) {
if (patient.getActive() != null && patient.getActive().getValue()) {
for (HumanName name : patient.getName()) {
if (name.getFamily() != null) {
System.out.println(name.getFamily().getValue());
}
}
}
}
}
![Page 25: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/25.jpg)
24
Null checkingprivate static void printActivePatientSurnames(List<Patient> patients) {
for (Patient patient : patients) {
if (patient.getActive() != null && Boolean.TRUE.equals(patient.getActive().getValue())) {
for (HumanName name : patient.getName()) {
if (name.getFamily() != null) {
System.out.println(name.getFamily().getValue());
}
}
}
}
}
![Page 27: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/27.jpg)
26
Questions?
![Page 28: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/28.jpg)
27
Bonus: IBM fhir-persistence search tests
• Organized by search parameter type• Covers all allowed type mappings defined at
https://www.hl7.org/fhir/search.html#table• Basic resources with extensions (1 or more per data type)• Custom SearchParameter definitions (>1 for complex types)
![Page 29: Nooks and Crannies: Lessons from FHIR Server Testing · 2020. 8. 30. · 4 FHIR Server example-driven component tests FHIR Model Validation Search Persistence Logic Round-trip resources](https://reader035.vdocuments.mx/reader035/viewer/2022063021/5fe5e38dcbaa5d29932c8ddd/html5/thumbnails/29.jpg)
28