All skills
secondsky avatar

/sap-abap

@620a19a
by Eddiesecondsky/sap-skills456 stars
120

Comprehensive ABAP development skill for SAP systems. Use when writing ABAP code, working with internal tables, structures, ABAP SQL, object-oriented programming, RAP (RESTful Application Programming Model), CDS views, EML statements, ABAP Cloud development, string processing, dynamic programming, RTTI/RTTC, field symbols, data references, exception handling, or ABAP unit testing. Covers both classic ABAP and modern ABAP for Cloud Development patterns.

Use this Skill: https://skilld.dev/gh/secondsky/sap-skills/sap-abap

This session only. Nothing lands on disk.

referencesunit-testing.md

≈2.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

ABAP Unit Testing - Complete Reference

Source: https://github.com/SAP-samples/abap-cheat-sheets/blob/main/14_ABAP_Unit_Tests.md

Version Note: Test seams (TEST-SEAM/TEST-INJECTION) require 7.50+. Test relations (@testing ABAP Doc) require 7.52+. All other ABAP Unit features are available from 7.40+.


Test Class Structure

CLASS ltc_test_class DEFINITION
  FOR TESTING
  RISK LEVEL HARMLESS
  DURATION SHORT.

  PRIVATE SECTION.
    DATA cut TYPE REF TO zcl_class_under_test.  " Class Under Test

    CLASS-METHODS class_setup.
    CLASS-METHODS class_teardown.
    METHODS setup.
    METHODS teardown.

    METHODS test_method_1 FOR TESTING.
    METHODS test_method_2 FOR TESTING.

ENDCLASS.

CLASS ltc_test_class IMPLEMENTATION.

  METHOD class_setup.
    " Run once before all tests
  ENDMETHOD.

  METHOD class_teardown.
    " Run once after all tests
  ENDMETHOD.

  METHOD setup.
    " Run before each test
    cut = NEW #( ).
  ENDMETHOD.

  METHOD teardown.
    " Run after each test
    CLEAR cut.
  ENDMETHOD.

  METHOD test_method_1.
    " Given
    DATA(input) = 5.

    " When
    DATA(result) = cut->multiply_by_two( input ).

    " Then
    cl_abap_unit_assert=>assert_equals(
      act = result
      exp = 10 ).
  ENDMETHOD.

ENDCLASS.

Risk Level and Duration

Risk Levels

RISK LEVEL HARMLESS    " No system changes (default)
RISK LEVEL CRITICAL    " Changes system settings
RISK LEVEL DANGEROUS   " Changes persistent data

Duration

DURATION SHORT         " Seconds (default)
DURATION MEDIUM        " About 1 minute
DURATION LONG          " More than 1 minute

Fixture Methods

Method Type Execution
class_setup Static Once before all tests
setup Instance Before each test
teardown Instance After each test
class_teardown Static Once after all tests

Assertions (CL_ABAP_UNIT_ASSERT)

Equality and Comparison

" Verify equality
cl_abap_unit_assert=>assert_equals(
  act = actual_value
  exp = expected_value
  msg = 'Values should be equal' ).

" Verify difference
cl_abap_unit_assert=>assert_differs(
  act = value1
  exp = value2 ).

" Verify number in range
cl_abap_unit_assert=>assert_number_between(
  lower  = 1
  upper  = 10
  number = actual_number ).

Boolean Assertions

" True condition
cl_abap_unit_assert=>assert_true(
  act = condition
  msg = 'Condition should be true' ).

" False condition
cl_abap_unit_assert=>assert_false(
  act = condition ).

Reference Assertions

" Reference is bound
cl_abap_unit_assert=>assert_bound(
  act = ref ).

" Reference is not bound
cl_abap_unit_assert=>assert_not_bound(
  act = ref ).

Initial Value Assertions

" Value is initial
cl_abap_unit_assert=>assert_initial(
  act = data_object ).

" Value is not initial
cl_abap_unit_assert=>assert_not_initial(
  act = data_object ).

System Field Assertions

" Check sy-subrc
cl_abap_unit_assert=>assert_subrc(
  exp = 0
  msg = 'Operation should succeed' ).

" Check return code
cl_abap_unit_assert=>assert_return_code(
  exp = 0
  act = return_code ).

Table Assertions

" Line exists in table
cl_abap_unit_assert=>assert_table_contains(
  line  = expected_line
  table = itab ).

