Skip to content

Lesson 22 — ABAP Unit, Debugging, ATC & Performance ​

Guided learning: 3 hours
Independent practice: 3 hours (separate file)
Environment: SAP BTP ABAP Environment Trial + Eclipse with ABAP Development Tools (ADT)
Prerequisites: Basic ABAP classes, methods, internal tables, and ABAP SQL. No objects from previous lessons are required.

1. The business problem: a calculation is wrong ​

Imagine you maintain an order-processing application. A user reports:

“Sometimes the total is too low. Also, customers buying exactly ten items are not receiving their discount.”

The application activates successfully. It does not produce a runtime error. However, the calculation gives the wrong business result.

In a real development team, you should not just change code until the result looks right. You need to reproduce the problem, identify its cause, correct it, and show that the fix has not broken other cases.

This lesson teaches four everyday development skills:

  1. ABAP Unit: automatically check that methods return the right result.
  2. Debugger: stop a program, inspect variable values, and discover why a test fails.
  3. ABAP Test Cockpit (ATC): check code for potential quality and ABAP Cloud issues.
  4. Performance: ask the database for only the rows and columns you need.

Our workflow:

text
Bug report → Reproduce → Write failing test → Debug
           → Fix → Tests pass → ATC check → SQL review

Important: The first code example contains intentional logical bugs. It is supposed to activate and then fail two tests. Do not fix those lines until you have seen the failures.

2. Create the guided exercise package and class ​

Step 2.1 — Open the ABAP project ​

  1. Start Eclipse.
  2. Open the ABAP perspective using Window → Perspective → Open Perspective → Other… → ABAP if necessary.
  3. In Project Explorer, expand your SAP BTP ABAP Trial project.
  4. Choose an existing writable package, or create a new package named ZPKG_L22_001 (substitute your assigned suffix for 001).

Step 2.2 — Create a class ​

  1. Right-click the package.
  2. Choose New → ABAP Class. If it is not listed, use New → Other ABAP Repository Object…, and search for ABAP Class.
  3. Enter the name ZCL_L22_ORDER_TOTAL_001.
  4. Description: Lesson 22 - Order calculation and tests.
  5. Complete the wizard, selecting a transport request if requested.
  6. Replace the generated global class source with the code below.

Use a unique suffix consistently in the class name, every reference to the class, and the later SQL table name. The names shown here use 001 only as a classroom example.

Step 2.3 — Paste the intentionally faulty class ​

The business rules are:

  • Merchandise subtotal = unit price × quantity.
  • Orders of 10 or more items receive 10% off merchandise only.
  • The delivery fee is added after the discount.
  • For this exercise, use nonnegative prices and delivery fees and positive quantities.
abap
CLASS zcl_l22_order_total_001 DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

    CLASS-METHODS calculate_total
      IMPORTING
        iv_unit_price   TYPE decfloat34
        iv_quantity     TYPE i
        iv_delivery_fee TYPE decfloat34
      RETURNING VALUE(rv_total) TYPE decfloat34.
ENDCLASS.

CLASS zcl_l22_order_total_001 IMPLEMENTATION.

  METHOD calculate_total.

    rv_total = iv_unit_price * iv_quantity.

    " Deliberate bug 1: the exact boundary is handled incorrectly.
    IF iv_quantity > 10.
      rv_total = rv_total * CONV decfloat34( '0.9' ).
    ENDIF.

    " Deliberate bug 2: delivery is subtracted, not added.
    rv_total = rv_total - iv_delivery_fee.

  ENDMETHOD.

  METHOD if_oo_adt_classrun~main.

    DATA(total) = calculate_total(
      iv_unit_price   = CONV decfloat34( '40' )
      iv_quantity     = 2
      iv_delivery_fee = CONV decfloat34( '5' ) ).

    out->write( |Calculated total: { total }| ).
    out->write( 'Expected business total: 85' ).

  ENDMETHOD.

ENDCLASS.

Step 2.4 — Activate and run ​

  1. Save using Ctrl+S.
  2. Activate using Ctrl+F3.
  3. Right-click the class editor and choose Run As → ABAP Application (Console), or use F9.
  4. Read the ABAP Console output.

