Test Suite: EHR_SERVICE / I_COMPOSITION Interface

Normative Reference

Items in this validation suite conceptually use the following abstract interfaces from the Abstract Platform Service Model, EHR/COMPOSITION component.

  • I_EHR_COMPOSITION

These are concretely realised in implementation technology specfic APIs, such as the EHR REST API.

This test suite uses artefacts defined by the following information model specifications:

Dependencies

This test suite depends on other test suites:

Test Environment

  1. The server under test should support at least OPTs, 1.4 or 2, but OPT 1.4 if more frequent since modeling tools supporting this were around for a long time. Could also support ADL, 1.4 or 2.

  2. The server should support at least one of the XML or JSON representations of COMPOSITIONs for committing data, and integrate the corresponding schemas (XML or JSON) to validate data syntactically (before validating against an OPT).

Test Cases

Service Model operation: I_EHR_COMPOSITION.has_composition()

Service Model reference: I_EHR_COMPOSITION.has_composition()

Test Case I_EHR_COMPOSITION.has_composition

Description

Has existing COMPOSITION

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR has a CONTRIBUTION

  3. The CONTRIBUTION contains a VERSION with known uid.

Post-conditions

None

Flow

  1. Invoke the has COMPOSITION service for the ehr_id and VERSION.uid

  2. The result must be TRUE

Test runners

Test Case I_EHR_COMPOSITION.has_composition-bad_composition

Description

Has COMPOSITION, COMPOSITION doesn’t exist

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR has no CONTRIBUTIONs

Post-conditions

None

Flow

  1. Invoke the has COMPOSITION service for ehr_id, and a random VERSION.uid

  2. The result must be FALSE

Test runners

Test Case I_EHR_COMPOSITION.has_composition-bad_ehr

Description

Has COMPOSITION on non-existent EHR

Pre-conditions

  1. There are no EHRs on the server

Post-conditions

None

Flow

  1. Invoke the has COMPOSITION service with a random ehr_id

  2. The service should return an error related to the non existence of the EHR

Test runners

Get COMPOSITION latest

Implementation consideration:

When a COMPOSITION is retrieved from a service, it will comply with a specific format. There could be a variant for each test to retrieve the COMPOSITION in any of the supported openEHR formats, and the syntactic validation of those retrieved formats should be done by using the corresponding schemas (XML, JSON, etc). That would be the minimal validation for conformance testing. Though it would be ideal to have semantic validation of the retrieved COMPOSITIONs to ensure conformance, which is achieved by validating against the corresponding OPT in the testing layer.

Test Case I_EHR_COMPOSITION.get_composition_latest

Description

Get existing COMPOSITION latest

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR has a VERSIONED_COMPOSITION with known uid

  3. The VERSIONED_COMPOSITION has two VERSIONs

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION latest service for the ehr_id and VERSIONED_COMPOSITION uid

  2. The result must return the COMPOSITION contents, and should be the latest version

  3. The retrieved format should contain all the exact same data as the format used when committing the COMPOSITION (content check)

Test runners

Test Case I_EHR_COMPOSITION.get_composition_latest-bad_composition

Description

Get COMPOSITION latest, COMPOSITION doesn’t exist

Pre-conditions

  1. An EHR with known ehr_id exists and has no CONTRIBUTIONs

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION latest service for ehr_uid, and a random VERSIONED_COMPOSITION uid

  2. The result must be empty, with an error “the COMPOSITION uid doesn’t exist in the EHR ehr_uid”

Test runners

Test Case I_EHR_COMPOSITION.get_composition_latest-bad_ehr

Description

Get COMPOSITION latest on non-existent EHR

Pre-conditions

  1. There are no EHRs on the server

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION latest service with a random ehr_id, and a random VERSIONED_COMPOSITION uid

  2. The service should return an error related to the non existence of the EHR

Test runners

Get COMPOSITION at time

Test Case I_EHR_COMPOSITION.get_composition_at_time

Description

Get existing COMPOSITION at time

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR has one or more VERSIONED_COMPOSITIONs with known uids

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at time service for the ehr_id, VERSIONED_COMPOSITION.uid and current time

  2. The result must return the COMPOSITION contents of the existing COMPOSITION at given time

  3. The retrieved format should contain all the exact same data as the format used when committing the COMPOSITION (content check)

    NOTE: When requesting a `COMPOSITION` at time using the current time, the last version of the matching composition, if it exists, should be retrieved.

