Testing and Simulation in the Jeppesen Studio
Developing rules for combinatorial optimization carries high risk; a single misclassified rule (e.g., misclassifying an Illegal Subchain Rule as a Final Rule) can cause the optimizer to drop valid solutions or explore dead-end subtrees infinitely.
To mitigate this, the Jeppesen ecosystem provides powerful Integrated Development Environment (IDE) tooling, including interactive interpreters and simulators.
1. The In-IDE Interpreter and Simulator
Turnaround time for code generation and compilation can be slow. To allow domain experts and developers to experiment with models quickly, the ecosystem supports an in-IDE interpreter.
Features of the Simulator:
-
Interactive Stepping: Users can "play" with a program, stepping through it in single steps and watching values change dynamically.
-
Calculation Tree Expansion: Because declarative languages evaluate complex trees of dependencies, the debugger can "expand" the calculation tree so users can inspect all intermediate results.
-
Rapid Prototyping: This allows domain experts (who may not be deep programmers) to simulate programs, observe their progress, and stimulate them to see how they react to specific edge-case flight schedules.
2. Tabular Unit Testing
In addition to interactive simulation, the language supports automated testing. Test cases can be expressed in an Excel-like tabular notation.
| Test Case Name | Input (Flight Time) | Expected Result (Pay) | Actual Result | Status |
|---|---|---|---|---|
| Short Flight | 01:00 | 04:00 (Min Guar) | 04:00 | PASS |
| Long Flight | 09:00 | 09:00 | 09:00 | PASS |
-
Domain Expert Friendly: This tabular notation allows non-programmers (like insurance mathematicians or airline union reps) to specify test data for each input value of a rule.
-
Immediate Feedback: The rules are then evaluated by an interpreter, providing immediate visual feedback (e.g., coloring rows red or green) about incorrect rules.
-
Semantic Synchronization: During full production builds, these same unit tests are executed by the generated C/C++ code, expecting the exact same results as the interpreted version, ensuring semantic consistency across the execution engines.