$npx -y skills add likweitan/abap-skills --skill abap-unit-testingHelp with ABAP Unit testing including test class setup, assertions, test doubles, mocking frameworks, dependency injection, CDS test environments, SQL test environments, RAP BO test doubles, and test fixtures. Use when users ask about ABAP unit tests, test classes, test methods,
| 1 | # ABAP Unit Testing |
| 2 | |
| 3 | Guide for writing effective ABAP Unit tests including test class setup, assertions, test doubles, mocking frameworks, and test environments for CDS, SQL, and RAP. |
| 4 | |
| 5 | ## Workflow |
| 6 | |
| 7 | 1. **Determine the testing goal**: |
| 8 | - Testing business logic in a class method |
| 9 | - Testing a CDS view entity |
| 10 | - Testing a RAP BO behavior implementation |
| 11 | - Testing database-dependent logic with SQL test doubles |
| 12 | - Setting up test doubles for external dependencies |
| 13 | |
| 14 | 2. **Choose the right approach**: |
| 15 | - Direct unit test for pure logic (no dependencies) |
| 16 | - Constructor/setter injection for mockable dependencies |
| 17 | - CDS test environment for CDS view tests |
| 18 | - OSQL test environment for SQL-dependent code |
| 19 | - RAP BO test doubles for RAP behavior tests |
| 20 | |
| 21 | 3. **Follow the AAA pattern**: Arrange → Act → Assert |
| 22 | |
| 23 | 4. **Ensure test isolation**: Tests must not depend on persistent data or external systems |
| 24 | |
| 25 | ## Test Class Fundamentals |
| 26 | |
| 27 | ### Test Class Definition |
| 28 | |
| 29 | ```abap |
| 30 | "! Test class for ZCL_MY_CLASS |
| 31 | CLASS ltc_my_class DEFINITION FINAL FOR TESTING |
| 32 | DURATION SHORT |
| 33 | RISK LEVEL HARMLESS. |
| 34 | |
| 35 | PRIVATE SECTION. |
| 36 | DATA cut TYPE REF TO zcl_my_class. "Class Under Test |
| 37 | |
| 38 | CLASS-METHODS class_setup. "Once before all tests |
| 39 | CLASS-METHODS class_teardown. "Once after all tests |
| 40 | METHODS setup. "Before each test |
| 41 | METHODS teardown. "After each test |
| 42 | |
| 43 | METHODS test_calculate_total FOR TESTING. |
| 44 | METHODS test_validate_input FOR TESTING. |
| 45 | METHODS test_empty_input FOR TESTING RAISING cx_static_check. |
| 46 | ENDCLASS. |
| 47 | |
| 48 | CLASS ltc_my_class IMPLEMENTATION. |
| 49 | |
| 50 | METHOD class_setup. |
| 51 | " One-time setup for all tests in this class |
| 52 | ENDMETHOD. |
| 53 | |
| 54 | METHOD class_teardown. |
| 55 | " One-time cleanup |
| 56 | ENDMETHOD. |
| 57 | |
| 58 | METHOD setup. |
| 59 | " Create fresh instance before each test |
| 60 | cut = NEW #( ). |
| 61 | ENDMETHOD. |
| 62 | |
| 63 | METHOD teardown. |
| 64 | " Cleanup after each test |
| 65 | ENDMETHOD. |
| 66 | |
| 67 | METHOD test_calculate_total. |
| 68 | " Arrange |
| 69 | DATA(lv_quantity) = 5. |
| 70 | DATA(lv_price) = CONV decfloat34( '10.50' ). |
| 71 | |
| 72 | " Act |
| 73 | DATA(lv_result) = cut->calculate_total( |
| 74 | iv_quantity = lv_quantity |
| 75 | iv_price = lv_price ). |
| 76 | |
| 77 | " Assert |
| 78 | cl_abap_unit_assert=>assert_equals( |
| 79 | act = lv_result |
| 80 | exp = CONV decfloat34( '52.50' ) |
| 81 | msg = 'Total should be quantity * price' ). |
| 82 | ENDMETHOD. |
| 83 | |
| 84 | METHOD test_validate_input. |
| 85 | cl_abap_unit_assert=>assert_true( |
| 86 | act = cut->validate_input( 'VALID_INPUT' ) |
| 87 | msg = 'Valid input should return true' ). |
| 88 | ENDMETHOD. |
| 89 | |
| 90 | METHOD test_empty_input. |
| 91 | TRY. |
| 92 | cut->validate_input( '' ). |
| 93 | cl_abap_unit_assert=>fail( msg = 'Should have raised exception' ). |
| 94 | CATCH zcx_validation_error INTO DATA(lx_error). |
| 95 | cl_abap_unit_assert=>assert_bound( |
| 96 | act = lx_error |
| 97 | msg = 'Exception should be raised for empty input' ). |
| 98 | ENDTRY. |
| 99 | ENDMETHOD. |
| 100 | |
| 101 | ENDCLASS. |
| 102 | ``` |
| 103 | |
| 104 | ### Test Class Attributes |
| 105 | |
| 106 | | Attribute | Options | Purpose | |
| 107 | | ------------ | ------------------------------------- | ------------------------------------------------------ | |
| 108 | | `DURATION` | `SHORT` / `MEDIUM` / `LONG` | Expected execution time; `SHORT` < 1s (default for CI) | |
| 109 | | `RISK LEVEL` | `HARMLESS` / `DANGEROUS` / `CRITICAL` | Impact on system data; `HARMLESS` = no DB changes | |
| 110 | |
| 111 | ### Test Method Additions |
| 112 | |
| 113 | | Addition | Purpose | |
| 114 | | ------------------------- | ------------------------------------------------------------------ | |
| 115 | | `FOR TESTING` | Marks method as a test method | |
| 116 | | `RAISING cx_static_check` | Allows exceptions to propagate (test fails on unhandled exception) | |
| 117 | |
| 118 | ## CL_ABAP_UNIT_ASSERT — Assertion Methods |
| 119 | |
| 120 | | Method | Purpose | Example | |
| 121 | | --------------------------- | --------------------------- | ------------------------------------------------------------ | |
| 122 | | `assert_equals` | Value equality | `assert_equals( act = result exp = 42 )` | |
| 123 | | `assert_true` | Boolean true |