ABAP Unit Testing

Unit Testing is one of the corner stones of TDD ( Test Driven Development ). The main goal of  Unit Testing is to test each individual units of code, and determine if it behaves as you designed it to. Each piece of the "puzzle" is tested independently before being integrated into the larger problem you wish to solve. Finding an error in the complete code is much more complex than isolating each unit and then testing it before integrating it into you code.

The biggest resistance to UNIT Testing is the amount of time required to create the tests when you are dealing with a deadline. But there are there are some evidences that TDD and Unit Testing while having an incease of 10-15% in initial time of development, produce a 40-90% decrease in pre-release defects. This are links from Nachiappan Nagapan (link1link2) and another from Boby George and Laurie Williams (link 3)

Unit Tests provide a safety net of regression tests and validation tests so that you can re-factor and integrate effectively. Creating the unit test before the code helps even further by solidifying the requirements, improving developer focus, and avoid creeping elegance.


SAP provides an embedded framework called ABAP UNIT to aid the Test Driven Development approach.


As a basic example we will use our simple Regular Expression email validation program:

http://abapdevblog.blogspot.pt/2013/08/regular-expressions-in-abap-part-1.html


*&---------------------------------------------------------------------*
*& Report  Z_REGEX_EMAIL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT  z_regex_email.

SELECTION-SCREEN BEGIN OF SCREEN 100.
PARAMETERS email TYPE c LENGTH 30 LOWER CASE.
SELECTION-SCREEN END OF SCREEN 100.

CLASS lcl_test_class DEFINITION DEFERRED.

*----------------------------------------------------------------------*
*       CLASS lcl_demo DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_demo DEFINITION
  FRIENDS lcl_test_class. " So that we can test Private & protected methods

  PUBLIC SECTION.
    METHODS: constructor,
            main.
  PRIVATE SECTION.
    METHODS: is_email_valid IMPORTING value(im_email) TYPE char30
                            RETURNING value(re_bool) TYPE abap_bool.

    DATA: mv_email_regex TYPE string.

ENDCLASS.                    "public SECTION.


*----------------------------------------------------------------------*
*       CLASS lcl_demo IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_demo IMPLEMENTATION.
  METHOD constructor.

    " the regular expression to validate the email was retrieved
    " from this wonderful site http://www.regular-expressions.info/
    " which is a great source of knowlege regarding Regular Expression
    mv_email_regex =  '\w+(\.\w+)*@(\w+\.)+((\l|\u){2,4})'.

  ENDMETHOD.                    "class_constructor
  METHOD main.

    CALL SELECTION-SCREEN 100.

    " We use the predifined string function MATCH
    IF abap_true EQ is_email_valid( email ).
      " The Email Matches the Regular expression
      MESSAGE 'Format matches' TYPE 'S'.
    ELSE.
      " There is no match between the email and the regular expression
      MESSAGE 'Format does not Match!' TYPE 'S' DISPLAY LIKE 'E'.
    ENDIF.

  ENDMETHOD.                    "main

  METHOD is_email_valid.
    IF matches( val   = im_email
                regex = mv_email_regex ).
      " The Email Matches the Regular expression
      re_bool = abap_true.
    ELSE.
      re_bool = abap_false.
    ENDIF.
  ENDMETHOD.                    "is_email_valid

ENDCLASS.                    "lcl_demo IMPLEMENTATION



START-OF-SELECTION.
  DATA: lo_demo TYPE REF TO lcl_demo.

  CREATE OBJECT lo_demo.
  lo_demo->main( ).



*----------------------------------------------------------------------*
*       CLASS lcl_Test_Class DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_test_class DEFINITION FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.

  PRIVATE SECTION.
* ================
    DATA:
          f_cut TYPE REF TO lcl_demo.  "class under test


    CLASS-METHODS: class_setup.
    CLASS-METHODS: class_teardown.
    METHODS: setup.
    METHODS: teardown.
    METHODS: email_is_valid FOR TESTING.
    METHODS: email_is_not_valid FOR TESTING.

ENDCLASS.       "lcl_Test_Class
*----------------------------------------------------------------------*
*       CLASS lcl_Test_Class IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_test_class IMPLEMENTATION.
* ====================================

  METHOD class_setup.
* ===================


  ENDMETHOD.       "class_Setup


  METHOD class_teardown.
* ======================


  ENDMETHOD.       "class_Teardown


  METHOD setup.
* =============

    CREATE OBJECT f_cut.
  ENDMETHOD.       "setup


  METHOD teardown.
* ================


  ENDMETHOD.       "teardown

  METHOD email_is_valid.

    cl_abap_unit_assert=>assert_equals(
    EXPORTING
      exp                  = abap_true
      act                  = f_cut->is_email_valid( 'VALID.EMAIL@EMAIL.COM' ) ).

  ENDMETHOD.                    "email_is_valid

  METHOD email_is_not_valid.

    cl_abap_unit_assert=>assert_equals(
    EXPORTING
      exp                  = abap_false
      act                  = f_cut->is_email_valid( 'INVALID@email' ) ).

  ENDMETHOD.                    "email_is_not_valid

