Now accepting guest editorial from SAP, Oracle, Workday and ServiceNow practitioners.Pitch a guide
The Sign-Off Table

Lesson 6 of 6

Testing Groovy scripts

15 min

Listen to this lesson

0:00 / 5:48

SAP's guideline is explicit: don't deploy and run integration flows to test scripts. Test them before deployment, with a simulation or in an external development environment. For Contoso that matters more than usual: every Groovy rewrite of a PO Java UDF needs proof that it behaves like the original, and the proof has to be repeatable when the script changes or Groovy is upgraded.

Three levels of script testing

  1. Static checkProblems view (Upgrade Readiness Check, General Script Check) and CodeNarc 3.4.0, the version SAP supports
  2. Unit test outside the tenantRun the script in a local Groovy project against stub messages and saved payloads
  3. Simulation in the tenantSimulate the flow or the mapping before deployment; Script steps are supported
  4. Deployed contract testCall the deployed test flow's endpoint with known inputs and assert the outputs
From cheapest to most realistic: each level catches different defects.
The Sign-Off Table · thesignofftable.com/academy/sap-pim-202

A local test harness

Set up a Groovy project in your IDE and add SAP's script API from Maven Central: com.sap.cloud.script:script.api for version 1 scripts or com.sap.cloud.script:script.v2.api for version 2. That gives you the Message type and code completion. The API defines the interface, not a runtime, so you supply a small stub message. Groovy's map coercion is enough: def props = [:]
def msg = [getBody: { Class t -> t == Reader ? new StringReader(body) : body }, getProperty: { n -> props[n] }, setProperty: { n, v -> props[n] = v }] as Message
Returning a StringReader when the script asks for a Reader matters: XmlSlurper.parse given a plain String would treat it as a file name or URI.

Then load the script with a binding that supplies messageLogFactory, call it and assert: def binding = new Binding([messageLogFactory: new Expando(getMessageLog: { m -> null })])
def script = new GroovyShell(binding).parse(new File('SetPoProperties.groovy'))
script.processData(msg)
assert props.poNumber == '4500000187'
The stub log returns null, which your script already handles with a null check.

A local unit test runs the real script file against a stub message and a saved payload, with no tenant involved.
The Sign-Off Table · thesignofftable.com/academy/sap-pim-202

What to test

CaseContoso exampleExpected
Happy pathORDERS05 with three itemspoNumber 4500000187, lineCount 3
BulkTwo IDocs in one messageDefined behavior: error, or values for both
Missing dataNo E1EDK01 segmentA clear exception, not a null property
Edge valuesMaterial 000000000000012345stripZeros returns 12345
Version paritySame tests on Script 1.x and 2.xIdentical results before the upgrade
PO parityInputs that proved the PI Java UDFSame outputs as PO

A minimal test set for one script; keep it next to the script in source control.

Static checks before any run

Static checks are the cheapest test you have. In the tenant, the script editor's Problems view runs the Upgrade Readiness Check and the General Script Check every time you open a script. Outside the tenant, SAP names CodeNarc 3.4.0 for analyzing Groovy code for defects, bad practices and style issues. Contoso runs it in the same build that runs the unit tests, with a short rule set agreed by Theo's team: unused imports, unused variables, empty catch blocks and string concatenation in loops fail the build. Style rules that only matter to taste are warnings, so the build stays trusted.

Where the tests live

A test that only exists on one developer's laptop isn't evidence. Contoso keeps each script, its test class and its sample payloads together in source control, with the payloads anonymized: no real bank details or contact names from XP1 traffic. The test run's output goes into the test case for the interface in SAP Cloud ALM, next to the mapping evidence from sap-pim-201. When Groovy or the script API changes version, the whole set runs again, and the results are compared before anyone touches production.

Simulation in the tenant

The integration flow simulation supports the Script step, among other message transformers. Its limit: HTTP calls made inside a script can't be simulated. Mock receiver responses on Request Reply steps instead. Simulation is the right place to check how the script interacts with the headers and properties set by earlier steps, which a local test only approximates.

Key points
  • Don't test scripts by deploying them; use static checks, local unit tests and simulation first.
  • SAP's script API is on Maven Central (script.api and script.v2.api); stub Message and messageLogFactory locally.
  • Test happy path, bulk, missing data, edge values, version parity and PO parity.
  • Simulation supports Script steps but not HTTP calls made inside scripts.

Check your understanding · not graded

Lesson check

  1. 1. Which Maven coordinates provide SAP's script API for version 2 scripts?

  2. 2. Why does a local test pass a binding with <code>messageLogFactory</code>?

  3. 3. What can't the integration flow simulation do with a Script step?

  4. 4. Which test proves a Groovy rewrite of a PI Java UDF is safe to migrate?