Skip to content
This repository was archived by the owner on Jan 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #468 from onc-healthit/FI-886
Browse files Browse the repository at this point in the history
Fi 886 - Basic read/validate test generator
  • Loading branch information
radamson authored Jul 24, 2020
2 parents 3289c38 + 440f69d commit ff81cb2
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 0 deletions.
2 changes: 2 additions & 0 deletions generator/generator_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def load_resources
# There were problems with round-tripping certain SearchParameters though
new_resource_json = JSON.parse(File.read(resource))
new_resource = FHIR.from_contents(File.read(resource))
next unless new_resource.present?

resource_by_path[resource_path(new_resource)] = new_resource_json
type = new_resource.class.name.demodulize
type = 'CapabilityStatement' if type == 'Conformance'
Expand Down
63 changes: 63 additions & 0 deletions generator/generic/generic_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# frozen_string_literal: true

require_relative '../generator_base'
require_relative '../sequence_metadata'
require_relative './read_test'
require_relative './profile_validation_test'

module Inferno
module Generator
class GenericGenerator < Generator::Base
include ReadTest
include ProfileValidationTest

def resource_profiles
resources_by_type['StructureDefinition'].reject { |definition| definition['type'] == 'Extension' }
end

def sequence_metadata
@sequence_metadata ||= resource_profiles.map { |profile| SequenceMetadata.new(profile) }
end

def generate
generate_sequences
generate_module
end

def generate_sequences
sequence_metadata.each do |metadata|
create_read_test(metadata)
create_profile_validation_test(metadata)
generate_sequence(metadata)
end
end

def generate_sequence(metadata)
puts "Generating #{metadata.title}\n"
file_name = File.join(sequence_out_path, metadata.file_name + '.rb')
template = ERB.new(File.read(File.join(__dir__, 'templates/sequence.rb.erb')))
output = template.result_with_hash(metadata: metadata)
FileUtils.mkdir_p(sequence_out_path + '/') unless File.directory?(sequence_out_path + '/')
File.write(file_name, output)
end

def module_file_path
"#{module_yml_out_path}/#{@path}_module.yml"
end

def generate_module
file_name = module_file_path

module_info = {
title: @path,
sequences: sequence_metadata,
description: ''
}
template = ERB.new(File.read(File.join(__dir__, 'templates/module.yml.erb')))
output = template.result_with_hash(module_info)

File.write(file_name, output)
end
end
end
end
22 changes: 22 additions & 0 deletions generator/generic/profile_validation_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require_relative '../test_metadata'

module Inferno
module Generator
module ProfileValidationTest
def create_profile_validation_test(metadata)
profile_validation_test = TestMetadata.new(
title: "Server returns #{metadata.resource_type} resource that matches the #{metadata.title} profile",
key: :resource_validate_profile,
description: "This test will validate that the #{metadata.resource_type} resource returned from the server matches the #{metadata.title} profile."
)
profile_validation_test.code = %(
skip 'No resource found from Read test' unless @resource_found.present?
test_resource_against_profile('#{metadata.resource_type}', @resource_found, '#{metadata.url}')
)
metadata.add_test(profile_validation_test)
end
end
end
end
22 changes: 22 additions & 0 deletions generator/generic/read_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require_relative '../test_metadata'

module Inferno
module Generator
module ReadTest
def create_read_test(metadata)
read_test = TestMetadata.new(
title: "Server returns correct #{metadata.resource_type} resource from the #{metadata.resource_type} read interaction",
key: :resource_read,
description: "This test will verify that #{metadata.resource_type} resources can be read from the server."
)
read_test.code = %(
resource_id = @instance.#{metadata.resource_type.underscore}_id
@resource_found = validate_read_reply(FHIR::#{metadata.resource_type}.new(id: resource_id), FHIR::#{metadata.resource_type})
)
metadata.add_test(read_test)
end
end
end
end
13 changes: 13 additions & 0 deletions generator/generic/templates/module.yml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: <%= title.underscore %>
title: <%= title %>
description : <%= description %>
fhir_version: r4
default_test_set: ad_hoc_testing
test_sets:
ad_hoc_testing:
view: default
tests:
- name: <%= title %> Profiles
run_all: true
sequences:<% sequences.each do |sequence| %>
- <%= sequence.class_name %><% end %>
35 changes: 35 additions & 0 deletions generator/generic/templates/sequence.rb.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Inferno
module Sequence
class <%= metadata.class_name %> < SequenceBase
title '<%= metadata.title %> Tests'
description 'Verify support for the server capabilities required by the <%= metadata.title %> profile.'
details %(
)
test_id_prefix '<%= metadata.test_id_prefix %>'
requires <%= metadata.requirements.join(', ') %>

@resource_found = nil

<% metadata.tests.each_with_index do |test, idx|%>
<% if test.key.present? %>
test :<%= test.key %> do
<% else %>
test '<%= test.title %>' do
<% end %>
metadata do
id '<%= format('%02d', idx + 1) %>'<% if test.key.present? %>
name '<%= test.title %>'<% end %>
link '<%= metadata.url %>'<% if test.optional %>
optional<% end %>
description %(
<%= test.description %>
)
versions :r4
end
<%= test.code %>
end<% end %>
end
end
end
67 changes: 67 additions & 0 deletions generator/sequence_metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# frozen_string_literal: true

module Inferno
module Generator
class SequenceMetadata
attr_reader :profile,
:tests
attr_writer :class_name,
:file_name,
:requirements,
:sequence_name,
:test_id_prefix,
:title,
:url

def initialize(profile)
@profile = profile
@tests = []
end

def resource_type
profile['type']
end

def sequence_name
@sequence_name ||= initial_sequence_name
end

def class_name
@class_name ||= sequence_name + 'Sequence'
end

def file_name
@file_name ||= sequence_name.underscore + '_sequence'
end

def title
@title ||= profile['title'] || profile['name']
end

def test_id_prefix
# this needs to be made more generic
@test_id_prefix ||= profile['name'].chars.select { |c| c.upcase == c && c != ' ' }.join
end

def requirements
@requirements ||= [":#{resource_type.underscore}_id"]
end

def url
@url ||= profile['url']
end

def add_test(test)
@tests << test
end

private

def initial_sequence_name
return profile['name'] unless profile['name'].include?('-')

profile['name'].split('-').map(&:capitalize).join
end
end
end
end
17 changes: 17 additions & 0 deletions generator/test_metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module Inferno
module Generator
class TestMetadata
attr_accessor :title, :key, :link, :description, :optional, :code

def initialize(title: '', key: nil, link: '', description: '', code: '')
@title = title
@key = key
@link = link
@description = description
@code = code
end
end
end
end
4 changes: 4 additions & 0 deletions lib/app/utils/validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ def self.definitions
json = File.read(definition)
version = VERSION_MAP[JSON.parse(json)['fhirVersion']]
resource = get_resource(json, version)
next unless resource.respond_to? 'url'

DEFINITIONS[resource.url] = resource
if resource.resourceType == 'StructureDefinition'
next unless resource.snapshot.present?

profiled_type = resource.snapshot.element.first.path # will this always be the first?
RESOURCES[version][profiled_type] ||= []
RESOURCES[version][profiled_type] << resource
Expand Down

0 comments on commit ff81cb2

Please # to comment.