Test runners

Test Case I_EHR_COMPOSITION.get_composition_at_time-no_time_arg

Description

Get existing COMPOSITION at time, without a given time

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR has one or more VERSIONED_COMPOSITIONs with known uids

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at time service for the ehr_id, VERSIONED_COMPOSITION uid and no time

  2. The result must return the COMPOSITION contents of the existing COMPOSITION, and should be the latest VERSION of the COMPOSITION

  3. The retrieved format should contain all the exact same data as the format used when committing the COMPOSITION (content check)

    NOTE: Test this using `COMPOSITIONs` with one version and multiple versions, to be sure the retrieved one is the latest; +
    The previous tests for "`get COMPOSITION latest`" could be used to compare results.

Test runners

Test Case I_EHR_COMPOSITION.get_composition_at_time-bad_composition

Description

Get COMPOSITION at time, COMPOSITION doesn’t exist

Pre-conditions

  1. An EHR with known ehr_id exists and has no CONTRIBUTIONs

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at time service for ehr_uid, and a random VERSIONED_COMPOSITION.uid and current time

  2. The result must be empty, with an error related to “the COMPOSITION uid doesn’t exist in the EHR ehr_uid”

Test runners

Test Case I_EHR_COMPOSITION.get_composition_at_time-bad_ehr

Description

Get COMPOSITION at time on non-existent EHR

Pre-conditions

  1. There are no EHRs on the server

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at time service with a random ehr_id, random VERSIONED_OBJECT.uid and current time

  2. The service should return an error indicating non-existence of the EHR

Test runners

Test Case I_EHR_COMPOSITION.get_composition_at_times

Description

Get existing COMPOSITION at time, cover different times

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR should have one VERSIONED_COMPOSITION with a know uid

  3. The VERSIONED_COMPOSITION should have two VERSIONs (the EHR has two CONTRIBUTIONs for the same COMPOSITION)

  4. CONTRIBUTIONs were done at times t0 and t1 with t0 < t1

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at time service for the ehr_id, VERSIONED_COMPOSITION uid and a time < t0

  2. The result must be negative and return an error related to the COMPOSITION not existing at that time

  3. Invoke the get COMPOSITION at time service for the ehr_id, VERSIONED_COMPOSITION uid and a time > t0 and < t1

  4. The result must return the COMPOSITION contents of the COMPOSITION committed in t0

  5. The retrieved format should contain all the exact same data as the format used when committing the COMPOSITION (content check)

  6. Invoke the get COMPOSITION at time service for the ehr_id, VERSIONED_COMPOSITION uid and a time > t1

  7. The result must return the COMPOSITION contents of the COMPOSITION committed in t1

  8. The retrieved format should contain all the exact same data as the format used when committing the COMPOSITION (content check)

Test runners

Get COMPOSITION at version

Test Case I_EHR_COMPOSITION.get_composition_version

Description

Get existing COMPOSITION at version

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR has one VERSION with known version id

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at version service for the ehr_id, VERSION version id

  2. The result must return the COMPOSITION contents of the existing VERSION

  3. The retrieved format should contain all the exact same data as the format used when committing the COMPOSITION (content check)

Test runners

Test Case I_EHR_COMPOSITION.get_composition_version-bad_version

Description

Get COMPOSITION at version, VERSION doesn’t exist

Pre-conditions

  1. An EHR with known ehr_id exists and doesn’t have any commits

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at version service for the ehr_id, and a random version id

  2. The result must be negative and return an error related to the non-existent COMPOSITION with the version id

Test runners

Test Case I_EHR_COMPOSITION.get_composition_version-bad_ehr

Description

Get COMPOSITION at version, EHR doesn’t exist

Pre-conditions

  1. The system doesn’t have any EHRs

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at version service a random ehr_id and random version id

  2. The result must be negative and return an error related to the non-existent EHR.

Test runners

Test Case I_EHR_COMPOSITION.get_composition_versions

Description

Get COMPOSITION at version, cover different versions

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR should have one VERSIONED_COMPOSITION with a known uid

  3. The VERSIONED_COMPOSITION should have two VERSIONs (the EHR has two CONTRIBUTIONs for the same COMPOSITION)

  4. Both VERSIONs have ids: v1 and v2

Post-conditions

None

Flow

  1. Invoke the get COMPOSITION at version service, for the ehr_id and VERSION version id v1

  2. The result must be positive and retrieve the COMPOSITION, that should match the COMPOSITION created with version id v1. (content check).

  3. Invoke the get COMPOSITION at version service, for the ehr_id and VERSION version id v2

  4. The result must be positive and retrieve the COMPOSITION, that should match the COMPOSITION created with version id v2 (content check).

Test runners

Get VERSIONED COMPOSITION

Test Case I_EHR_COMPOSITION.get_versioned_composition

Description

Get existing VERSIONED_COMPOSITION

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR has one VERSIONED_COMPOSITION with known uid

Post-conditions

None

Flow

  1. Invoke the get VERSIONED_COMPOSITION service for the ehr_id and VERSIONED_COMPOSITION uid

  2. The result must return a valid VERSIONED_COMPOSITION object, referencing the VERSION it contains

Test runners

To consider different cases, try with VERSIONED_COMPOSITION that contain just one VERSION or many VERSIONs
For that, the valid test cases for Create COMPOSITION could be used to comply with the preconditions of this test flow

Test Case I_EHR_COMPOSITION.get_versioned_composition-non_existent

Description

Get non-existent VERSIONED_COMPOSITION

Pre-conditions

  1. An EHR with known ehr_id exists

  2. The EHR doesn’t have any commits

Post-conditions

None

Flow

  1. Invoke the get VERSIONED_COMPOSITION service for the ehr_id and a random VERSIONED_COMPOSITION uid

  2. The result must be negative and return an error related to the non-existence of the VERSIONED_COMPOSITION

Test runners

Test Case I_EHR_COMPOSITION.get_versioned_composition-bad_ehr

Description

Get VERSIONED_COMPOSITION, EHR doesn’t exist

Pre-conditions

  1. The system doesn’t have any EHRs

Post-conditions

None

Flow

  1. Invoke the get VERSIONED_COMPOSITION service for a random ehr_id and a random VERSIONED_COMPOSITION uid

  2. The result must be negative and return an error related to the non-existence of the EHR

Test runners

Create COMPOSITION

Service Model reference: I_EHR_COMPOSITION.create_composition()

Test Case I_EHR_COMPOSITION.create_composition-event

Description

Create new event COMPOSITION

Pre-conditions

  1. The OPT, associated with the event COMPOSITION that will be created, should exist on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

A new event COMPOSITION exists in the EHR.

Flow

  1. Invoke the create COMPOSITION service with a valid event COMPOSITION, compliant with the existing OPT, and with the known ehr_id

  2. The result should be positive, return information about the new COMPOSITION added to the EHR, and the version number should be 1

Test runners

Test Case I_EHR_COMPOSITION.create_composition-persistent

Description

Create new persistent COMPOSITION

Pre-conditions

  1. The OPT, associated with the persistent COMPOSITION that will be created, should exist on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

A new persistent COMPOSITION exists in the EHR.

Flow

  1. Invoke the create COMPOSITION service with a valid persistent COMPOSITION, compliant with the existing OPT, and the known ehr_id

  2. The result should be positive, and return information about the new COMPOSITION added to the EHR, and the version number should be 1

Test runners

Test Case I_EHR_COMPOSITION.create_composition-same_opt_twice

Description

Create persistent COMPOSITION for the same OPT twice

Pre-conditions

  1. The OPT, associated with the persistent COMPOSITION that will be created, should exist on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

A new persistent COMPOSITION exists in the EHR.

Flow

  1. Invoke the create COMPOSITION service with a valid persistent COMPOSITION, compliant with the existing OPT, and with the known ehr_id

  2. The result should be positive, and return information about the new COMPOSITION added to the EHR, and the version number should be 1

  3. Invoke the create COMPOSITION service with a valid persistent COMPOSITION and the same ehr_id as in 1., the COMPOSITION should comply with the same persistent OPT as the COMPOSITION in 1

  4. The result should be negative, returning an error related to trying to create a persistent COMPOSITION for the same persistent OPT that already has a first version

Test runners

Notes:

  1. Current criteria is: only one ‘create’ operation is allowed for persistent COMPOSITIONs, the next operations over an existing persistent COMPOSITION should be ‘modifications’.

  2. This is under debate in the openEHR SEC since some implementations permit 'persistent' COMPOSIITONS to have more than one instance in the same EHR and some others not. This is due to the lack of information in the openEHR specifications. There is also a discussion to define other types of categories for COMPOSITIONs to allow different behaviors.

Test Case I_EHR_COMPOSITION.create_composition-invalid_event

Description

Create new invalid event COMPOSITION

Pre-conditions

  1. The OPT, associated with the event COMPOSITION that will be created, should exist on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

None

Flow

  1. Invoke the create COMPOSITION service with an invalid event COMPOSITION and the known ehr_id

  2. The result should be negative, and return information about the errors in the provided COMPOSITION

Test runners

Test Case I_EHR_COMPOSITION.create_composition-invalid_persistent

Description

Create new invalid persistent COMPOSITION

Pre-conditions

  1. The OPT, associated with the persistent COMPOSITION that will be created, should exist on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

None

Flow

  1. Invoke the create COMPOSITION service with an invalid persistent COMPOSITION and the known ehr_id

  2. The result should be negative, and return information about the errors in the provided COMPOSITION

Test runners

Test Case I_EHR_COMPOSITION.create_composition-event_bad_opt

Description

Create new event COMPOSITION, referenced OPT doesn’t exist

Pre-conditions

  1. The OPT, referenced by the COMPOSITION to commit, doesn’t exist on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

None

Flow

  1. Invoke the create COMPOSITION service with a valid event COMPOSITION and the known ehr_id

    1. The COMPOSITION should reference an OPT that doesn’t exist on the server

  2. The result should be negative, and return information about the non-existent OPT

Test runners

Test Case I_EHR_COMPOSITION.create_composition-event_bad_ehr

Description

Create new event COMPOSITION, EHR doesn’t exist

Pre-conditions

  1. The OPT, referenced by the COMPOSITION to commit, exists on the server

  2. The server doesn’t have any EHRs

Post-conditions

None

Flow

  1. Invoke the create COMPOSITION service with a valid event COMPOSITION and a random ehr_id

  2. The result should be negative, and return information about the non-existent EHR

Test runners

Update COMPOSITION

The update COMPOSITION service needs the VERSION.preceding_version_uid attribute to be set, so the server knows which existing VERSION of the COMPOSITION will be associated with the newly committed COMPOSITION. The Service Model spec is not clear about where that attribute is defined. By taking into account the Reference Model, the COMPOSITION doesn’t contain that value but the VERSION does. For the COMPOSITION update service the preceding_version_uid should be a parameter or the definition in the SM should mention this.

Service Model reference: I_EHR_COMPOSITION.update_composition()

Test Case I_EHR_COMPOSITION.update_composition-event

Description

Update an existing event COMPOSITION

Pre-conditions

  1. The OPT referenced by the COMPOSITIONs to commit exists on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

  1. A new VERSIONED_OBJECT exists on the server

  2. The VERSIONED_OBJECT has two VERSIONs of COMPOSITION

  3. One VERSION.commit_audit.change_type is CREATE, the other one is MODIFY

Flow

  1. Invoke the create COMPOSITION service with a valid event COMPOSITION and the existing ehr_id

    1. The COMPOSITION reference the existing OPT

  2. The result should be positive and a new COMPOSITION should exist in the EHR

  3. Invoke the update COMPOSITION service with a valid event COMPOSITION to the existing ehr_id and preceding_version_uid should be the version uid from the COMPOSITION created in 1

    1. This COMPOSITION has the same OPT as the COMPOSITION created in 1

  4. The result should be positive and a new version of the existing COMPOSITION should exist in the EHR

Test runners

Test Case I_EHR_COMPOSITION.update_composition-persistent

Description

Update an existing persistent COMPOSITION

Pre-conditions

  1. The OPT referenced by the COMPOSITIONs to commit exists on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

  1. The server should contain one VERSIONED_OBJECT

  2. The VERSIONED_OBJECT should have two VERSIONs of COMPOSITION

  3. The COMPOSITIONs should comply with the existing OPT

Flow

  1. Invoke the create COMPOSITION service with a valid persistent COMPOSITION and the existing ehr_id

    1. The OPT referenced by this COMPOSITION exists on the server

  2. The result should be positive and a new COMPOSITION should exist in the EHR

  3. Invoke the update COMPOSITION service with a valid persistent COMPOSITION, to the existing ehr_id

    1. that has the same template as the COMPOSITION created in 1.,

    2. preceding_version_uid should be the VERSION.uid from the COMPOSITION created in 1

  4. The result should be positive and a new version of the existing COMPOSITION should exist in the EHR

Test runners

Test Case I_EHR_COMPOSITION.update_composition-non_existent

Description

Update a non-existing COMPOSITION

Pre-conditions

  1. The OPT referenced by the COMPOSITIONs to commit exists on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

None

Flow

  1. Invoke the update COMPOSITION service with a valid event COMPOSITION, the existing ehr_id and preceding_version_uid should be a random value

    1. The COMPOSITION should comply with the existing OPT

  2. The result should be negative and return an error related to the non-existence of the preceding_version_id

Test runners

Test Case I_EHR_COMPOSITION.update_composition-wrong_template

Description

Update an existing COMPOSITION, referencing a different template

Pre-conditions

  1. The OPTs, referenced by the COMPOSITIONs to commit, exist on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

  1. The server has a new VERSIONED_OBJECT

  2. The VERSIONED_OBJECT has one version of a COMPOSITION

Flow

  1. Invoke the create COMPOSITION service with a valid event COMPOSITION and the existing ehr_id

    1. The OPT referenced by this COMPOSITION exists on the server

  2. The result should be positive and a new COMPOSITION should exist in the EHR

  3. Invoke the update COMPOSITION service with a valid event COMPOSITION, to the existing ehr_id and preceding_version_uid should be the version uid from the COMPOSITION created in 1

    1. The COMPOSITION references a different template than the one referenced by the COMPOSITION created in 1.

    2. The OPT referenced by this COMPOSITION exists on the server

  4. The result should be negative and return an error related to the template_id mismatch

Test runners

Delete COMPOSITION

Service Model reference: I_EHR_COMPOSITION.delete_composition()

Test Case I_EHR_COMPOSITION.delete_composition-event

Description

Delete event COMPOSITION

Pre-conditions

  1. The OPT referenced by the COMPOSITIONs to commit exists on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

  1. The server has one VERSIONED_OBJECT

  2. The VERSIONED_OBJECT contains two versions of COMPOSITION

  3. The second VERSION.lifecycle_state value is the code `openehr::523

deleted

`

Flow

  1. Invoke the create COMPOSITION service with a valid event COMPOSITION and the existing ehr_id

    1. The COMPOSITION complies with the existing OPT

  2. The result should be positive and a new COMPOSITION should exist in the EHR

  3. Invoke the delete COMPOSITION service with the existing ehr_id and preceding_version_uid should be the version id of the COMPOSITION created in 1

  4. The result should be positive, and the COMPOSITION should be deleted

Test runners

The common implementation of the delete operation is two create a new VERSION of the COMPOSITION that has VERSION.commit_audit.change_type = openehr::523|deleted|, and VERSION.lifecycle_state = openehr::523|deleted|. So the delete operation is not a physical delete but a logical delete. Some implementations might add the option of a physical deleted. This test case considers the postcondition to be a logical delete, which behaves like an update operation in which a new VERSION of an existing COMPOSITION is created.

Test Case I_EHR_COMPOSITION.delete_composition-persistent

Description

Delete persistent COMPOSITION

Pre-conditions

  1. The OPT referenced by the COMPOSITIONs to commit exists on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

  1. The server has one VERSIONED_OBJECT

  2. The VERSIONED_OBJECT contains two versions of COMPOSITION

  3. The second VERSION.lifecycle_state value is the code `openehr::523

deleted

`

Flow

  1. Invoke the create COMPOSITION service with a valid persistent COMPOSITION and the existing ehr_id

    1. The COMPOSITION complies with the existing OPT

  2. The result should be positive and a new COMPOSITION should exist in the EHR

  3. Invoke the delete COMPOSITION service with the existing ehr_id and preceding_version_uid should be the version id of the COMPOSITION created in 1

  4. The result should be positive, and the COMPOSITION should be deleted

Test runners

Test Case I_EHR_COMPOSITION.delete_composition-non_existent

Description

Delete persistent COMPOSITION

Pre-conditions

  1. The OPT referenced by the COMPOSITIONs to commit exists on the server

  2. An EHR with known ehr_id should exist

  3. The EHR should have no commits

Post-conditions

None

Flow

  1. Invoke the delete COMPOSITION service with the existing ehr_id and a random preceding_version_uid

  2. The result should be negative and return an error related to the non-existent COMPOSITION

Test runners