nooks and crannies: lessons from fhir server testing · 2020. 8. 30. · 4 fhir server...

29
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

Upload: others

Post on 04-Sep-2020

2 views

Category:

Documents


0 download

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 26: 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

25

Try it!

feedback welcome at #ibm on https://chat.fhir.org

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

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

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

28