Skip to main content

ABAP Unit Coverage Pipeline

adt aunit (from @abapify/adt-aunit) runs ABAP Unit tests and can emit coverage in the formats consumers expect. The pipeline is thin: two SAP calls + a local transform.

Two-step coverage collection

SAP splits coverage into two endpoints:

POST /sap/bc/adt/runtime/traces/coverage/measurements/<id>

└─► tree of {class → method → counters}
(lines / branches / statements, missed + executed)

GET /sap/bc/adt/runtime/traces/coverage/statements/<id>

└─► per-method statement ranges (start line → end line)

Both responses are typed — they have contracts in @abapify/adt-contracts under runtime-traces and reuse the Acoverage* schemas from adt-schemas. The CLI calls:

const measurements =
await client.adt.runtime.traces.coverage.measurements.post(measurementId);
const statements =
await client.adt.runtime.traces.coverage.statements.get(measurementId);

(see packages/adt-aunit/src/commands/aunit.ts).

JaCoCo XML emit

formatters/jacoco.ts folds (measurements, statements) into a single JaCoCo XML tree. Two formats are supported out-of-the-box:

FormatFlagConsumer
JaCoCo--coverage-format jacocogeneric CI; IntelliJ; default
Sonar Generic--coverage-format sonar-genericSonarQube 'Generic Test Coverage' importer

Counter types are mapped to JaCoCo's vocabulary:

SAP counterJaCoCo type
statementsLINE
branchesBRANCH
methodsMETHOD

Missed/covered counts are emitted per <counter> element.

abapGit filename mapping (our improvement over sapcli)

SAP identifies coverage targets by ADT URI (/sap/bc/adt/oo/classes/ZCL_X/includes/main). CI tools want file paths. sapcli leaves the URI in place, which makes SonarQube reports useless — the "files" are unclickable ADT handles.

adt aunit imports adtUriToAbapGitPath from @abapify/adt-plugin-abapgit and rewrites every target to the abapGit path convention:

/sap/bc/adt/oo/classes/ZCL_X → src/zcl_x.clas.abap
/sap/bc/adt/oo/classes/ZCL_X/includes/main → src/zcl_x.clas.abap
/sap/bc/adt/oo/classes/ZCL_X/includes/testclasses → src/zcl_x.clas.testclasses.abap
/sap/bc/adt/programs/programs/ZMY → src/zmy.prog.abap

The resulting sourcefile and name attributes in the JaCoCo XML match what abapGit would write to disk, so the reports line up with the source files a developer actually has in their repo / IDE.

SonarQube integration

sonar-project.properties needs:

sonar.coverage.jacoco.xmlReportPaths=reports/jacoco.xml
sonar.sources=src
sonar.tests=src

Then:

adt aunit -p $ZDEMO \
--coverage --coverage-format jacoco \
--coverage-output reports/jacoco.xml
# ... then run sonar-scanner

SonarQube picks up the src/zcl_*.clas.abap filenames directly — no further rewriting needed.

The sonar-generic format (SonarQube's "generic test coverage" schema) is also supported and uses the same filename mapping.

MCP equivalent

The run_unit_tests MCP tool calls the same contracts + formatters. See MCP → run_unit_tests.

See also