Expected result before the fix:

text
Calculated total: 75
Expected business total: 85

The code activates, but the calculation is incorrect. Activation verifies syntax, not business correctness.

3. Understand the expected results before writing tests ​

Work out these examples yourself. A 10% discount means multiplying the merchandise subtotal by 0.90, then adding the delivery fee.

ScenarioQuantityUnit priceDeliveryExpected total
Below discount threshold120020
Delivery fee240585
Exactly 10 items10305275
More than 10 items12200216

An ABAP Unit test can check each example automatically. It will report a failure when the method produces something different.

4. Create ABAP Unit tests in Eclipse ADT ​

Step 4.1 — Open the Test Classes tab ​

  1. Open ZCL_L22_ORDER_TOTAL_001 in the ABAP editor.
  2. At the bottom of the editor, select Test Classes (near the Global Class / Local Types tabs; the exact tab layout can differ by ADT version).
  3. The test-class include will be created automatically if it does not exist.
  4. Paste the code below into Test Classes, not into the Global Class source.

This separation matters: the main class contains production logic, while the test classes are executed by the ABAP Unit framework.

Step 4.2 — Paste these four tests ​

abap
CLASS ltc_order_total DEFINITION FINAL FOR TESTING
  DURATION SHORT
  RISK LEVEL HARMLESS.

  PRIVATE SECTION.
    METHODS below_threshold FOR TESTING.
    METHODS delivery_fee     FOR TESTING.
    METHODS exactly_ten      FOR TESTING.
    METHODS above_threshold  FOR TESTING.
ENDCLASS.

CLASS ltc_order_total IMPLEMENTATION.

  METHOD below_threshold.
    DATA(actual) = zcl_l22_order_total_001=>calculate_total(
      iv_unit_price   = CONV decfloat34( '20' )
      iv_quantity     = 1
      iv_delivery_fee = CONV decfloat34( '0' ) ).

    cl_abap_unit_assert=>assert_equals(
      exp = CONV decfloat34( '20' )
      act = actual
      msg = 'A single item must not receive a discount' ).
  ENDMETHOD.

  METHOD delivery_fee.
    DATA(actual) = zcl_l22_order_total_001=>calculate_total(
      iv_unit_price   = CONV decfloat34( '40' )
      iv_quantity     = 2
      iv_delivery_fee = CONV decfloat34( '5' ) ).

    cl_abap_unit_assert=>assert_equals(
      exp = CONV decfloat34( '85' )
      act = actual
      msg = 'Delivery must be added to the merchandise total' ).
  ENDMETHOD.

  METHOD exactly_ten.
    DATA(actual) = zcl_l22_order_total_001=>calculate_total(
      iv_unit_price   = CONV decfloat34( '30' )
      iv_quantity     = 10
      iv_delivery_fee = CONV decfloat34( '5' ) ).

    cl_abap_unit_assert=>assert_equals(
      exp = CONV decfloat34( '275' )
      act = actual
      msg = 'The discount begins at exactly ten items' ).
  ENDMETHOD.

  METHOD above_threshold.
    DATA(actual) = zcl_l22_order_total_001=>calculate_total(
      iv_unit_price   = CONV decfloat34( '20' )
      iv_quantity     = 12
      iv_delivery_fee = CONV decfloat34( '0' ) ).

    cl_abap_unit_assert=>assert_equals(
      exp = CONV decfloat34( '216' )
      act = actual
      msg = 'A quantity above ten receives a ten-percent discount' ).
  ENDMETHOD.

ENDCLASS.

Step 4.3 — Run the tests ​

  1. Save and activate the class and its test-class include.
  2. Right-click the class in Project Explorer or the editor.
  3. Choose Run As → ABAP Unit Test, or press Ctrl+Shift+F10.
  4. Open the ABAP Unit view if it is not displayed automatically: Window → Show View → Other…, then search for ABAP Unit.
  5. Expand the results to see individual test methods.

Expected before correction: four test methods are discovered; below_threshold and above_threshold pass; delivery_fee and exactly_ten fail. The test names and messages help identify the business rules being violated.

