Untested ABAP is a rumor
Every ABAP developer has a "it worked in DEV" story that ended badly in QA. ABAP Unit is the framework that ends those stories: automated test classes, running in ADT, catching regressions before transport.
If you've never written one, the first test class is the whole learning curve. After that, it's repetition. Here's the first one, explained.
The anatomy of a test class
CLASS ltc_order_calc DEFINITION DEFERRED.
CLASS zcl_order_calc DEFINITION LOCAL FRIENDS ltc_order_calc.
CLASS ltc_order_calc DEFINITION FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS calc_total FOR TESTING.
ENDCLASS.
CLASS ltc_order_calc IMPLEMENTATION.
METHOD calc_total.
" given
DATA(lo_calc) = NEW zcl_order_calc( ).
" when
DATA(lv_total) = lo_calc->calc_total(
iv_quantity = 10
iv_price = '25.50' ).
" then
cl_abap_unit_assert=>assert_equals(
exp = '255.00'
act = lv_total
msg = 'Total should be quantity x price' ).
ENDMETHOD.
ENDCLASS.
FOR TESTING marks the class; DURATION SHORT and RISK LEVEL HARMLESS tell the framework it's safe to run automatically. LOCAL FRIENDS gives the test access to the class under test — including private members, when you need them.
Given – when – then. Arrange the inputs, execute the method, assert the outcome. Every test you'll ever write follows this shape.
What makes a good first test
- Pure logic. Calculations, validations, mappings — methods with inputs and outputs, no database, no UI. Testable in milliseconds.
- One behavior per method.
calc_totaltests the happy path. A second method tests the zero-quantity edge. Small tests, clear failures. - Meaningful asserts.
assert_equalswith expected and actual. Themsgparameter is what you'll read at 2 AM — write it for that reader.
Running it
In ADT: right-click the class → Run As → ABAP Unit Test (Ctrl+Shift+F10). Green bar, done. The results view shows every test method, timings, and failure details with a jump-to-code link.
For database-dependent logic, use test doubles — the framework's term for mocks. ABAP Unit supports test seams and doubles so your tests don't need a populated DEV client. Tests that need real database state are integration tests; keep them separate and few.
Start with the pure-logic methods — they're the easiest wins. Once the habit sticks, move to harder cases: EML-based logic with test doubles, then full behavior tests. Each level builds on the last.
The habit that matters
One test class per production class, written alongside the code — not "when there's time." The ROI isn't philosophical: it's the refactoring you can finally do without fear, the regression caught before transport, the 2 AM debugging session that never happens.
Untested code isn't just risky — it's frozen. Nobody refactors what they can't verify. Tests are what keep code changeable.
Start today: pick your most calculation-heavy class and write three test methods for it. Thirty minutes, and you'll never want to go back.
What's your excuse been — no time, legacy code, or "it works"? Be honest in the comments.