ABAP Unit
ABAP Unit is the xUnit adoption for the ABAP language. ABAP Unit is directly embedded into the ABAP development environment and into the ABAP runtime environment. In ABAP Unit tests are test methods in dedicated test classes. A test class may contain several test methods. The optional methods SETUP() and TEARDOWN() offer the possibility to manage the context of the unit tests. Usually test classes are local classes within the program under tests. The domain code and the test code share this way the same life cycle and are always in sync. The test code can exercise the domain code of the program but not vice versa. This restriction is checked by ABAP runtime system and ensures the pattern "no test code in productive code". Test execution for single programs is possible from within the editors. Newer versions of ABAP Unit (>= SAP_BASIS 7.02) offer an integration with coverage metrics and a report to schedule automatic test execution with mail notification. ABAP Unit offers no feature to define test suites programmatically. Mass runs for entire packages can be executed with the Code Inspector integration only. A mocking framework inspired by the fluent interface of EasyMock is provided with the ABAP class CL_ABAP_TESTDOUBLE. Test seams (since ABAP release 7.50) allow rewriting productive code during unit tests. This allows, for example, database accesses or RFC calls to be overwritten in unit tests.
The topic of this article may not meet Wikipedia's general notability guideline. (July 2014) |
ABAP Unit is the xUnit adoption for the ABAP language. ABAP Unit is directly embedded into the ABAP development environment and into the ABAP runtime environment.
In ABAP Unit tests are test methods in dedicated test classes. A test class may contain several test methods. The optional methods SETUP() and TEARDOWN() offer the possibility to manage the context of the unit tests. Usually test classes are local classes within the program under tests. The domain code and the test code share this way the same life cycle and are always in sync. The test code can exercise the domain code of the program but not vice versa. This restriction is checked by ABAP runtime system and ensures the pattern "no test code in productive code".
Test execution for single programs is possible from within the editors. Newer versions of ABAP Unit (>= SAP_BASIS 7.02) offer an integration with coverage metrics and a report to schedule automatic test execution with mail notification. ABAP Unit offers no feature to define test suites programmatically. Mass runs for entire packages can be executed with the Code Inspector integration only.
A mocking framework inspired by the fluent interface of EasyMock is provided with the ABAP class CL_ABAP_TESTDOUBLE.
Test seams (since ABAP release 7.50) allow rewriting productive code during unit tests. This allows, for example, database accesses or RFC calls to be overwritten in unit tests.
Sample
[edit]REPORT z_test_aunit.
CLASS lcl_constants DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS class_constructor.
INTERFACES zif_constants. "Public interface with the method GET_CONSTANT
CLASS-DATA lo_instance TYPE REF TO lcl_constants READ-ONLY.
ENDCLASS.
CLASS lcl_constants IMPLEMENTATION.
METHOD class_constructor.
lo_instance = NEW #( ).
ENDMETHOD.
METHOD zif_constants~get_constant.
CASE iv_name.
WHEN `Pi`.
rv_value = '3.14'.
ENDCASE.
ENDMETHOD.
ENDCLASS.
CLASS: lct_math DEFINITION DEFERRED.
CLASS lcl_math DEFINITION FRIENDS lct_math. "Allow access to private attributes for the test class.
PUBLIC SECTION.
METHODS: constructor,
quotient IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_c) TYPE i
RAISING cx_sy_arithmetic_error,
area_circle IMPORTING iv_r TYPE i
RETURNING VALUE(rv_a) TYPE f.
PRIVATE SECTION.
DATA mo_constants TYPE REF TO zif_constants.
ENDCLASS.
CLASS lcl_math IMPLEMENTATION.
METHOD constructor.
mo_constants = lcl_constants=>lo_instance.
ENDMETHOD.
METHOD quotient.
IF iv_b = 0.
RAISE EXCEPTION TYPE cx_sy_zerodivide.
ELSE.
rv_c = iv_a / iv_b.
ENDIF.
* TEST-SEAM bla.
* WRITE 'test'.
* END-TEST-SEAM.
ENDMETHOD.
METHOD area_circle.
rv_a = iv_r ** 2 * mo_constants->get_constant( `Pi` ).
ENDMETHOD.
ENDCLASS.
CLASS lct_math DEFINITION FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PUBLIC SECTION.
METHODS t_quotient_1 FOR TESTING.
METHODS t_quotient_2 FOR TESTING.
METHODS t_area_circle_1 FOR TESTING.
PRIVATE SECTION.
METHODS setup.
* METHODS teardown.
* CLASS-METHODS class_setup.
* CLASS-METHODS class_teardown.
DATA mo_cut TYPE REF TO lcl_math. "Class under testing
ENDCLASS.
CLASS lct_math IMPLEMENTATION.
METHOD setup.
mo_cut = NEW #( ).
* TEST-INJECTION bla.
* END-TEST-INJECTION.
ENDMETHOD.
METHOD t_quotient_1.
cl_aunit_assert=>assert_equals(
act = mo_cut->quotient( iv_a = 6 iv_b = 3 )
exp = 2
).
ENDMETHOD.
METHOD t_quotient_2.
TRY.
mo_cut->quotient( iv_a = 1 iv_b = 0 ).
cl_aunit_assert=>fail( ).
CATCH cx_sy_arithmetic_error INTO DATA(lo_error).
* cl_aunit_assert=>assert_bound( lo_error ).
ENDTRY.
ENDMETHOD.
METHOD t_area_circle_1.
DATA(lo_constants_mock) = CAST zif_constants( cl_abap_testdouble=>create( `ZIF_CONSTANTS` ) ).
cl_abap_testdouble=>configure_call( lo_constants_mock )->returning( CONV f( '3' ) )->and_expect( )->is_called_once( ).
lo_constants_mock->get_constant( `Pi` ).
mo_cut->mo_constants = lo_constants_mock. "Overwriting the real dependency with the mock object
cl_aunit_assert=>assert_equals(
act = mo_cut->area_circle( 2 )
exp = 12
).
cl_abap_testdouble=>verify_expectations( lo_constants_mock ).
ENDMETHOD.
ENDCLASS.