ENDCLASS.       "lcl_Test_Class



As you can see we made a couple of changes to the initial program:
  • First the methods from lcl_demo are no longer static methods but instance methods. 
    • This was to show you that the ABAP Unit Framework provides you with some fixture methods to help setup your test data and test object.

  METHOD setup.
* =============
    " There is a SETUP method in a test class, into which you
    " can relocate the data setup that is required before each test.

    CREATE OBJECT f_cut. " we create the instance of the class under test

  ENDMETHOD.       "setup

  • The lcl_demo now has as a friend the new lcl_test_class which has its definition deferred to make the class lcl_test_class known to lcl_demo, regardless of the location of the actual definition of the class in the program. The friendship part is important so that we can grant lcl_test_class access to the protected and private members of lcl_demo class.

CLASS lcl_test_class DEFINITION DEFERRED.

*----------------------------------------------------------------------*
*       CLASS lcl_demo DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_demo DEFINITION
  FRIENDS lcl_test_class. " So that we can test Private & protected method


  • Then we have our new lcl_test_class with a special definition

CLASS lcl_test_class DEFINITION FOR TESTING
                     DURATION SHORT
                     RISK LEVEL HARMLESS.


    • The FOR TESTING addition is used to defined a class as a test class for the ABAP Unit tool.
    • These additions assign test properties to a test class. RISK LEVEL defines the risk level for a test and DURATION the expected execution time. The test properties are checked during when the test is executed. Tests whose risk level is higher than allowed in a system are not executed. Tests that run longer than the expected execution time are terminated.  


    • And our test methods.

    METHODS: email_is_valid FOR TESTING.
    METHODS: email_is_not_valid FOR TESTING.

  METHOD email_is_valid.

    cl_abap_unit_assert=>assert_equals(
    EXPORTING
      exp                  = abap_true
      act                  = f_cut->is_email_valid( 'VALID.EMAIL@EMAIL.COM' ) ).

  ENDMETHOD.                    "email_is_valid

  METHOD email_is_not_valid.

    cl_abap_unit_assert=>assert_equals(
    EXPORTING
      exp                  = abap_false
      act                  = f_cut->is_email_valid( 'INVALID@email' ) ).

  ENDMETHOD.                    "email_is_not_valid


In out initial coding we had a program while re-factoring the is_email_vaild method and introduced a bug. we forgot to change out match variable from email to the importing parameter im_email.


  METHOD is_email_valid.
    IF matches( val   = email
                regex = mv_email_regex ).
      " The Email Matches the Regular expression
      re_bool = abap_true.
    ELSE.
      re_bool = abap_false.
    ENDIF.
  ENDMETHOD.                    "is_email_valid



So when we tested our code  (Ctrl+Shift+F10) we got the following report showing that we have an error.


Execute the Unit Tests



ABAP Unit Report

Being an easy fix we change the code so that we use the import parameter im_email.


  METHOD is_email_valid.
    IF matches( val   = im_email
                regex = mv_email_regex ).
      " The Email Matches the Regular expression
      re_bool = abap_true.
    ELSE.
      re_bool = abap_false.
    ENDIF.
  ENDMETHOD.                    "is_email_valid

Testing again produces the message saying that our method passed all the tests.


Our Unit Tests Passed


9 comments:

  1. Thank for sharing this unit testing, I also have ABAP programming blog, I will post about unit testing soon.

    ReplyDelete
  2. Thanks for sharing this useful information with all of us... SAP Audit Information System ecc6

    ReplyDelete
  3. SAP Training

    Thanks for sharing this valuable information.and I gathered some information from this blog. I did SAP Training in Chennai, at FITA Academy which offer best SAP Course in Chennai with years of experienced professionals.

    ReplyDelete
  4. SAP ABAP Online Training will help you have faster and more cost-effective initial implementations. The best thing about Smartmind online training provides SAP ABAP online training combines business, academic and technical skills that are beneficial to their students.
    This combination broadens students' understanding of the theories and applications of information technology.
    SAP ABAP Online Training

    ReplyDelete
  5. Its a grate ABAP Unit Testing place, IT can help the abap developement. Nice post.. Proffesional Blogger of Web Knowledge Free

    ReplyDelete
  6. http://best-sap-abap-online-training.blogspot.in/2013/05/sap-abap-online-training-from-india.html?showComment=1436525354352#c3203977278118108221

    ReplyDelete
  7. Improve your software system with the different services of technique system please follow us on :- So Computer System Validation much nature by the side of best or high quality is ordering

    by the side of getting in the places Validation Change Management with the main purpose it

    has to be best placed in common none extra or added ways. There is simple on the other access the side Validation Software of

    logical item or obsessions all being eth part by the side of Electronic Validation ordering levels.

    ReplyDelete