" Line does not exist
cl_abap_unit_assert=>assert_table_not_contains(
  line  = line_to_check
  table = itab ).

String Assertions

" Pattern matching
cl_abap_unit_assert=>assert_char_cp(
  act = text
  exp = '*error*' ).  " Contains 'error'

" No pattern match
cl_abap_unit_assert=>assert_char_np(
  act = text
  exp = '*error*' ).

" Regex matching
cl_abap_unit_assert=>assert_text_matches(
  text    = actual_text
  pattern = '\d{3}-\d{4}' ).

" No regex match
cl_abap_unit_assert=>assert_text_not_matches(
  text    = actual_text
  pattern = 'error' ).

Manual Control

" Force test failure
cl_abap_unit_assert=>fail(
  msg = 'This should not happen' ).

" Skip test
cl_abap_unit_assert=>skip(
  msg = 'Prerequisites not met' ).

Common Parameters

  • act: Actual value to verify
  • exp: Expected value
  • msg: Error message (optional)
  • quit: Control test flow (use if_abap_unit_constant=>quit-no to continue)

Test Class Friendship

" Allow test class to access private methods
CLASS zcl_production_class DEFINITION LOCAL FRIENDS ltc_test_class.

" Multiple test classes
CLASS ltc_test_1 DEFINITION DEFERRED.
CLASS ltc_test_2 DEFINITION DEFERRED.
CLASS zcl_production_class DEFINITION LOCAL FRIENDS ltc_test_1 ltc_test_2.

Partial Interface Implementation

CLASS ltd_test_double DEFINITION FOR TESTING.
  PUBLIC SECTION.
    INTERFACES zif_some_interface PARTIALLY IMPLEMENTED.
ENDCLASS.

CLASS ltd_test_double IMPLEMENTATION.
  METHOD zif_some_interface~needed_method.
    " Only implement what's needed for test
  ENDMETHOD.
ENDCLASS.

Test Doubles

Manual Test Double (Interface-based)

" Test double class
CLASS ltd_database_access DEFINITION FOR TESTING.
  PUBLIC SECTION.
    INTERFACES zif_database_access.
    DATA returned_data TYPE zdemo_table.
ENDCLASS.

CLASS ltd_database_access IMPLEMENTATION.
  METHOD zif_database_access~get_data.
    result = me->returned_data.  " Return configured data
  ENDMETHOD.
ENDCLASS.

" Usage in test
METHOD test_with_double.
  " Given
  DATA(double) = NEW ltd_database_access( ).
  double->returned_data = VALUE #( ( id = 1 name = 'Test' ) ).

  cut = NEW zcl_processor( database = double ).

  " When
  DATA(result) = cut->process( ).

  " Then
  cl_abap_unit_assert=>assert_equals( act = result exp = 'Test' ).
ENDMETHOD.

Injection Techniques

Constructor Injection:

" Production class
CLASS zcl_processor DEFINITION.
  PUBLIC SECTION.
    METHODS constructor
      IMPORTING database TYPE REF TO zif_database_access.
ENDCLASS.

" In test
cut = NEW zcl_processor( database = test_double ).

Setter Injection:

cut->set_database( test_double ).

Back Door Injection (via friendship):

" With LOCAL FRIENDS declaration
cut->mo_database = test_double.

Test Seams

Production Code

METHOD do_something.
  DATA result TYPE string.

  TEST-SEAM database_access.
    SELECT * FROM dbtab INTO TABLE @DATA(data).
    result = process( data ).
  END-TEST-SEAM.

  RETURN result.
ENDMETHOD.

Test Code

METHOD test_do_something.
  " Inject test data
  TEST-INJECTION database_access.
    data = VALUE #( ( id = 1 name = 'Test' ) ).
    result = 'processed'.
  END-TEST-INJECTION.

  " When
  DATA(actual) = cut->do_something( ).

  " Then
  cl_abap_unit_assert=>assert_equals( act = actual exp = 'processed' ).
ENDMETHOD.

ABAP OO Test Double Framework

" Create test double for class
DATA(double) = CAST zif_my_interface(
  cl_abap_testdouble=>create( 'ZIF_MY_INTERFACE' ) ).

" Configure method behavior
cl_abap_testdouble=>configure_call( double
  )->returning( value = 'mocked result'
  )->and_expect( )->is_called_once( ).

