Expression Rule Testing Functions

This page includes detailed information about the a!testRunStatusForId() and the a!testRunResultForId() functions, which can be used to query the status, or fetch the results of an expression rule test run. For information on starting a test run, see a!startRuleTestsAll() and - a!startRuleTestsApplications().

Common Uses

The following examples represent some common uses of the a!testRunStatusForId() and a!testRunResultForId() functions.

Integrating with an external system

Running expression rule tests from an external systems can be accomplished by creating web APIs that use expression rule testing functions and smart services in them.

The first web API should start the test exectution by using either the a!startRuleTestsAll() or the - a!startRuleTestsApplications() smart services. The second web API should query the status of a test run by using the a!testRunStatusForId(). Finally, the third web API should fetch the results of the test by using the a!testRunResultForId() function.

Once these web APIs are created, they can then be called from the external system.

The following example shows a writeable web API (i.e. HTTP Method: POST) that start the test run and return the test-run ID (i.e. fv!testRunId) which can then be used by the external system to query the status and/or fetch the test results.

a!startRuleTestsAll(
   onSuccess: a!httpResponse(
    statusCode: 200,
    body: fv!testRunId
  ),
  onError: a!httpResponse(
    statusCode: 500,
    body: "An error occurred when calling a!startRuleTestsAll" 
  )
)
  • Use the - a!startRuleTestsApplications() smart service instead, if you want to start a test on expression rules that belong to specific applications.
  • Writeable web APIs require you to set the HTTP Method to POST.

Assuming the writeable API listed above has been created, you would then create another web API similar to the one shown below to query the status of the test run. In this example, this web API receives a testRunId parameter (http!request.queryParameters.testRunId), and returns a text representing the status of the test run. This web API may have to be invoked more than once, until the status of the test run is COMPLETE.

a!httpResponse(
  statusCode: 200,
  headers: {},
  body:
    a!testRunStatusForId(http!request.queryParameters.testRunId)
)

Once the status returned by the previous web API is COMPLETE, you can get the entire result set by using the web API below. In this example, the test results are transformed to xml using the toxml() function so the external system can parse the test results.

a!httpResponse(
  statusCode: 200,
  headers: {},
  body: toxml(
    a!testRunResultForId(http!request.queryParameters.testRunId)
    )
)

See Running Automated Tests on Expression Rules from Jenkins for step-by-step instructions on how to integrate expression rule testing with Jenkins.

Using test results in a SAIL interface

If you don't want to use an external system to perform automated testing, you can alternatively use Appian forms and reports. Both have the capability of running tests and displaying the results in drillable grids and graphs.

The following example allows designers to run a test on all expression rules in an Appian system, or an application; and display the results of a test run as the test executes, or once it is finished.

The interface provides the following fields and buttons to provide the functionality described above.

Buttons

  • Run System Test: Calls the a!startRuleTestsAll() smart service and stores the test-run ID in the local!testRunId variable, which is then displayed in the Test-run ID field.
  • Run App Test: Calls the - a!startRuleTestsApplications() smart service and stores the test-run ID in the local!testRunId variable, which is then displayed in the Test-run ID field.
  • Refresh: Calls the a!testRunStatusForId() function by passing the local!testRunId variable and saving the result in the local!testStatus variable, which is then displayed in the Status field.

  • This example requires you to create a new constant of type application named TEST_APPLICATIONS to run a test on select applications.

  • Every time the interface is re-loaded, the a!testRunResultForId() function is called to obtain test results, which can be used to update the corresponding fields and the pie chart in this interface.

The following screenshot shows what this sample SAIL interface looks like. Copy and paste an example into a new interface to see how this works.

