subscriptions_test_kit 0.11.1 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/subscriptions_test_kit/common/notification_conformance_verification.rb +4 -4
- data/lib/subscriptions_test_kit/endpoints/subscription_create_endpoint.rb +1 -1
- data/lib/subscriptions_test_kit/jobs/send_subscription_notifications.rb +3 -1
- data/lib/subscriptions_test_kit/requirements/generated/subscriptions_r5_backport_r4_client_requirements_coverage.csv +17 -0
- data/lib/subscriptions_test_kit/requirements/generated/{subscriptions-test-kit_requirements_coverage.csv → subscriptions_r5_backport_r4_server_requirements_coverage.csv} +114 -132
- data/lib/subscriptions_test_kit/requirements/hl7.fhir.uv.subscriptions_1.1.0_requirements.xlsx +0 -0
- data/lib/subscriptions_test_kit/requirements/{subscriptions-test-kit_requirements.csv → subscriptions_test_kit_requirements.csv} +139 -141
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils.rb +3 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/processing_attestation_test.rb +0 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client_suite.rb +8 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/subscription_conformance_test.rb +1 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/handshake_heartbeat/handshake_conformance_test.rb +0 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server_suite.rb +8 -0
- data/lib/subscriptions_test_kit/version.rb +2 -2
- data/lib/subscriptions_test_kit.rb +0 -1
- metadata +8 -10
- data/lib/inferno_requirements_tools/ext/inferno_core/runnable.rb +0 -22
- data/lib/inferno_requirements_tools/tasks/collect_requirements.rb +0 -223
- data/lib/inferno_requirements_tools/tasks/requirements_coverage.rb +0 -266
- data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_out_of_scope_requirements.csv +0 -23
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: subscriptions_test_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Naden, Emily Semple, Tom Strassner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inferno_core
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.6.
|
19
|
+
version: 0.6.14
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.6.
|
26
|
+
version: 0.6.14
|
27
27
|
description: Inferno test kit for FHIR R5-style Subscriptions
|
28
28
|
email:
|
29
29
|
- inferno@groups.mitre.org
|
@@ -38,9 +38,6 @@ files:
|
|
38
38
|
- config/presets/subscription_server_preset_empty.json.erb
|
39
39
|
- config/presets/subscription_server_preset_full_resource.json.erb
|
40
40
|
- config/presets/subscription_server_preset_id_only.json.erb
|
41
|
-
- lib/inferno_requirements_tools/ext/inferno_core/runnable.rb
|
42
|
-
- lib/inferno_requirements_tools/tasks/collect_requirements.rb
|
43
|
-
- lib/inferno_requirements_tools/tasks/requirements_coverage.rb
|
44
41
|
- lib/subscriptions_test_kit.rb
|
45
42
|
- lib/subscriptions_test_kit/common/notification_conformance_verification.rb
|
46
43
|
- lib/subscriptions_test_kit/common/subscription_conformance_verification.rb
|
@@ -57,9 +54,10 @@ files:
|
|
57
54
|
- lib/subscriptions_test_kit/igs/README.md
|
58
55
|
- lib/subscriptions_test_kit/jobs/send_subscription_notifications.rb
|
59
56
|
- lib/subscriptions_test_kit/metadata.rb
|
60
|
-
- lib/subscriptions_test_kit/requirements/generated/
|
61
|
-
- lib/subscriptions_test_kit/requirements/
|
62
|
-
- lib/subscriptions_test_kit/requirements/
|
57
|
+
- lib/subscriptions_test_kit/requirements/generated/subscriptions_r5_backport_r4_client_requirements_coverage.csv
|
58
|
+
- lib/subscriptions_test_kit/requirements/generated/subscriptions_r5_backport_r4_server_requirements_coverage.csv
|
59
|
+
- lib/subscriptions_test_kit/requirements/hl7.fhir.uv.subscriptions_1.1.0_requirements.xlsx
|
60
|
+
- lib/subscriptions_test_kit/requirements/subscriptions_test_kit_requirements.csv
|
63
61
|
- lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils.rb
|
64
62
|
- lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/fixtures/capability_statement.json
|
65
63
|
- lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_payload_verification_test.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Inferno
|
2
|
-
module DSL
|
3
|
-
# This module contains the DSL for defining child entities in the test
|
4
|
-
# definition framework.
|
5
|
-
module Runnable
|
6
|
-
# Set/Get the IDs of requirements verifed by this runnable
|
7
|
-
# Set with [] to clear the list
|
8
|
-
#
|
9
|
-
# @param requirements [Array<String>]
|
10
|
-
# @return [Array<String>] the requirement IDs
|
11
|
-
def verifies_requirements(*requirement_ids)
|
12
|
-
if requirement_ids.empty?
|
13
|
-
@requirement_ids || []
|
14
|
-
elsif requirement_ids == [[]]
|
15
|
-
@requirement_ids = []
|
16
|
-
else
|
17
|
-
@requirement_ids = requirement_ids
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,223 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'csv'
|
4
|
-
require 'roo'
|
5
|
-
|
6
|
-
module InfernoRequirementsTools
|
7
|
-
module Tasks
|
8
|
-
# This class manages the collection of requirements details from
|
9
|
-
# requirements planning excel workbooks into a CSV representation.
|
10
|
-
# Currently splits out Requirements and Planned Not Tested Requirements
|
11
|
-
# into two separate files.
|
12
|
-
#
|
13
|
-
# The `run` method will generate the files
|
14
|
-
# The `run_check` method will check whether the previously generated files are up-to-date.
|
15
|
-
class CollectRequirements
|
16
|
-
# Update these constants based on the test kit.
|
17
|
-
TEST_KIT_ID = 'subscriptions-test-kit'
|
18
|
-
INPUT_SETS = ['hl7.fhir.uv.subscriptions_1.1.0'].freeze
|
19
|
-
|
20
|
-
# Derivative constants
|
21
|
-
TEST_KIT_CODE_FOLDER = TEST_KIT_ID.gsub('-', '_')
|
22
|
-
INPUT_HEADERS =
|
23
|
-
[
|
24
|
-
'ID*',
|
25
|
-
'URL*',
|
26
|
-
'Requirement*',
|
27
|
-
'Conformance*',
|
28
|
-
'Actor*',
|
29
|
-
'Sub-Requirement(s)',
|
30
|
-
'Conditionality',
|
31
|
-
'Verifiable?',
|
32
|
-
'Verifiability Details',
|
33
|
-
'Planning To Test?',
|
34
|
-
'Planning To Test Details'
|
35
|
-
].freeze
|
36
|
-
REQUIREMENTS_OUTPUT_HEADERS =
|
37
|
-
[
|
38
|
-
'Req Set',
|
39
|
-
'ID',
|
40
|
-
'URL',
|
41
|
-
'Requirement',
|
42
|
-
'Conformance',
|
43
|
-
'Actor',
|
44
|
-
'Sub-Requirement(s)',
|
45
|
-
'Conditionality'
|
46
|
-
].freeze
|
47
|
-
REQUIREMENTS_OUTPUT_FILE_NAME = "#{TEST_KIT_ID}_requirements.csv".freeze
|
48
|
-
REQUIREMENTS_OUTPUT_FILE =
|
49
|
-
File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', REQUIREMENTS_OUTPUT_FILE_NAME).freeze
|
50
|
-
PLANNED_NOT_TESTED_OUTPUT_HEADERS = ['Req Set', 'ID', 'Reason', 'Details'].freeze
|
51
|
-
PLANNED_NOT_TESTED_OUTPUT_FILE_NAME = "#{TEST_KIT_ID}_out_of_scope_requirements.csv".freeze
|
52
|
-
PLANNED_NOT_TESTED_OUTPUT_FILE =
|
53
|
-
File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', PLANNED_NOT_TESTED_OUTPUT_FILE_NAME).freeze
|
54
|
-
|
55
|
-
def available_input_worksheets
|
56
|
-
@available_input_worksheets ||= Dir.glob(File.join(@input_directory, '*.xlsx')).reject { |f| f.include?('~$') }
|
57
|
-
end
|
58
|
-
|
59
|
-
# Of the form:
|
60
|
-
# {
|
61
|
-
# req_set_id_1: [row1, row2, row 3, ...],
|
62
|
-
# req_set_id_2: [row1, row2, row 3, ...]
|
63
|
-
# }
|
64
|
-
def input_requirement_sets
|
65
|
-
@input_requirement_sets ||= INPUT_SETS.each_with_object({}) do |req_set_id, hash|
|
66
|
-
req_set_file = available_input_worksheets.find { |worksheet_file| worksheet_file.include?(req_set_id) }
|
67
|
-
|
68
|
-
hash[req_set_id] =
|
69
|
-
unless req_set_file.nil?
|
70
|
-
CSV.parse(Roo::Spreadsheet.open(req_set_file).sheet('Requirements').to_csv,
|
71
|
-
headers: true).map do |row|
|
72
|
-
row.to_h.slice(*INPUT_HEADERS)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def new_requirements_csv
|
79
|
-
@new_requirements_csv ||=
|
80
|
-
CSV.generate(+"\xEF\xBB\xBF") do |csv| # start with an unnecessary BOM to make viewing in excel easier
|
81
|
-
csv << REQUIREMENTS_OUTPUT_HEADERS
|
82
|
-
|
83
|
-
input_requirement_sets.each do |req_set_id, input_rows|
|
84
|
-
input_rows.each do |input_row| # NOTE: use row order from source file
|
85
|
-
csv << REQUIREMENTS_OUTPUT_HEADERS.map do |header|
|
86
|
-
header == 'Req Set' ? req_set_id : input_row[header] || input_row["#{header}*"]
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def old_requirements_csv
|
94
|
-
@old_requirements_csv ||= File.read(REQUIREMENTS_OUTPUT_FILE)
|
95
|
-
end
|
96
|
-
|
97
|
-
def new_planned_not_tested_csv
|
98
|
-
@new_planned_not_tested_csv ||=
|
99
|
-
CSV.generate(+"\xEF\xBB\xBF") do |csv| # start with an unnecessary BOM to make viewing in excel easier
|
100
|
-
csv << PLANNED_NOT_TESTED_OUTPUT_HEADERS
|
101
|
-
|
102
|
-
input_requirement_sets.each do |req_set_id, input_rows|
|
103
|
-
input_rows.each do |row|
|
104
|
-
if spreadsheet_value_falsy?(row['Verifiable?'])
|
105
|
-
csv << [req_set_id, row['ID*'], 'Not Verifiable', row['Verifiability Details']]
|
106
|
-
elsif spreadsheet_value_falsy?(row['Planning To Test?'])
|
107
|
-
csv << [req_set_id, row['ID*'], 'Not Tested', row['Planning To Test Details']]
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def old_planned_not_tested_csv
|
115
|
-
@old_planned_not_tested_csv ||= File.read(PLANNED_NOT_TESTED_OUTPUT_FILE)
|
116
|
-
end
|
117
|
-
|
118
|
-
def run(input_directory)
|
119
|
-
@input_directory = input_directory
|
120
|
-
check_presence_of_input_files
|
121
|
-
|
122
|
-
update_requirements =
|
123
|
-
if File.exist?(REQUIREMENTS_OUTPUT_FILE)
|
124
|
-
if old_requirements_csv == new_requirements_csv
|
125
|
-
puts "'#{REQUIREMENTS_OUTPUT_FILE_NAME}' file is up to date."
|
126
|
-
false
|
127
|
-
else
|
128
|
-
puts 'Requirements set has changed.'
|
129
|
-
true
|
130
|
-
end
|
131
|
-
else
|
132
|
-
puts "No existing #{REQUIREMENTS_OUTPUT_FILE_NAME}."
|
133
|
-
true
|
134
|
-
end
|
135
|
-
|
136
|
-
if update_requirements
|
137
|
-
puts "Writing to file #{REQUIREMENTS_OUTPUT_FILE}..."
|
138
|
-
File.write(REQUIREMENTS_OUTPUT_FILE, new_requirements_csv, encoding: Encoding::UTF_8)
|
139
|
-
end
|
140
|
-
|
141
|
-
udpate_planned_not_tested =
|
142
|
-
if File.exist?(PLANNED_NOT_TESTED_OUTPUT_FILE)
|
143
|
-
if old_planned_not_tested_csv == new_planned_not_tested_csv
|
144
|
-
puts "'#{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME}' file is up to date."
|
145
|
-
false
|
146
|
-
else
|
147
|
-
puts 'Planned Not Tested Requirements set has changed.'
|
148
|
-
true
|
149
|
-
end
|
150
|
-
else
|
151
|
-
puts "No existing #{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME}."
|
152
|
-
true
|
153
|
-
end
|
154
|
-
|
155
|
-
if udpate_planned_not_tested
|
156
|
-
puts "Writing to file #{PLANNED_NOT_TESTED_OUTPUT_FILE}..."
|
157
|
-
File.write(PLANNED_NOT_TESTED_OUTPUT_FILE, new_planned_not_tested_csv, encoding: Encoding::UTF_8)
|
158
|
-
end
|
159
|
-
|
160
|
-
puts 'Done.'
|
161
|
-
end
|
162
|
-
|
163
|
-
def run_check(input_directory)
|
164
|
-
@input_directory = input_directory
|
165
|
-
check_presence_of_input_files
|
166
|
-
|
167
|
-
requirements_ok =
|
168
|
-
if File.exist?(REQUIREMENTS_OUTPUT_FILE)
|
169
|
-
if old_requirements_csv == new_requirements_csv
|
170
|
-
puts "'#{REQUIREMENTS_OUTPUT_FILE_NAME}' file is up to date."
|
171
|
-
true
|
172
|
-
else
|
173
|
-
puts "#{REQUIREMENTS_OUTPUT_FILE_NAME} file is out of date."
|
174
|
-
false
|
175
|
-
end
|
176
|
-
else
|
177
|
-
puts "No existing #{REQUIREMENTS_OUTPUT_FILE_NAME} file."
|
178
|
-
false
|
179
|
-
end
|
180
|
-
|
181
|
-
planned_not_tested_requirements_ok =
|
182
|
-
if File.exist?(PLANNED_NOT_TESTED_OUTPUT_FILE)
|
183
|
-
if old_planned_not_tested_csv == new_planned_not_tested_csv
|
184
|
-
puts "'#{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME}' file is up to date."
|
185
|
-
true
|
186
|
-
else
|
187
|
-
puts "#{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME} file is out of date."
|
188
|
-
false
|
189
|
-
end
|
190
|
-
else
|
191
|
-
puts "No existing #{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME} file."
|
192
|
-
false
|
193
|
-
end
|
194
|
-
|
195
|
-
return if planned_not_tested_requirements_ok && requirements_ok
|
196
|
-
|
197
|
-
puts <<~MESSAGE
|
198
|
-
Check Failed. To resolve, run:
|
199
|
-
|
200
|
-
bundle exec rake "requirements:collect[<input_directory>]"
|
201
|
-
|
202
|
-
MESSAGE
|
203
|
-
exit(1)
|
204
|
-
end
|
205
|
-
|
206
|
-
def check_presence_of_input_files
|
207
|
-
input_requirement_sets.each do |req_set_id, rows|
|
208
|
-
next unless rows.nil?
|
209
|
-
|
210
|
-
puts %(
|
211
|
-
Could not find input file for set #{req_set_id} in directory #{input_directory}. Aborting requirements
|
212
|
-
collection..."
|
213
|
-
)
|
214
|
-
exit(1)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
def spreadsheet_value_falsy?(str)
|
219
|
-
str&.downcase == 'no' || str&.downcase == 'false'
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
@@ -1,266 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'csv'
|
4
|
-
require_relative '../ext/inferno_core/runnable'
|
5
|
-
|
6
|
-
module InfernoRequirementsTools
|
7
|
-
module Tasks
|
8
|
-
# This class manages the mapping of test kit tests to requirements that they verify
|
9
|
-
# and creates a CSV file with the tests that cover each requirement.
|
10
|
-
# It expects a CSV file in the repo at `lib/[test kit id]/requirements/[test kit id]_requirements.csv`
|
11
|
-
# that serves as the source of the requirement set for the test kit. The requirements in
|
12
|
-
# this files are identified by a requirement set and an id and tests, groups, and suites
|
13
|
-
# within in the test kit can claim that they verify a requirement by including a reference
|
14
|
-
# to that requirementin the form <requirement set>@<id> in their `verifies_requirements` field.
|
15
|
-
# Requirements that are out of scope can be listed in a companion file
|
16
|
-
# `lib/[test kit id]/requirements/[test kit id]_out_of_scope_requirements.csv`.
|
17
|
-
#
|
18
|
-
# The `run` method generates a CSV file at
|
19
|
-
# `lib/[test kit id]/requirements/generated/[test kit id]_requirements_coverage.csv``.
|
20
|
-
# This file will be identical to the input spreadsheet, plus an additional column which holds a comma separated
|
21
|
-
# list of inferno test IDs that test each requirement. These test IDs are Inferno short form IDs that represent the
|
22
|
-
# position of the test within its group and suite. For example, the fifth test in the second group will have an ID
|
23
|
-
# of 2.05. This ID is also shown in the Inferno web UI.
|
24
|
-
#
|
25
|
-
# The `run_check` method will check whether the previously generated file is up-to-date.
|
26
|
-
class RequirementsCoverage
|
27
|
-
# Update these constants based on the test kit.
|
28
|
-
TEST_KIT_ID = 'subscriptions-test-kit'
|
29
|
-
TEST_SUITES = [SubscriptionsTestKit::SubscriptionsR5BackportR4Client::SubscriptionsR5BackportR4ClientSuite,
|
30
|
-
SubscriptionsTestKit::SubscriptionsR5BackportR4Server::SubscriptionsR5BackportR4ServerSuite].freeze
|
31
|
-
SUITE_ID_TO_ACTOR_MAP = {
|
32
|
-
'subscriptions_r5_backport_r4_client' => 'Client',
|
33
|
-
'subscriptions_r5_backport_r4_server' => 'Server'
|
34
|
-
}.freeze
|
35
|
-
|
36
|
-
# Derivative constants
|
37
|
-
TEST_KIT_CODE_FOLDER = TEST_KIT_ID.gsub('-', '_')
|
38
|
-
INPUT_HEADERS = [
|
39
|
-
'Req Set',
|
40
|
-
'ID',
|
41
|
-
'URL',
|
42
|
-
'Requirement',
|
43
|
-
'Conformance',
|
44
|
-
'Actor',
|
45
|
-
'Sub-Requirement(s)',
|
46
|
-
'Conditionality'
|
47
|
-
].freeze
|
48
|
-
SHORT_ID_HEADER = 'Short ID(s)'
|
49
|
-
FULL_ID_HEADER = 'Full ID(s)'
|
50
|
-
INPUT_FILE_NAME = "#{TEST_KIT_ID}_requirements.csv".freeze
|
51
|
-
INPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', INPUT_FILE_NAME).freeze
|
52
|
-
NOT_TESTED_FILE_NAME = "#{TEST_KIT_ID}_out_of_scope_requirements.csv".freeze
|
53
|
-
NOT_TESTED_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', NOT_TESTED_FILE_NAME).freeze
|
54
|
-
OUTPUT_HEADERS = INPUT_HEADERS + TEST_SUITES.flat_map do |suite|
|
55
|
-
["#{suite.title} #{SHORT_ID_HEADER}", "#{suite.title} #{FULL_ID_HEADER}"]
|
56
|
-
end
|
57
|
-
OUTPUT_FILE_NAME = "#{TEST_KIT_ID}_requirements_coverage.csv".freeze
|
58
|
-
OUTPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', 'generated', OUTPUT_FILE_NAME).freeze
|
59
|
-
|
60
|
-
def input_rows
|
61
|
-
@input_rows ||=
|
62
|
-
CSV.parse(File.open(INPUT_FILE, 'r:bom|utf-8'), headers: true).map do |row|
|
63
|
-
row.to_h.slice(*INPUT_HEADERS)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def not_tested_requirements_map
|
68
|
-
@not_tested_requirements_map ||= load_not_tested_requirements
|
69
|
-
end
|
70
|
-
|
71
|
-
def load_not_tested_requirements
|
72
|
-
return {} unless File.exist?(NOT_TESTED_FILE)
|
73
|
-
|
74
|
-
not_tested_requirements = {}
|
75
|
-
CSV.parse(File.open(NOT_TESTED_FILE, 'r:bom|utf-8'), headers: true).each do |row|
|
76
|
-
row_hash = row.to_h
|
77
|
-
not_tested_requirements["#{row_hash['Req Set']}@#{row_hash['ID']}"] = row_hash
|
78
|
-
end
|
79
|
-
|
80
|
-
not_tested_requirements
|
81
|
-
end
|
82
|
-
|
83
|
-
# Of the form:
|
84
|
-
# {
|
85
|
-
# 'req-id-1': [
|
86
|
-
# { short_id: 'short-id-1', full_id: 'long-id-1', suite_id: 'suite-id-1' },
|
87
|
-
# { short_id: 'short-id-2', full_id: 'long-id-2', suite_id: 'suite-id-2' }
|
88
|
-
# ],
|
89
|
-
# 'req-id-2': [{ short_id: 'short-id-3', full_id: 'long-id-3', suite_id: 'suite-id-3' }],
|
90
|
-
# ...
|
91
|
-
# }
|
92
|
-
def inferno_requirements_map
|
93
|
-
@inferno_requirements_map ||= TEST_SUITES.each_with_object({}) do |suite, requirements_map|
|
94
|
-
serialize_requirements(suite, 'suite', suite.id, requirements_map)
|
95
|
-
suite.groups.each do |group|
|
96
|
-
map_group_requirements(group, suite.id, requirements_map)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
102
|
-
def new_csv
|
103
|
-
@new_csv ||=
|
104
|
-
CSV.generate(+"\xEF\xBB\xBF") do |csv|
|
105
|
-
csv << OUTPUT_HEADERS
|
106
|
-
input_rows.each do |row| # NOTE: use row order from source file
|
107
|
-
next if row['Conformance'] == 'DEPRECATED' # filter out deprecated rows
|
108
|
-
|
109
|
-
TEST_SUITES.each do |suite|
|
110
|
-
suite_actor = SUITE_ID_TO_ACTOR_MAP[suite.id]
|
111
|
-
if row['Actor']&.include?(suite_actor)
|
112
|
-
set_and_req_id = "#{row['Req Set']}@#{row['ID']}"
|
113
|
-
suite_requirement_items = inferno_requirements_map[set_and_req_id]&.filter do |item|
|
114
|
-
item[:suite_id] == suite.id
|
115
|
-
end
|
116
|
-
short_ids = suite_requirement_items&.map { |item| item[:short_id] }
|
117
|
-
full_ids = suite_requirement_items&.map { |item| item[:full_id] }
|
118
|
-
if short_ids.blank? && not_tested_requirements_map.key?(set_and_req_id)
|
119
|
-
row["#{suite.title} #{SHORT_ID_HEADER}"] = 'Not Tested'
|
120
|
-
row["#{suite.title} #{FULL_ID_HEADER}"] = 'Not Tested'
|
121
|
-
else
|
122
|
-
row["#{suite.title} #{SHORT_ID_HEADER}"] = short_ids&.join(', ')
|
123
|
-
row["#{suite.title} #{FULL_ID_HEADER}"] = full_ids&.join(', ')
|
124
|
-
end
|
125
|
-
else
|
126
|
-
row["#{suite.title} #{SHORT_ID_HEADER}"] = 'NA'
|
127
|
-
row["#{suite.title} #{FULL_ID_HEADER}"] = 'NA'
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
csv << row.values
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
136
|
-
|
137
|
-
def input_requirement_ids
|
138
|
-
@input_requirement_ids ||= input_rows.map { |row| "#{row['Req Set']}@#{row['ID']}" }
|
139
|
-
end
|
140
|
-
|
141
|
-
# The requirements present in Inferno that aren't in the input spreadsheet
|
142
|
-
def unmatched_requirements_map
|
143
|
-
@unmatched_requirements_map ||= inferno_requirements_map.except(*input_requirement_ids)
|
144
|
-
end
|
145
|
-
|
146
|
-
def old_csv
|
147
|
-
@old_csv ||= File.read(OUTPUT_FILE)
|
148
|
-
end
|
149
|
-
|
150
|
-
def run
|
151
|
-
unless File.exist?(INPUT_FILE)
|
152
|
-
puts "Could not find input file: #{INPUT_FILE}. Aborting requirements coverage generation..."
|
153
|
-
exit(1)
|
154
|
-
end
|
155
|
-
|
156
|
-
if unmatched_requirements_map.any?
|
157
|
-
puts "WARNING: The following requirements indicated in the test kit are not present in #{INPUT_FILE_NAME}"
|
158
|
-
output_requirements_map_table(unmatched_requirements_map)
|
159
|
-
end
|
160
|
-
|
161
|
-
if File.exist?(OUTPUT_FILE)
|
162
|
-
if old_csv == new_csv
|
163
|
-
puts "'#{OUTPUT_FILE_NAME}' file is up to date."
|
164
|
-
return
|
165
|
-
else
|
166
|
-
puts 'Requirements coverage has changed.'
|
167
|
-
end
|
168
|
-
else
|
169
|
-
puts "No existing #{OUTPUT_FILE_NAME}."
|
170
|
-
end
|
171
|
-
|
172
|
-
puts "Writing to file #{OUTPUT_FILE}..."
|
173
|
-
File.write(OUTPUT_FILE, new_csv)
|
174
|
-
puts 'Done.'
|
175
|
-
end
|
176
|
-
|
177
|
-
def run_check
|
178
|
-
unless File.exist?(INPUT_FILE)
|
179
|
-
puts "Could not find input file: #{INPUT_FILE}. Aborting requirements coverage check..."
|
180
|
-
exit(1)
|
181
|
-
end
|
182
|
-
|
183
|
-
if unmatched_requirements_map.any?
|
184
|
-
puts "The following requirements indicated in the test kit are not present in #{INPUT_FILE_NAME}"
|
185
|
-
output_requirements_map_table(unmatched_requirements_map)
|
186
|
-
end
|
187
|
-
|
188
|
-
if File.exist?(OUTPUT_FILE)
|
189
|
-
if old_csv == new_csv
|
190
|
-
puts "'#{OUTPUT_FILE_NAME}' file is up to date."
|
191
|
-
return unless unmatched_requirements_map.any?
|
192
|
-
else
|
193
|
-
puts <<~MESSAGE
|
194
|
-
#{OUTPUT_FILE_NAME} file is out of date.
|
195
|
-
To regenerate the file, run:
|
196
|
-
|
197
|
-
bundle exec rake requirements:generate_coverage
|
198
|
-
|
199
|
-
MESSAGE
|
200
|
-
end
|
201
|
-
else
|
202
|
-
puts <<~MESSAGE
|
203
|
-
No existing #{OUTPUT_FILE_NAME} file.
|
204
|
-
To generate the file, run:
|
205
|
-
|
206
|
-
bundle exec rake requirements:generate_coverage
|
207
|
-
|
208
|
-
MESSAGE
|
209
|
-
end
|
210
|
-
|
211
|
-
puts 'Check failed.'
|
212
|
-
exit(1)
|
213
|
-
end
|
214
|
-
|
215
|
-
def map_group_requirements(group, suite_id, requirements_map)
|
216
|
-
serialize_requirements(group, group.short_id, suite_id, requirements_map)
|
217
|
-
group.tests&.each { |test| serialize_requirements(test, test.short_id, suite_id, requirements_map) }
|
218
|
-
group.groups&.each { |subgroup| map_group_requirements(subgroup, suite_id, requirements_map) }
|
219
|
-
end
|
220
|
-
|
221
|
-
def serialize_requirements(runnable, short_id, suite_id, requirements_map)
|
222
|
-
runnable.verifies_requirements&.each do |requirement_id|
|
223
|
-
requirement_id_string = requirement_id.to_s
|
224
|
-
|
225
|
-
requirements_map[requirement_id_string] ||= []
|
226
|
-
requirements_map[requirement_id_string] << { short_id:, full_id: runnable.id, suite_id: }
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
# Output the requirements in the map like so:
|
231
|
-
#
|
232
|
-
# requirement_id | short_id | full_id
|
233
|
-
# ---------------+------------+----------
|
234
|
-
# req-id-1 | short-id-1 | full-id-1
|
235
|
-
# req-id-2 | short-id-2 | full-id-2
|
236
|
-
#
|
237
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
238
|
-
def output_requirements_map_table(requirements_map)
|
239
|
-
headers = %w[requirement_id short_id full_id]
|
240
|
-
col_widths = headers.map(&:length)
|
241
|
-
col_widths[0] = [col_widths[0], requirements_map.keys.map(&:length).max].max
|
242
|
-
col_widths[1] = ([col_widths[1]] + requirements_map.values.flatten.map { |item| item[:short_id].length }).max
|
243
|
-
col_widths[2] = ([col_widths[2]] + requirements_map.values.flatten.map { |item| item[:full_id].length }).max
|
244
|
-
col_widths.map { |width| width + 3 }
|
245
|
-
|
246
|
-
puts [
|
247
|
-
headers[0].ljust(col_widths[0]),
|
248
|
-
headers[1].ljust(col_widths[1]),
|
249
|
-
headers[2].ljust(col_widths[2])
|
250
|
-
].join(' | ')
|
251
|
-
puts col_widths.map { |width| '-' * width }.join('-+-')
|
252
|
-
requirements_map.each do |requirement_id, runnables|
|
253
|
-
runnables.each do |runnable|
|
254
|
-
puts [
|
255
|
-
requirement_id.ljust(col_widths[0]),
|
256
|
-
runnable[:short_id].ljust(col_widths[1]),
|
257
|
-
runnable[:full_id].ljust(col_widths[2])
|
258
|
-
].join(' | ')
|
259
|
-
end
|
260
|
-
end
|
261
|
-
puts
|
262
|
-
end
|
263
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_out_of_scope_requirements.csv
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
Req Set,ID,Reason,Details
|
2
|
-
hl7.fhir.uv.subscriptions_1.1.0,3,Not Verifiable,Not precise enough to be consistently verified
|
3
|
-
hl7.fhir.uv.subscriptions_1.1.0,4,Not Tested,"MAY requirement, support for which doesn't imply other requirements. Additionally, meeting this requirement is simply the absence of other features."
|
4
|
-
hl7.fhir.uv.subscriptions_1.1.0,18,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
5
|
-
hl7.fhir.uv.subscriptions_1.1.0,19,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
6
|
-
hl7.fhir.uv.subscriptions_1.1.0,22,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
7
|
-
hl7.fhir.uv.subscriptions_1.1.0,33,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
8
|
-
hl7.fhir.uv.subscriptions_1.1.0,34,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
9
|
-
hl7.fhir.uv.subscriptions_1.1.0,37,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
10
|
-
hl7.fhir.uv.subscriptions_1.1.0,41,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
11
|
-
hl7.fhir.uv.subscriptions_1.1.0,58,Not Tested,Conflicts with requirement 120 and is removed in future versions of the spec.
|
12
|
-
hl7.fhir.uv.subscriptions_1.1.0,61,Not Verifiable,"In the context of this implementation guide, details on how to receive notifications over a custom channel do not exist."
|
13
|
-
hl7.fhir.uv.subscriptions_1.1.0,80,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
14
|
-
hl7.fhir.uv.subscriptions_1.1.0,84,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
15
|
-
hl7.fhir.uv.subscriptions_1.1.0,88,Not Tested,"MAY requirement, support for which doesn't imply other requirements. Additionally, Inferno won't be able to accept non-R4 subscriptions."
|
16
|
-
hl7.fhir.uv.subscriptions_1.1.0,92,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
17
|
-
hl7.fhir.uv.subscriptions_1.1.0,100,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
18
|
-
hl7.fhir.uv.subscriptions_1.1.0,104,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
19
|
-
hl7.fhir.uv.subscriptions_1.1.0,105,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
20
|
-
hl7.fhir.uv.subscriptions_1.1.0,117,Not Tested,"MAY requirement, support for which doesn't imply other requirements."
|
21
|
-
hl7.fhir.uv.subscriptions_1.1.0,123,Not Tested,Used for Websocket channels that Inferno does not currently support
|
22
|
-
hl7.fhir.uv.subscriptions_1.1.0,131,Not Verifiable,IG doesn't indicate what must support requirements are for the SubscriptionStatus profile (in contrast to the Subscription profile where they are provided)
|
23
|
-
hl7.fhir.uv.subscriptions_1.1.0,132,Not Verifiable,IG doesn't indicate what must support requirements are for the SubscriptionStatus profile (in contrast to the Subscription profile where they are provided)
|