Thursday, January 23, 2014

Behavior Driven FHIR Starting

Last weekend, my colleague Scott Bolte attended the FHIR Connectathon with intent, but like me at prior events, he really hadn't the time to prepare.  It's the nature of our work, sometimes, the best thing we are able to show up with is our brains.

Even so, he managed to be successful, as you can hear from his story below.

Two weeks ago, Keith extolled the benefits of user stories to capture interoperability needs.  This week, at the FHIR Connectathon, I demonstrated that user stories can also serve as executable tests to guide development and verify server/client interactions.  Building on that, I showed the potential of sharing user stories across implementations to improve interoperability.

User stories have long served as the source for system requirements.  Unfortunately, stories are typically translated into detailed requirements with corresponding unit tests.  Not surprisingly, important information is often lost in translation.  To make matters worse, repeating the translation for other implementations increases the odds that interoperability peers will fail to communicate.

An Agile Development practice called Behavior-Driven Development (BDD) fundamentally changes the approach. User stories are structured as a series of Given, When, and Then statements.  The statements, written in simple prose, serve as both a narrative and as test drivers.  The narrative remains accessible to all stakeholders, essential for everyone from the domain expert to the implementer.  At the same time, once glue code is written to map each statement to a small code fragment, the story is a complete test.

One benefit of BDD is that as statements are tied to glue code, they can be assembled into new, unique stories.  Different pre-conditions, the Given statements, can be combined in novel ways to set up a new starting point.  Different triggers for interaction, the When statements, can be used.  Finally, the expected results, expressed as Then statements, allow simple or complex outcomes to be assessed.

I arrived at the FHIR Connectathon pretty much a novice.  I had reviewed the FamilyHistory resource earlier, but had not delved into RESTful APIs or any of the available toolkits. I started by writing some bare bone scenarios to confirm connectivity with a FHIR server; scenarios that evolved in lockstep with the Perl client I was writing.

Here is an early example:

Scenario: Fragile, low-level FHIR server query
   When making a "metadata" query
   Then the status should be "200 OK"

One hazard of the example above is it is tied to the implementation.  Appending /metadata to the provided URL is just one way to check for availability.  The literal use of one particular HTTP status code (200 OK) precludes other success codes from being accepted.  However, the worse aspect of that scenario is it is cryptic to anyone but a developer.

Scenario: demonstrate use of symbolic terms to capture stories.
  Given "Grahame's" FHIR server
   When confirming the server is available
   Then the query should succeed

The second scenario is a big improvement.  Referring to Grahame Grieve's test server by name allows for the underling URL to change.  Asking for server availability, instead of a specific URL, allows the client implementation to use alternate techniques such as an OPTIONS request instead of GET.  Finally, simply asking broadly that success be checked allows for different status codes.  In the end, it concisely captures a behavior in a way that anyone can understand.

Before the end of the day, even starting from scratch, my BDD scenarios progressed so I could query resources, create simple reports, and request different data formats.  The example below illustrates table driven capabilities though the use of <SERVER> and <FORMAT> markers.  Furthermore, a multi-line report - the list of medications found on Grahame's server, is verified for both XML and JSON data.

Scenario: bare Patient query of server
  Given "<SERVER>" FHIR server
    And a format of "<FORMAT>"
   When searching for "Medication" resources
   Then the query should succeed
    And the search summary should be
"""
Search results for resource type Medication
     1. Combivent
     2. Crestor
     3. Enalapril
     4. Flucloxacillin
     5. Metoprolol
     6. Paracetamol
     7. Penicillin VK oral suspension 125mg/5ml
     8. Salmeterol/fluticason
     9. Tolbutamide
"""
  Examples:
    | SERVER   | FORMAT |                                               
    | Graham's | xml    |                                               
    | Graham's | json   |                                               

It is a testament to alignment of FHIR to mature web technology that I was able to create such tests from scratch in a few hours.  However, what I find most encouraging is that the final scenarios are completely independent of the underlying implementation.  Users of Java, C#, or any other FHIR client API can write their own glue code. Once they do, they can use the exact same BDD scenarios.  That is not a big deal for the simple scenarios above, but as more complex behavior is described, the reuse benefits will become significant.

1 comment: