This article is a follow-up to Test Automation in InterSystems Cache and Ensemble. An Ensemble production is a configuration of objects that interact with each other and perform different tasks. A typical HL7 production is composed of inbound services, message routing processes, transformations, and outbound operations.
Typically productions are tested manually by observing desired outcomes. However, manual tests do not exercise individual components of the system and do not lend themselves to automated regression testing. We at Atomic Object have had great success breaking up a production into its components and building automated functional and unit tests for these components.
A normal production has many configuration items that, in turn, have many different settings. These settings are very easy to configure and change through the Ensemble interface. This makes them that much more susceptible to accidental changes or temporary updates that never got reverted. Many of the inbound services and outbound operations are built-in Ensemble components that are constructed to be highly configurable. The behavior of these components are heavily influenced by their settings and makes testing the configuration of a production that much more important.
Luckily unit testing production settings is simple and easy. The configuration items and their settings are easily accessible. A simple assertion of each setting is all the effort required to provide significant test coverage for the production.
Message routers are normally used to send messages (typically HL7) to different transformations and outbound operations. A router is constructed with a set of rules that evaluate a message and send it somewhere depending on the value of a set of fields. If these routers are not tested properly, a message could be discarded or sent to the wrong transformation and operation. This can be especially disastrous since the message might contain important insurance or medical-related details.
In order to test a router, the production must be running and a request must be sent to it with a message. The result of where the message went can be looked up in a database log that details both where each message was sent and what rule or rules were exercised. Using the database log, we test the routers without needing to indirectly test or be bounded to the behavior of an operation or transformation. Testing against the log also makes our tests much more robust, since a change to a transformation or operation does not effect our tests.
A transformation, or DTL, is used to change a message into a format that is acceptable to the outbound operation or system. Transformations are defined in XML; the system creates new messages that are built from this definition. Internally, a DTL is a class that contains the XML transformation data and a method that can be invoked to perform the transformation.
Since DTLs do not rely on the production or any other components, they are easy to test in isolation. We broke our tests into small units that exercise individual parts of the transformation rather than the whole transformation. For instance, one test asserts that the “MSH” segment is copied over to the new message while another tests conditional statements that affect a different segment or field. In the end, the entire transformation is fully tested, but in consumable pieces that are more easily maintained than one monolithic transformation.
Function sets are used by message routers and have a significant part in determining where messages are routed. These functions are indirectly tested when the router is tested. A function set is a class that inherits from the function set base class and contains a set of class methods that are used by a message router. Since they are like other classes in the system, we test them no differently than any other class. Unit testing these function sets help us determine when a method is overly complex.
In summary, when testing Ensemble productions, we find them no different than desktop, web, or embedded applications. Breaking the production up into small, easily-consumed pieces makes automated testing straightforward.