" Set input expectations
cl_abap_testdouble=>configure_call( double
  )->for_method( 'GET_DATA'
  )->with_parameters(
       VALUE #( ( name = 'ID' value = 1 ) )
  )->returning( VALUE #( ( id = 1 name = 'Test' ) ) ).

" Verify interactions
cl_abap_testdouble=>verify_expectations( double ).

SQL Test Double Framework

CLASS ltc_sql_test DEFINITION FOR TESTING
  RISK LEVEL HARMLESS DURATION SHORT.

  PRIVATE SECTION.
    CLASS-DATA sql_env TYPE REF TO if_osql_test_environment.

    CLASS-METHODS class_setup.
    CLASS-METHODS class_teardown.

    METHODS test_select FOR TESTING.
ENDCLASS.

CLASS ltc_sql_test IMPLEMENTATION.

  METHOD class_setup.
    sql_env = cl_osql_test_environment=>create(
      VALUE #( ( 'ZDEMO_TABLE' ) ) ).
  ENDMETHOD.

  METHOD class_teardown.
    sql_env->destroy( ).
  ENDMETHOD.

  METHOD test_select.
    " Insert test data
    sql_env->insert_test_data(
      VALUE zdemo_table( ( id = 1 name = 'Test' ) ) ).

    " Execute code under test
    DATA(result) = cut->read_data( ).

    " Assert
    cl_abap_unit_assert=>assert_equals(
      act = lines( result )
      exp = 1 ).

    " Clear for next test
    sql_env->clear_doubles( ).
  ENDMETHOD.

ENDCLASS.

CDS Test Double Framework

CLASS ltc_cds_test DEFINITION FOR TESTING
  RISK LEVEL HARMLESS DURATION SHORT.

  PRIVATE SECTION.
    CLASS-DATA cds_env TYPE REF TO if_cds_test_environment.

    CLASS-METHODS class_setup.
    CLASS-METHODS class_teardown.
ENDCLASS.

CLASS ltc_cds_test IMPLEMENTATION.

  METHOD class_setup.
    cds_env = cl_cds_test_environment=>create( 'ZDEMO_CDS_VIEW' ).
  ENDMETHOD.

  METHOD class_teardown.
    cds_env->destroy( ).
  ENDMETHOD.

ENDCLASS.

RAP BO Test Double Framework

" Transactional buffer double
DATA(test_env) = cl_botd_txbufdbl_bo_test_env=>create(
  src_bindings = VALUE #( ( 'ZDEMO_RAP_ROOT' ) ) ).

" Mock EML APIs
DATA(mock_env) = cl_botd_mockemlapi_bo_test_env=>create(
  environment = VALUE #( ( 'ZDEMO_RAP_ROOT' ) ) ).

Test Documentation

"! @testing zcl_class_under_test
CLASS ltc_test_class DEFINITION FOR TESTING.
  ...
ENDCLASS.

Running Tests

In ADT:

  • All class tests: Ctrl + Shift + F10
  • With coverage: Ctrl + Shift + F11
  • Right-click → Run as → ABAP Unit Test

ATC Integration:

  • Tests run as part of ABAP Test Cockpit
  • Configure in ATC check variant

Best Practices

  1. One assertion per test when possible
  2. Use Given-When-Then structure
  3. Name tests descriptively (test_calculate_returns_sum_of_inputs)
  4. Keep tests independent - no shared state between tests
  5. Use setup/teardown for common initialization
  6. Prefer constructor injection for dependencies
  7. Test public interface - avoid testing private methods directly
  8. Use appropriate risk level to enable test execution

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    A comprehensive reference for SAP ABAP development, providing documentation and code examples for both classic ABAP and modern ABAP Cloud patterns. No security issues were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    3/32 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 620a19a. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 months ago
Other metadata
metadata
{
  "maintainer": "Eduard Jiglau",
  "maintainer_email": "hello@sap-ai-skills.com",
  "website": "https://sap-ai-skills.com",
  "version": "2.4.1",
  "last_verified": "2026-04-02",
  "abap_release": "7.40 SP08+ / 7.50+ / ABAP Cloud",
  "sources": [
    "https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm",
    "https://github.com/SAP-samples/abap-cheat-sheets"
  ]
}

README badge

README badge for secondsky/sap-skills/sap-abap