On this page ...

Finishing the Test

All basic building blocks for the interpreter have been implemented. What’s left is to combine the information and present it to the user.

Evaluation of TestFlow

Every TestFlow consists of a series of steps, where the page that is the result of a previous step should equal the fromPage of the next. In the following code we loop over the steps, remember the evaluation result from the previous step, and compare it to the fromPage of the current step. If there’s an error, we create a readable message that will be shown to the user.

// EducationInterpreter/src/custom/interpreter/EducationInterpreter.ts#L84-L107

override evalTestFlow(node: TestFlow, ctx: InterpreterContext): RtObject {
    console.log("Evaluating Test Flow " + node.freId() + "  steps " + node.steps?.length)
    let previousPage: RtPage = undefined
    let previousStep: Step
    let first: boolean = true      // indicates whether there is a calculated value for 'previous'
    for (const step of node.steps) {
        // Compare the fromPage with the previous stepResult
        if (!first && previousPage.page !== step.$fromPage) {
            // There was an error. Based on the given answers, we should not be on 'fromPage'.
            return new RtError(`Next page of step ${EducationEnvironment.getInstance().writer.writeToLines(previousStep)} should be ${previousPage.page.name}, not ${step.$fromPage.name}.`)
        }
        const stepResult = main.evaluate(step, ctx)
        if (isRtPage(stepResult) ) {
            // Remember the previous stepResult
            previousPage = stepResult
            previousStep = step
            first = false
        }
        if (isRtError(stepResult)) {
            return stepResult
        }
    }
    return RtBoolean.TRUE
}

Evaluation of Scenario and Test

The evaluation of Scenario is straightforward: loop over all test flows and return false if any produces an error.

// EducationInterpreter/src/custom/interpreter/EducationInterpreter.ts#L70-L82

override evalScenario(node: Scenario, ctx: InterpreterContext): RtObject {
    console.log("Evaluating Scenario " + node.description + "  testFlow " + node.testFlow?.length)
    for (const testFlow of node.testFlow) {
        const stepFlowResult = main.evaluate(testFlow, ctx)
        if (isRtBoolean(stepFlowResult) && stepFlowResult.asBoolean() === false) {
            return RtBoolean.FALSE
        }
        if (isRtError(stepFlowResult)) {
            return stepFlowResult
        }
    }
    return RtBoolean.TRUE
}

In the final evaluation function, evalTest, we also add the flow to the context under CURRENT_FLOW. The rest mirrors the evalScenario logic.

// EducationInterpreter/src/custom/interpreter/EducationInterpreter.ts#L52-L68

override evalTest(node: Test, ctx: InterpreterContext): RtObject {
    console.log("Evaluating Scenario " + node.freId() + "  flow " + node.flow.referred?.name)
    // Puts the current flow in the context
    const newCtx = new InterpreterContext(ctx)
    const flow = new RtFlow(node.flow.referred)
    newCtx.set("CURRENT_FLOW", flow)
    for (const s of node.scenarios) {
        const scenarioResult = main.evaluate(s, newCtx)
        if (isRtBoolean(scenarioResult) && scenarioResult.asBoolean() === false) {
            return RtBoolean.FALSE
        }
        if (isRtError(scenarioResult)) {
            return scenarioResult
        }
    }
    return RtBoolean.TRUE
}

The Result

Running the interpreter on the complete TestB model unit from our model (named Model4Interpreter) results in this error:

Image 'examples/Interpreter/Interpreter-result.png' seems to be missing
Figure 1. The result of the interpreter showing an error
© 2018 - 2025 Freon contributors - Freon is open source under the MIT License.