=load(
  local!testRunId,
  local!error,
  local!testStatus,
  local!isAppTest,
  with(
    local!testRunResults: if(
      isnull(local!testRunId), 
      null, 
      a!testRunResultForId(local!testRunId)
    ),
    a!dashboardLayout(
      contents: {
        a!buttonLayout(
          secondaryButtons: {
            a!buttonWidget(
              label: "Run System Test",
              value: local!testRunId,
              saveInto: {
                a!startRuleTestsAll(
                  onSuccess: {
                    a!save(local!testRunId, fv!testRunId)
                  },
                  onError: {
                    a!save(local!error, "Could not execute test.")
                  }
                ),
                a!save(local!isAppTest, false)
              }
            ),
            a!buttonWidget(
              label: "Run App Test",
              value: local!testRunId,
              saveInto: {
                  a!startRuleTestsApplications(
                    applications: cons!TEST_APPLICATIONS,
                    onSuccess: {
                      a!save(local!testRunId, fv!testRunId)
                    },
                    onError: {
                      a!save(local!error, "Could not execute test.")
                    }
                ),
                a!save(local!isAppTest, true)
              }
            ),
            a!buttonWidget(
              label: "Refresh",
              value: local!testStatus,
              saveInto: {
                a!save(local!testStatus, a!testRunStatusForId(local!testRunId))
              }
            )
          }
        ),
        a!sectionLayout(
          label: "Summary" & 
            if(isnull(local!testRunResults), null, " - " & local!testRunResults.type),
          contents: {
            a!columnsLayout(
              columns: {
                a!columnLayout(
                  contents: {
                    a!textField(
                      label: "Test-run ID",
                      labelPosition: "ADJACENT",
                      value: local!testRunId,
                      readOnly: true,
                      showWhen: not(isnull(local!testRunResults))
                    ),
                    a!richTextDisplayField(
                      showWhen: not(isnull(local!testRunResults)),
                      label: "Status",
                      labelPosition: "ADJACENT",
                      value: if(
                        local!testStatus = "COMPLETE",
                        if(
                          local!testRunResults.status="ERROR",
                          {
                            a!richTextImage(
                              image: a!documentImage(
                                document: a!iconIndicator("STATUS_ERROR")
                              )
                            ),
                            "One or more tests encountered an error"
                          },
                          local!testRunResults.status="FAIL",
                          {
                            a!richTextImage(
                              image: a!documentImage(
                                document: a!iconIndicator("STATUS_NOTDONE")
                              )
                            ),
                            "One or more test case assertions failed"
                          },
                          local!testRunResults.status="PASS",
                          {
                            a!richTextImage(
                              image: a!documentImage(
                                document: a!iconIndicator("STATUS_OK")
                              )
                            ),
                            "All test case assertions passed"
                          },
                          {
                            a!richTextImage(
                              image: a!documentImage(
                                document: a!iconIndicator("PROGRESS_RUNNING")
                              )
                            ),
                            "In progress"
                          }
                        ),
                        {
                          a!richTextImage(
                            image: a!documentImage(
                              document: a!iconIndicator("PROGRESS_RUNNING")
                            )
                          ),
                          "In progress"
                        }                  
                      )
                    ),
                    a!textField(
                      label: "Execution Time",
                      labelPosition: "ADJACENT",
                      value: local!testRunResults.totalExecutionTime & " seconds",
                      readOnly: true,
                      showWhen: not(isnull(local!testRunResults))
                    ),
                    a!textField(
                      label: "Total Time",
                      labelPosition: "ADJACENT",
                      value: local!testRunResults.totalElapsedTime & " seconds",
                      readOnly: true,
                      showWhen: not(isnull(local!testRunResults))
                    ),
                    a!textField(
                      label: "Executed On",
                      labelPosition: "ADJACENT",
                      value: local!testRunResults.startTime,
                      readOnly: true,
                      showWhen: not(isnull(local!testRunResults))
                    ),
                    a!textField(
                      label: "Executed By",
                      labelPosition: "ADJACENT",
                      value: user(local!testRunResults.executedBy, "firstName") & " " &
                        user(local!testRunResults.executedBy, "lastName"),
                      readOnly: true,
                      showWhen: not(isnull(local!testRunResults))
                    )
                  }
                ),
                a!columnLayout(
                  contents: {
                    a!pieChartField(
                      labelPosition: "COLLAPSED",
                      series: {
                        a!chartSeries(
                          label: "Passed", 
                          data: local!testRunResults.passCount, 
                          color: "GREEN"
                        ),
                        a!chartSeries(
                          label: "Failed", 
                          data: local!testRunResults.failureCount, 
                          color: "YELLOW"
                        ),
                        a!chartSeries(
                          label: "Error", 
                          data: local!testRunResults.errorCount, 
                          color: "RED"
                        )
                      },
                      showDataLabels: true,
                      showWhen: not(isnull(local!testRunResults))
                    )
                  }
                )
              }
            )
          }
        )
      }
    )
  )
)
FEEDBACK