Key Factors of Testability
This page outlines the theory behind the key factors that define the testability quality criterion and details how the Menditect Testability Framework implements them. Testability is formally recognized as a subcharacteristic of Maintainability within the ISO/IEC 25010 standard.
1. The Key Factors
Testability is not an isolated quality characteristic, but is closely linked to several other quality criteria:
- Observability: This is the ability to understand a system’s internal state by looking at its external outputs. It requires clear logging, good diagnostic tools, and consistent outputs for specific inputs. If outputs that provide insight into the internal state are not available, testing becomes very difficult.
- Controllability: This refers to the ability to easily manipulate a system's state and inputs for testing purposes. It means you can set up specific test conditions and isolate different sections of the application to test them independently.
- Simplicity: This measures the overall complexity of a system. Code that is simpler and more modular is easier to understand, test, and debug. High complexity tends to hide defects, making them harder to isolate and resolve
- Isolatability: This is the capacity to test individual components or modules separately from the rest of the application. It is a fundamental characteristic of good design and is essential for efficient unit and integration testing
- Documentation: Good documentation is essential for maintainability, informing both the developer and the user.
2. Implementing Observability
Most observability requirements, such as logging, diagnostics, and error message handling, are provided by the Mendix platform.
Menditect enhanced this by introducing the TestLogger component. This component provides a probe that records the execution path, allowing testers to determine which sequence of code the application has taken.
3. Implementing Controllability
Controllability strongly depends on the degree to which system components can operate independently, as described by the “Isolatability” factor.
Mendix Test Automation (MTA) makes it possible to create, modify, and remove test data directly in the database and can even bypass the applied domain model access rights in case this is required to prepare or cleanup test data. This precise data handling supports the testing of isolated parts of the application. However, even with automation, clear principles for data management and the use of input parameters remain essential for achieving good controllability within the application.
4. Implementing Simplicity
A simpler system requires fewer paths and variables to consider, making it inherently easier to test. Simplicity is achieved through:
- Modular Design: Breaking the system into small, independent, and loosely coupled components. A component is easier to understand and test in isolation when it has a single, well-defined purpose.
- Low Cyclomatic Complexity: This metric measures the number of independent paths through the code. Lower complexity means fewer test cases are required for comprehensive coverage.
- Minimal Features: Sticking to the core functionality required to meet the business needs, as unnecessary features add complexity and new points of failure that must be tested.
Mendix's visual language can encourage the creation of long, complex microflows. Developers should consciously break these down into smaller, simpler, and reusable sub-microflows to reduce complexity and increase modularity. Guidelines for splitting microflows can be found in the sections covering Microflow typologies and Testable app architecture.
5. Implementing Isolatability
Isolatability is achieved through two core principles: Dependency Injection (DI) and clear Separation of Concerns (SoC). The Menditect framework implements these as follows:
- Dependency Injection (DI): In Mendix, DI is applied by ensuring that a component receives its required data (objects or literals) externally, rather than creating or retrieving them itself. The framework shifts the responsibility for data retrieval to the calling microflows. This results in microflows receiving their required objects as explicit parameters, making them independent and highly testable. (Read more about DI: Wikipedia: Dependency Injection)
- Separation of Concerns (SoC): This is implemented through Microflow Typologies and a Testable App Architecture. By using a consistent naming convention (e.g.,
ACT,ORC,OPR), each microflow is assigned a specific, isolated role, ensuring clear separation.
If an operation microflow needs to update an associated Order, the calling Orchestration microflow should execute the necessary GET microflow (e.g., GET_M_order_by_orderline) to retrieve the Order first, and then pass the retrieved Order object as an explicit parameter to the operation microflow. This makes the operation microflow independent of the data retrieval process.
6. Adding Documentation
The inclusion of documentation within the Mendix model is a crucial factor that enhances the entire system's testability. Good documentation provides a clear understanding of the system’s expected behavior and increases accessibility. It improves:
- Observability by improving knowledge about what to look for in logs and understanding system outputs.
- Controllability by providing clear instructions on how to set up specific test environments and mock external dependencies.
- Simplicity and Isolatability by helping developers understand the system's architecture, features, and data structure.