FHIR Terminology Ecosystem IG, published by HL7 FHIR Product Director. This guide is not an authorized publication; it is the continuous build for version 1.9.6 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/HL7/fhir-tx-ecosystem-ig/ and changes regularly. See the Directory of published versions
This page details the changes made to the terminology tests over time, based on the GitHub releases. Note that the GitHub repository that contains these tests also contains many other test cases for other kinds of functionality; this history only lists releases that include changes to the terminology tests.
This release mostly corrects expected responses that were wrong, but were not being checked properly.
=. So any string containing an = - most SNOMED CT expression messages, and anything naming an implicit value set (?fhir_vs=) - was only compared up to its first =. The runner now only compares strings as base64 when they really are base64 (this is fixed in the test runner, not the test cases; runners up to 6.10.5 have the bug). Correcting it exposed the wrong expected responses listed belowTest Edition, not the International Edition (validate-code-procedure-pc-bad1 and -bad2, validate-code-pc-unbracketed, and the validate-code-pc-mrcm-* tests)validate-code-implied-2 named the wrong value set in its message - it is the implicit value set that was asked for (http://snomed.info/sct?fhir_vs=refset/734139008), not sct-pc-none; and the display of 80891009 in bugs/validate-sct-parse-pc is Heart structurevalidate-code-inactive-display-*, both SNOMED CT and extensions), the list of matching systems in errors-combination-bad, the quoted code system URL in the unknown code system messages (errors-unknown-system2, validation-simple-coding-bad-system), and a stray double space in the related simple-all message} at the end of the value set URL; the overload tests expect the display Display #2; the OMOP used-conceptmap has no trailing |; and the LOINC supplement in the tx.fhir.org $lookup tests is version 2.82$validate-code: the code system version is systemVersion, not version (which is the CodeSystem/$validate-code parameter, and is not defined for ValueSet/$validate-code). Seven SNOMED CT and ICD-11 requests used version, which servers were right to ignore; they now use systemVersion, and validate-code-pc-none now states it toovalidate-code-pc-none: when the code is not in the value set, the version reported is the one the value set selects (compose.include.version, here the test edition), not the server's default edition$translate: result can only be true if at least one match is an actual translation. A match that says the concept is not related (not-related-to, or disjoint / unmatched in R4), or that there is no mapping (noMap), is still returned, but result is false (translate-2b, translate-4)validate-code-procedure-pc-bad1 and validate-code-pc-unbracketed must mention expression (and the code at fault), and the not-in-value-set message in validate-code-pc-none must name the value set and the expressiondisplayLanguage is written without spaces (en,*;q=0, not en, *; q=0), in the requests and in the expansion parameter a server echoes back (language-xform-*-hard, validation-simple-coding-bad-language). The Accept-Language header in validation-simple-coding-bad-language-header keeps its spaces, which are legal in a header$validate-code with something missing: eighteen new tests in the validation suite cover a request with no code at all (a code with no system and no inferSystem, a system with no code, and nothing at all — all request errors), and a Coding or CodeableConcept that is missing its code or its system, against both a value set and a code system. A Coding or CodeableConcept that was supplied but has bad content is a validation outcome (result = false), not a request error, and a missing code is reported against the coding itself, as a warning with issue type invalid and a tx-issue-type of invalid-data (the data supplied was invalid; there is no code for invalid-code to be about), with no companion "not in the value set" issue for a code that was never providedCoding with neither a system nor a code - a display on its own, say - is one problem, not two. The server reports a single warning (Coding_has_no_system_or_code__cannot_validate) saying that neither was provided, rather than one message about the missing system and another about the missing code: there is nothing there to validate, and saying so twice does not make it clearerCoding.system or Coding.code is a warning, not an error: a code with no system has no defined meaning and cannot be validated, but only the caller knows whether that is acceptable where the coding came from — a validator has no way to tell, and has to report it as a warning either way, so the server reports it as one. The code still does not validate, so result is false. Two consequences: a result = false response does not always carry an error-level issue, and a CodeableConcept with a systemless coding alongside a coding that is in the value set still validates (validation-missing-vs-cc-mixed). inferSystem is defined only for the code parameter - it does not apply to a Coding, nor to the codings of a CodeableConcept - and two tests pin that: with it set, a systemless coding is reported exactly as it is without ituuid parameter has been removed from the profiles the tests send (parameters-default.json, the two version profiles, and the CDA profile). Nothing ever read it: it was sent on every request, but no server or client uses it, and it is not part of any operation's definition$subsumes with no code system (simple-subsumes-no-system, simple-subsumes-no-system-coding): codeA and codeB with no system parameter, or a codingA and codingB with no system, is a problem with the request, not a code system that cannot be found - 400, with issue type invalid, a tx-issue-type of invalid-data, and the message id SUBSUMPTION_NO_SYSTEM367430006:{405813007=(85562004:272741003=24028007)}. Without the brackets the expression is ambiguous as well as invalid - in A:{B=C:D=E,F=G} nothing says whether F=G refines C or A. lookup-pc, validate-code-pc-nested-good, validate-code-implied-2 and validate-code-implied-2b used the unbracketed form, and have been corrected (including the expected displays); two new tests check that the unbracketed form fails (lookup-pc-unbracketed, validate-code-pc-unbracketed)validate-code-pc-scg-no-comma, validate-code-pc-scg-comma)validate-code-pc-mrcm-domain-finding, -event and -multi)text/plain means charset=us-ascii (RFC 6657) and format=fixed (RFC 3676), so writing the default out gives the same media type, and a different value contradicts the bare form rather than narrowing it - this is where the rule that a parameter narrows a media type does not hold. For a text/* type whose registration does not say how its charset is determined, a server cannot tell whether a missing charset means any charset or US-ASCII, so the relationship cannot be determined; and an unknown parameter carried identically by both codes does not stop the server deciding$translate: ConceptMap.sourceScope limits the scope of a map, so a code outside it has no applicable map, and the map's unmapped does not apply either (translate-6a, which has been corrected); naming the map explicitly does not put the code into its scope (translate-6b)MSG_DRAFT_SRC_STATUS, and the message names the value set as well as the code system$lookup name is the edition name (SNOMED CT Test Edition), not system|version; validate-sct-display-2 expects the US English display now that refset language handling is fixed; the ICD-11 cs-validate-uri issue is CODE_NOT_IN_NORMAL_FORM rather than CODE_CASE_DIFFERENCE; the capability statement must declare $subsumes; and bugs/validate-no-system and validation-simple-coding-no-system follow the missing-system rules aboveThis release is mostly about $subsumes, which previously had almost no tests, and adds suites for mime types, ICD-11 and ValueSet.compose.property.
$subsumes against a CodeSystem resource: the simple-subsumes-* tests cover parent, child, equivalent, transitive, siblings, unrelated roots and an unknown code, each with both codeA/codeB and codingA/codingB. The tho suite does the same for act-class, where the hierarchy is stated in subsumedBy properties rather than by nesting, including a code with two parents - a relationship nesting cannot express at all - and two parents of the same code, which are not thereby related to each otheris-a, descendent-of, is-not-a and child-of against act-class, and child-of in the simple code system (validation-simple-child-of-child, -grandchild). descendent-of excludes the code named in the filter, which is what distinguishes it from is-a; child-of excludes it too, and stops at the direct children, which is what distinguishes it from descendent-of$subsumes: simple codes (including an unknown code, a malformed code, an unknown edition and an unknown code system), and 17 tests for post-coordinated expressions - refined expressions against ancestors and their own focus concept, attribute values, extra and different attributes, a primitive focus concept, a concept against its own normal form, grouping as the MRCM requires it, terms, conjunctions, and expressions against precoordinated concepts$subsumes can fail to decide. It has no outcome for "unknown", so where a server cannot determine the relationship it returns an error with the tx-issue-type cannot-determine rather than claiming not-subsumed. This applies to SNOMED CT expressions where the structure finds no relationship (which is not a proof that none exists - a server that can classify may answer not-subsumed instead), and to mime types with a parameter the server does not know$subsumes for LOINC (in the tx.fhir.org suite) and UCUM. UCUM has no hierarchy: the same unit written two ways is equivalent, but a scaled unit, or a unit with the same canonical unit and a different magnitude, is not subsumedPrefix rules for extlang and variant subtags); case - a tag in the wrong case is valid, since BCP 47 is case-insensitive, but the server returns normalized-code; subsumption, following RFC 4647 extended filtering; language, region and script filters, where an absent component does not match a fixed one; and expansion of those filters, which is paged for a language, too costly for a region, and not possible for a script alonemimetypes suite (mode mimetypes). Type and subtype have no hierarchy, but parameters narrow a media type, and a structured suffix is tested too. The base filter selects by type or type/subtype and the registered filter by presence in the IANA registry; only registered = true can be expanded, and that expansion is marked unclosedicd-11 suite (mode icd-11) now has tests for $lookup (MMS short codes and entity URIs, groupers, residual categories, the Foundation, ICF, languages and postcoordination), $validate-code against the code system and against value sets, and $expand of the WHO postcoordination scale value sets and of client-supplied value sets. Several are expected to fail against the current WHO ICD-API; tests/icd-11/doco.txt says what each one asserts and whyValueSet.compose.property: a new properties suite that expands value sets asking for all properties, with a wildcard and by enumerating themvalidation-simple-codeableconcept-unknown-system: a CodeableConcept with a coding from an unknown code system alongside a coding that is in the value set. The unknown system cannot be checked, but the other coding satisfies membership, so the result is true, with a warning$validate-code tests in the tx.fhir.org suiteOperationOutcome: diagnostics is no longer asserted in any expected response - it is for server-specific detail - and every issue now carries a tx-issue-type coding (too-costly and not-supported were the ones missing)ConceptMap-novs has been given its own id: it had the same id as ConceptMap-fullThis release is dominated by a rework of the $translate tests, and by settling how servers report inactive concepts.
$translate: the source concept may now be named with sourceCode + sourceSystem, with sourceCoding, or with sourceCodeableConcept, and R4 servers are tested with the R4 spellings of the same thing (code + system, coding, codeableConcept, and targetsystem)$translate: tests for the full range of relationship types, including not-related-to, which is returned as a match like any other; and for ConceptMap.group.element.comment and .target.comment, returned as sourceComment and targetComment (element.comment is preadopted from R6 using a cross-version extension)$translate: tests for noMap — stated as element.noMap in R5, and as a target with no code in R4, but reported the same way either way — and for ConceptMap.group.unmapped in all three modes (use-source-code, fixed and other-map), including chains of otherMap maps and the detection of circular references$translate: the response reports originMap, the concept map the chain of maps started from, and a used-conceptmap for every other map that contributed to it (originMap was introduced in 1.9.2; it is now settled as the start of the chain of maps, not the end)$translate: the R4 reverse parameter is tested — an R4 server reverses the source and target parameters and translates forwards, an R5 or later server returns an error — along with the R5+ way of asking the same question, which is to name the target concept as the source. The translate tests are split into two suites so that the unmapped tests see only the concept maps they are aboutvalidate-code-inactive-display and validation-simple-code-bad-display are each split into a lenient and a not-lenient variant, driven by a new lenient-display property on the test caseversion property (4.0, or !4.0 for "any version but R4"), and $optional$ accepts a version filter (version:4) so that one expected response can cover both R4 and R5 servers where they legitimately differ. Expected content can also be marked $only$ — required in the nominated versions or modes, and prohibited in all the others; this is the counterpart of $optional$, which only ever relaxes a requirementstatus property is no longer optional in an expansion, and the expected responses have been updated to require it. Also, a status of deprecated no longer makes a concept inactive — inactive and retired do (see the requirements page)simple-expand-regex-none, validation-simple-code-regex-none)CodeSystem.concept.property is 0.., so a filter selects a concept when *any of its values match — not just the first — and expansion.contains.property reports all of them (simple-expand-repeating-prop, simple-expand-repeating-prop-values)20250909, and now includes the MRCM attribute domain and attribute range reference sets, the lateralizable body structure reference set, and a simple reference set. The relationship module in the subset has been corrected, and the loading and regeneration instructions in tx-source/readme.md have been rewrittenconstraint = * filter returns every concept, including inactive concepts and module concepts, so the ECL wildcard expansion and snomed-expand-count-all now agree (2259 codes)http://snomed.info/xsct/31000003106/version/20250909), updating the affected requests and expected responses (display names and version URIs) to match, and correct the type of the system-version parameter from string to uriOperationOutcome.issue.location is optional in the expected responses, and the operationoutcome-message-id extension is optional for every server except tx.fhir.org; the optional version OUT parameter is allowed in the six codeableconcept-*-vs1wb version testssimple-all and simple-enumerated were each defined twice with different content. The permutations suite now uses the shared simple/valueset-all.json, and its own enumerated value set has been renamed to valueset-simple-enumerated-codes.jsoncode-vnn-vsmix-2, remove a stray uuid parameter and stale $optional$ markers, fix JSON typing errors (a boolean written as a string), add the total OUT parameter to the CPT expansion test now that CPT iteration is fixed, and add the missing flat-format expected response for search-expand-all-yesThis is preparatory for settling the SNOMED CT tests, and then it will be labelled as 2.0.0
valueset-unclosed on filter-based ECL expansions; and tests for enumerating grammar-based code systems (including count=0 counts)$compare operation (previously named $related)originMap (replacing sourceMap)child-of, and regex filters — including a regex denial-of-service case and improved regex error messages$expand: flat result format (response:flat) and support for the total OUT parameterdesignation.use.display in responsesCodeableConcept using the first matching code rather than the lastlimit replaced by count, bad cache-id)ValueSet.compose.include.version, with wildcards, and the expansion parameters system-version etc.)version parameter that is no longer used or supported (after 1 year of grace)hierarchyMeaning for the simple CodeSystemexpansion.id & expansion.offset in many testsvalueset-version to default-valueset-versiondisplayLanguagesystemVersion instead of versionx-caused-by-unknown-system when a supplement is not foundValueSet.compose.inactive and the activeOnly parameterThere is no specific history for the terminology test cases prior to version 1.6.0. The only history notes available are mixed in with all the other kinds of tests in the GitHub release notes.