If no tests are discovered, check that your code is in the Test Classes tab, that each test method has FOR TESTING, and that the objects are activated.

5. Debug the incorrect result ​

A test tells you what is wrong. The debugger helps you understand why.

Step 5.1 — Add a breakpoint ​

  1. Open the Global Class tab for ZCL_L22_ORDER_TOTAL_001.
  2. Find the line IF iv_quantity > 10..
  3. Double-click the left margin beside the line number to set a breakpoint.
  4. Add another breakpoint to rv_total = rv_total - iv_delivery_fee..
  5. Execute the class using F9, or run the unit test that calls this method.
  6. If Eclipse prompts you to switch to the Debug perspective, accept.

Step 5.2 — Inspect what happens ​

In the debugger:

  • Open Variables and inspect iv_quantity, iv_unit_price, iv_delivery_fee, and rv_total.
  • Use Step Over (F6) to execute a statement without stepping into method calls.
  • Use Resume (F8) to continue to the next breakpoint or program completion.
  • Observe that with quantity 2, the subtotal is 80, then the delivery fee changes it to 75 instead of 85.
  • To reproduce the exact-threshold defect, debug the exactly_ten test or change the console call to iv_quantity = 10, iv_unit_price = 30 and iv_delivery_fee = 5.

If you change the console inputs, also change its expected-business-total message to 275: the correct calculation is (10 × 30 × 0.90) + 5. After inspecting this case, restore the console inputs to quantity 2, unit price 40, and delivery fee 5, and restore the expected-total message to 85 before continuing to Section 6.

If the debugger does not stop, check that the class is activated, the breakpoint is enabled, and you are executing in the same ADT project/user context. For this exercise the console and ABAP Unit tests are both valid entry points.

Step 5.3 — Write a short diagnosis ​

In your notes, record:

  1. Which line caused the delivery-fee problem?
  2. Which condition excluded an order containing exactly ten items?
  3. Why did both lines pass the syntax check?

6. Fix the class and prove the correction ​

Replace only the calculate_total method with the following corrected implementation:

abap
METHOD calculate_total.

  rv_total = iv_unit_price * iv_quantity.

  IF iv_quantity >= 10.
    rv_total = rv_total * CONV decfloat34( '0.9' ).
  ENDIF.

  rv_total = rv_total + iv_delivery_fee.

ENDMETHOD.

Save and activate. Then:

  1. Run Ctrl+Shift+F10 again.
  2. Verify that all four ABAP Unit tests pass.
  3. Run the class in the console again with the original inputs (quantity 2, unit price 40, delivery fee 5); its total should now be 85.
  4. Remove or disable the breakpoints when you are finished.

Important habit: Keep the tests. They will protect this calculation from accidental regressions when somebody changes it later.

7. Run the ABAP Test Cockpit (ATC) ​

ABAP Unit verifies the behavior you explicitly test. ATC checks code quality and compliance rules, such as selected syntax, maintainability, security, or performance patterns, depending on the configured check variant. ATC does not know whether an order total should include delivery unless you write a test for it.

Step 7.1 — Run a check ​

  1. Open the corrected ZCL_L22_ORDER_TOTAL_001 class in Eclipse ADT.
  2. Right-click in the editor or on the class in Project Explorer.
  3. Choose Run As → ABAP Test Cockpit, or use Ctrl+Shift+F2.
  4. Wait for the check to finish.
  5. Inspect the ATC Problems view; open it through Window → Show View → Other… if needed.

Step 7.2 — Interpret the result ​

  • No findings: This is a valid result for a small, clean class. Do not invent an ATC warning.
  • A finding appears: Read its check name, location, explanation, and severity. Correct a genuine problem, then rerun ATC.
  • ATC is unavailable or permission is denied: Record the restriction and continue with ABAP Unit, debugging, and SQL review. Do not assume that every Trial tenant has identical ATC permissions or check variants.

Try Run As → ABAP Test Cockpit With… only if your environment offers a suitable alternate check variant; do not invent check-variant names.

8. Improve data access: ask the database for less data ​

A different performance problem occurs when code reads more rows and columns than the task needs. This can waste work in the database, network, and ABAP application server. SAP recommends selecting only the required rows and fields.

