| name | mii-testdata-contribution |
| description | Guide for contributing test data to the MII (Medizininformatik-Initiative) testdata repository. Use when adding new module test data, understanding testdata repository patterns, creating transaction bundles, or adapting existing module examples for the testdata repo. Triggers on requests like "add testdata for module X", "create test bundle", "contribute to mii-testdata", or "adapt examples for testdata repo". |
MII Testdata Contribution
Guide for contributing FHIR test data to the centralized MII testdata repository.
Repository Overview
Repository: https://github.com/medizininformatik-initiative/mii-testdata
Structure: kds-testdata/input/fsh/
Directory Structure
kds-testdata/input/fsh/
├── Bundle.fsh # Master bundle definitions + AddBundleEntry RuleSet
├── aliases.fsh # Shared aliases
├── test-data-label.fsh # TestDataLabel RuleSet
├── modul-{module-name}/ # Module-specific test data
│ ├── {Module}Aliases.fsh # Module-specific aliases
│ └── {ResourceType}.fsh # Instance definitions
Naming Convention
mii-exa-test-data-{module}-{resource-type}-{number}[-variant]
Examples:
mii-exa-test-data-patient-1
mii-exa-test-data-onko-diagnose-1
mii-exa-test-data-molgen-variante-1
Required RuleSets
TestDataLabel
All instances must include the HTEST security label:
* insert TestDataLabel
AddBundleEntry
For adding resources to transaction bundles:
* insert AddBundleEntry(mii-exa-test-data-{resource}-1, {ResourceType})
Transaction Bundle Pattern
Instance: mii-exa-test-data-bundle-{module}-{number}
InstanceOf: Bundle
Usage: #example
Description: "Bundle: {description}"
* insert TestDataLabel
* type = #transaction
* timestamp = "2025-01-03T10:00:00+01:00"
// Infrastructure resources first
* insert AddBundleEntry(mii-exa-test-data-patient-1, Patient)
* insert AddBundleEntry(mii-exa-test-data-organization-1, Organization)
// Then domain-specific resources
* insert AddBundleEntry(mii-exa-test-data-{module}-{resource}-1, {ResourceType})
Workflow: Adding Module Test Data
Phase 1: Build Coverage Index
Before creating test data, build an index of what needs coverage.
1.1 Extract MS Elements from Profiles
For each profile in the source module, extract Must-Support elements from the differential:
for sd in fsh-generated/resources/StructureDefinition-mii-pr-*.json; do
echo "=== $(basename $sd .json) ==="
jq -r '.differential.element[] | select(.mustSupport == true) | .path' "$sd"
done
Note: The differential only shows MS elements defined in this profile. Parent profiles (MII KDS base, German base profiles, FHIR core) may have additional MS elements, bindings, and cardinality constraints. These inherited constraints will surface when running SUSHI and the validator.
1.2 Map SearchParameters for MS Elements
Every Must-Support element must be searchable via a SearchParameter. Resolve SPs using this 4-level hierarchy (check in order, use the first match):
| Level | Source | Example |
|---|
| 1. FHIR R4 Base | Standard SPs defined in the FHIR spec | Patient.name, Condition.code |
| 2. MII Meta | Cross-module SPs from kerndatensatz-meta | Shared SPs across KDS modules |
| 3. Dependencies | SPs from referenced modules/packages | SPs from parent or related modules |
| 4. Module itself | Module-specific SPs for own elements | Custom SPs defined in the module |
If no SP exists at any level for an MS element, a new SP must be defined in the module itself.
Automated Analysis
Run the SP coverage analysis script to automatically resolve the full 4-level hierarchy:
scripts/analyze-sp-coverage.sh /path/to/module
OUTPUT_FORMAT=json scripts/analyze-sp-coverage.sh /path/to/module
VERBOSE=1 scripts/analyze-sp-coverage.sh /path/to/module
The script is located at mii-kerndatensatz-dev/scripts/analyze-sp-coverage.sh and produces:
- Coverage summary (total MS elements, covered, uncovered, %)
- Per-element SP mapping with source level
- Slice discriminator analysis
- Profile identification check
Slice-Discriminator Requirements
Sliced MS elements (e.g., code.coding:icd10-gm) require a discriminator-aware SearchParameter — a generic SP on the parent path (e.g., code) is not sufficient. The SP expression must contain the discriminator value:
# Generic SP (NOT sufficient for slices):
Condition.code
# Discriminator-aware SP (required for slices):
Condition.code.coding.where(system='http://fhir.de/CodeSystem/bfarm/icd-10-gm')
Profile Identification Requirement
Each profile must have at least one SearchParameter that uniquely identifies resources of this profile type. Candidates are elements with:
fixedValue or patternValue with min >= 1
- Required ValueSet binding with
min >= 1
meta.profile alone is not sufficient — it is not reliably populated in all systems.
1.3 Create Coverage Tracking Table
Run the automated analysis or create a tracking table manually:
| Profile | MS Element | SearchParam | SP Source | Instance | Status |
|---------|------------|-------------|-----------|----------|--------|
| MII_PR_Onko_Diagnose | code.coding:icd10-gm | condition-code-icd10gm | Dep: Diagnose | -1 | pending |
| MII_PR_Onko_Diagnose | subject | patient | FHIR R4 | -1 | pending |
| MII_PR_Onko_TNM_Klassifikation | component:TNM-T | tnm-t | Module | -1 | pending |
Important: Every MS element row must have a SearchParam and SP Source filled in. If a cell is empty, resolve the SP or create a new one before proceeding.
Phase 2: Create Test Data
- Create branch:
git checkout -b feature/add-{module}-testdata
- Add dependency to
sushi-config.yaml:
dependencies:
de.medizininformatikinitiative.kerndatensatz.{module}: {version}
- Create module directory:
mkdir -p kds-testdata/input/fsh/modul-{module}
- Create aliases file with module-specific CodeSystems/ValueSets
- Create instance files - populate MS elements, update tracking table
- Create transaction bundle that includes all instances
Phase 3: Verify and Submit
- Run SUSHI:
cd kds-testdata && sushi .
- Review coverage table - ensure all MS elements and SearchParams covered
- Submit PR - CI/CD pipeline runs FHIR Validator
Adapting Existing Module Examples
When the source module already has examples (mii-exa-* instances):
- Analyze existing examples: Check profile coverage against MS index
- Adapt naming:
mii-exa-{module}-{name} → mii-exa-test-data-{module}-{name}-1
- Add TestDataLabel: Insert
* insert TestDataLabel
- Update references: Point to testdata instances
- Fill gaps: Create new instances for uncovered MS elements
Coverage Requirements
| Requirement | Description |
|---|
| Profile Coverage | At least one instance per published profile |
| MS Element Coverage | Every MS element populated in at least one instance |
| SearchParam Coverage | Every MS element must have a SearchParameter (from FHIR R4, MII Meta, Dependencies, or Module). Every SP's target path must be populated in test data. |
| Slice SP Coverage | Sliced MS elements require a discriminator-aware SP (with .where(system='...')) — a generic SP is not sufficient. |
| Profile Identification | Each profile must have at least one SP that uniquely identifies its resources (via fixed/pattern values or required bindings). meta.profile alone is not sufficient. |
| Reference Integrity | All references resolve within the bundle |
SearchParameter Type Requirements
| Type | Test Data Requirement |
|---|
token | Populate code + system in coding element |
reference | Include referenced resource in bundle |
date | Use valid FHIR date format |
string | Populate with searchable text |
quantity | Include value + unit + system |
composite | All component elements in same instance |
Common Issues
Alias Conflicts
Check aliases.fsh before adding new aliases to avoid redefinition errors.
Reference Resolution
All referenced resources must exist in the bundle. Use consistent instance IDs.
Invariant Satisfaction
Some profiles have invariants requiring specific data patterns. Create multiple instances if needed to satisfy conflicting invariant paths.
Local Validation
Run SUSHI locally before submitting PR:
cd kds-testdata
sushi .
FHIR Validator runs automatically in CI/CD pipeline after PR submission.