Skip to content

6. Importing Tests

Elsa Perelli edited this page Oct 23, 2024 · 6 revisions

Goal

Some Implementation Guides refer to other Implementation Guides in order to reuse guidance or rules. In these cases, it is useful to be able to import tests from associated Test Kits to provide a single integrated testing experience. This is how the Inferno-based (g)(10) Standardized API Test Kit is constructed -- it imports multi-purpose tests including the SMART App Launch Test Kit and the US Core Test Kit.

In this step, we will add an optional SMART App Launch test to this test suite, which will automatically provide other tests with an OAuth bearer token, as well as a patient_id if provided in context.

For those using the Inferno Reference Server, note that you may use the SAMPLE_PUBLIC_CLIENT_ID client id with no secret as registration information to provide into the tests.

Resources

Solution

In the .env file add the host of your environment (if launching from GitHub Codespaces or any non-localhost environment, you can just copy the host that the Inferno interface is served from). This allows Inferno's SMART App Launch tests to generate correct redirect URIs:

INFERNO_HOST=http://localhost

Update the inferno_template.gemspec to include the smart_app_launch_test_kit gem:

spec.add_runtime_dependency 'smart_app_launch_test_kit', '~> 0.4.3'

And update the tests to import the library, and include a new optional Auth section with groups described in the SMART App Launch documentation. Grouping all existing tests under an API section will help keep things clean:

require_relative 'inferno_template/patient_group'
require 'smart_app_launch_test_kit'

module InfernoTemplate
  class Suite < Inferno::TestSuite
    id :inferno_template_test_suite
    title 'Inferno Template Test Suite'
    description 'Inferno template test suite.'

    # These inputs will be available to all tests in this suite
    input :url,
          title: 'FHIR Server Base Url'

    input :credentials,
          title: 'OAuth Credentials',
          type: :oauth_credentials,
          optional: true

    # All FHIR validation requsets will use this FHIR validator
    fhir_resource_validator do
      igs 'hl7.fhir.us.core#3.1.1' # Use this method for published IGs/versions
      # igs 'igs/filename.tgz'   # Use this otherwise

      exclude_message do |message|
        message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
      end
    end

    group do
      id :auth
      title 'Auth'
      optional
      run_as_group

      output :access_token, :patient_id

      group from: :smart_discovery
      group from: :smart_standalone_launch
    end

    group do
      id :api
      title 'API'
      input :access_token

      # All FHIR requests in this suite will use this FHIR client
      fhir_client do
        url :url
        bearer_token :access_token
      end

      # Tests and TestGroups can be defined inline
      group do
        id :capability_statement
        title 'Capability Statement'
        description 'Verify that the server has a CapabilityStatement'

        test do
          id :capability_statement_read
          title 'Read CapabilityStatement'
          description 'Read CapabilityStatement from /metadata endpoint'

          run do
            fhir_get_capability_statement

            assert_response_status(200)
            assert_resource_type(:capability_statement)
          end
        end
      end

      # Tests and TestGroups can be written in separate files and then included
      # using their id
      group from: :patient_group

      group do
        id :search_tests
        title 'Search Tests'

        input :patient_id

        ['AllergyIntolerance',
        'CarePlan',
        'CareTeam',
        'Condition',
        'Device',
        'DiagnosticReport',
        'DocumentReference',
        'Encounter',
        'Goal',
        'Immunization',
        'MedicationRequest',
        'Observation',
        'Procedure'].each do |tested_resource|

          test do
            title "#{tested_resource} Search by Patient"

            run do
              fhir_search(tested_resource, params: { patient: patient_id })

              assert_response_status(200)
              assert_resource_type('Bundle')

              # skip_if is a shortcut to wrapping `skip` statement in an `if` block
              # it is a good idea to use the safe navigation operator `&.` to avoid runtime errors on nil
              skip_if resource.entry&.empty?, 'No entries in bundle response.'

              info "Bundle contains #{resource.entry&.count} resources."

              # There are not profiles for Observation, DocumentReference, or Device
              # in US Core v3.1.1
              pass_if ['Observation', 'DiagnosticReport', 'Device'].include?(tested_resource),
                "Note: no US Core Profile for #{tested_resource} resource type"

              assert_valid_bundle_entries(
                resource_types: {
                  "#{tested_resource}": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-#{tested_resource.downcase}"
                }
              )
            end
          end
        end
      end
    end
  end
end

link to the diff between step-6 and step-6-solution branches: https://github.com/inferno-training/inferno-tutorial/compare/step-6...step-6-solution

Note: When running this branch with the Inferno Reference Server and Patient 85, Test 2.02 will fail. This is an expected failure since Patient 85 in the reference server no longer conforms to USCore 3.1.1. Additionally, tests 3.01, 3.05, and 3.09 should be skipped.