For this small lab, you will create a table that belongs to you. You will not access or change SAP-delivered tables or the shared S/4HANA system.

Step 8.1 — Create a database table ​

  1. Right-click your package in Eclipse ADT.
  2. Choose New → Other ABAP Repository Object….
  3. Search for Database Table and choose it.
  4. Name the table ZL22_ORDERS_001 and enter a description.
  5. Replace the table definition with this code:
abap
@EndUserText.label : 'Lesson 22 SQL Performance Orders'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zl22_orders_001 {
  key client   : abap.clnt not null;
  key order_id : abap.numc(6) not null;
  customer    : abap.char(20);
  priority    : abap.char(1);
  amount      : abap.dec(13,2);
}
  1. Save and activate using Ctrl+F3.

Step 8.2 — Create a console class to seed and read the table ​

Create another ABAP class named ZCL_L22_SQL_LAB_001 in the same package and paste the following complete code:

abap
CLASS zcl_l22_sql_lab_001 DEFINITION
  PUBLIC FINAL CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
ENDCLASS.

CLASS zcl_l22_sql_lab_001 IMPLEMENTATION.

  METHOD if_oo_adt_classrun~main.

    " These are demonstration records in our own table.
    TYPES ty_rows TYPE STANDARD TABLE OF zl22_orders_001
      WITH EMPTY KEY.

    DATA(rows) = VALUE ty_rows(
      ( order_id = '000001'
        customer = 'ALICE' priority = 'H' amount = '100' )
      ( order_id = '000002'
        customer = 'BOB'   priority = 'N' amount = '50' )
      ( order_id = '000003'
        customer = 'CARLA' priority = 'H' amount = '200' )
      ( order_id = '000004'
        customer = 'DAVID' priority = 'N' amount = '70' )
      ( order_id = '000005'
        customer = 'ELENA' priority = 'H' amount = '125' ) ).

    MODIFY zl22_orders_001 FROM TABLE @rows.

    " Example A: reads all columns and all rows in this table.
    SELECT FROM zl22_orders_001
      FIELDS *
      INTO TABLE @DATA(all_orders).

    " Example B: reads only the two columns and rows we need.
    SELECT FROM zl22_orders_001
      FIELDS order_id, amount
      WHERE priority = 'H'
      INTO TABLE @DATA(high_priority_orders).

    out->write( |Rows read by broad query: { lines( all_orders ) }| ).
    out->write( |High-priority rows: { lines( high_priority_orders ) }| ).
    out->write( high_priority_orders ).

  ENDMETHOD.
ENDCLASS.

Activate and execute with F9.

For a new, student-specific table, the expected counts are 5 rows in the broad result and 3 high-priority rows. If you use a shared table name containing additional records, counts may differ; use a unique suffix.

Step 8.3 — Compare the two SELECT statements ​

Query AQuery B
FIELDS *FIELDS order_id, amount
No WHEREWHERE priority = 'H'
Reads all demo rows and columnsReads only required demo rows and columns
Useful to inspect a tiny demoBetter pattern for a selective business requirement

Do not interpret this five-row demonstration as a benchmark. The lesson shows how to reduce unnecessary data transfer; it does not prove a measurable runtime improvement. Actual performance work requires representative data volumes and profiling or SQL trace tools where available.

Step 8.4 — Think about an API equivalent ​

In Lesson 21, the OData client proxy supported filters and set_top( ). That is the same broad principle: restrict data as close to its source as possible rather than fetch everything and discard most of it in ABAP.

9. What you should now be able to do ​

Before moving to independent practice, check that you can:

10. Prepare for independent practice ​

You will receive a different maintenance ticket: repair a service-ticket response-time calculation. You will start from a working-but-incorrect class, design your own tests, debug it, run ATC, and explain one performance improvement.

Do not start by changing the class immediately. First write down the expected business behavior and observe the failing tests.

Official references ​

Environment note: The ABAP examples follow the SAP BTP ABAP Cloud / ADT programming model, but they have not been activated in your individual Trial tenant. If a generated wizard screen or available check variant differs, use the options exposed by your installed ADT and document the difference.