Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
vonglan
Active Participant

The ABAP Test Cockpit (ATC) can easily be configured to check every transport request that is released.

But in case you are using transport of copies to import into the quality/test system (for example if you use SAP ChaRM for transport management), it is not possible in the standard to perform the ATC checks automatically when transporting from development to quality/test system.

On the other hand, in various places, for example the SAP Code Inspector book by Randolf Eilenberger and others, it is described how to trigger a Code Inspector test for every transport task release.

I have not yet found a description how to call the ATC automatically, when a transport task is released.

If this is what you want in your development system, you only have to implement one method in an implementation of BAdI CTS_REQUEST_CHECK:

METHOD if_ex_cts_request_check~check_before_release.

  DATA is_ok TYPE abap_bool VALUE abap_true.

  SELECT SINGLE trfunction, strkorr FROM e070 WHERE trkorr = @request

                              INTO (@DATA(trfunction), @DATA(strkorr)).

  ASSERT sy-subrc = 0.

  " only process release of transport tasks,

  " not transport requests.

  " And only customer code (not repairs, not customizing).

  CHECK strkorr IS NOT INITIAL AND trfunction = 'S'.

  TRY.

      DATA(or_factory) = NEW cl_satc_api_factory( ).

      DATA(it_objects) = cl_satc_object_set_factory=>create_for_transport( request

                                                             )->if_satc_object_set~get_object_keys( ).

      DATA(or_objects) = cl_satc_object_set_factory=>create_for_object_keys( it_objects ).

      DATA(or_variant) = NEW cl_satc_ci_check_variant( ).

      or_variant->set_name( 'Z_STANDARD' ).  " replace with your check variant

      DATA(or_run_config) = or_factory->create_run_config_with_chk_var( EXPORTING i_object_set = or_objects

                                                                                                                  i_check_variant = or_variant

                                                                                                                  i_description = |Transport release { request } | ).

      DATA(or_run_controller) = or_factory->create_run_controller( or_run_config ).

      or_run_controller->run( IMPORTING e_result_access = DATA(or_result_access) ).

      or_result_access->get_findings( IMPORTING e_findings = DATA(it_f) ).

      LOOP AT it_f ASSIGNING FIELD-SYMBOL(<wa_f>) WHERE ( kind = 'E' OR kind = 'W' ) " errors/warnings

                                                    AND exceptn <> 'P'. " pseudo comments and pragmas

        is_ok = abap_false.

        EXIT.

      ENDLOOP.

    CATCH cx_satc_failure cx_satc_not_found INTO DATA(cx).

      DATA(exc_text) = cx->get_text( ).

      MESSAGE exc_text TYPE 'E'.

      is_ok = abap_false.

    CATCH cx_satc_empty_object_set cx_satc_invalid_argument INTO cx" ok, if transport is empty or contains only non-checkable objects

  ENDTRY.

  IF is_ok = abap_true.

    MESSAGE s007(zs_dev_tools_local).  " success message - create your own message

  ELSE.

    MESSAGE s008(zs_dev_tools_local).  " failure message - create your own message

    " we only get the execution ID with this "dirty" cast:

    DATA(or_result_access_int) = CAST cl_satc_result_access( or_result_access ).

    CALL FUNCTION 'SATC_AC_DISPL_RESULT_BY_EXEC'

      EXPORTING i_execution_id = or_result_access_int->if_satc_result_access~result_id

      EXCEPTIONS

        xpt_no_results     = 1

        xpt_not_authorized = 2

        xpt_display_used   = 3

        OTHERS             = 4.

    ASSERT sy-subrc = 0.

    RAISE cancel.

  ENDIF.

ENDMETHOD.

(This coding uses some of the new 7.40 SP08 language features, so you may have to adapt it.)

That’s it, basically.

I noted however, that include programs are not tested when transported on their own, because the ATC methods that I call only test frame programs (type 1 reports, classes, function groups). I did not find an easy way to overcome this using standard ATC framework functions, so I programmed it in a local class with the following methods:

  CLASS-METHODS:

      enrich_main_programs

        CHANGING c_it_keys                  TYPE if_satc_object_set=>ty_object_keys,

      is_include_program

        IMPORTING i_object                    TYPE if_satc_object_set=>ty_object_key

        RETURNING VALUE(r_is_include_program) TYPE abap_bool,

      get_main_programs_for_include

        IMPORTING i_object    TYPE if_satc_object_set=>ty_object_key

        RETURNING VALUE(r_it) TYPE if_satc_object_set=>ty_object_keys,

      is_mainprog_included

        IMPORTING

                  i_it_mainprogs    TYPE if_satc_object_set=>ty_object_keys

                  i_it_current_keys TYPE if_satc_object_set=>ty_object_keys

        RETURNING VALUE(r) TYPE abap_bool,

  METHOD enrich_main_programs.

    LOOP AT c_it_keys ASSIGNING FIELD-SYMBOL(<wa>).

      IF is_include_program( <wa> ).

        DATA(it_main_programs) = get_main_programs_for_include( <wa> ).

        IF it_main_programs IS NOT INITIAL

           AND NOT is_mainprog_included( EXPORTING i_it_mainprogs = it_main_programs

                                                   i_it_current_keys  = c_it_keys ).

          INSERT it_main_programs[ 1 ] INTO TABLE c_it_keys.

        ENDIF.

      ENDIF.

    ENDLOOP.

  ENDMETHOD.

  METHOD is_include_program.

    r_is_include_program = abap_false.

    CHECK i_object-obj_type = 'PROG'.

    SELECT SINGLE subc FROM reposrc WHERE progname = @i_object-obj_name AND subc = 'I'

                                           INTO @DATA(subc) ##warn_ok ##needed.

    IF sy-subrc = 0.

      r_is_include_program = abap_true.

    ENDIF.

  ENDMETHOD.

  METHOD get_main_programs_for_include.

    DATA it_mainprogs LIKE STANDARD TABLE OF i_object-obj_name.

    DATA wa LIKE LINE OF r_it.

    CLEAR r_it. " if there are no main programs, return initial

    CALL FUNCTION 'RS_GET_MAINPROGRAMS'

      EXPORTING

        name         = i_object-obj_name

      TABLES

        mainprograms = it_mainprogs

      EXCEPTIONS

        cancelled    = 1

        OTHERS       = 2.

    ASSERT sy-subrc = 0.

    wa-obj_type = 'PROG'.

    LOOP AT it_mainprogs ASSIGNING FIELD-SYMBOL(<wa>).

      wa-obj_name = <wa>.

      INSERT wa INTO TABLE r_it.

    ENDLOOP.

  ENDMETHOD.

  METHOD is_mainprog_included.

    r = abap_false.

    LOOP AT i_it_mainprogs ASSIGNING FIELD-SYMBOL(<wa>).

      READ TABLE i_it_current_keys WITH KEY obj_type = <wa>-obj_type obj_name = <wa>-obj_name

                                  TRANSPORTING NO FIELDS.

      IF sy-subrc = 0.

        r = abap_true.

        RETURN.

      ENDIF.

    ENDLOOP.

  ENDMETHOD.

Now, enrich_main_programs() needs to be called to change it_objects after the statement that is creating it_objects.

Edit 25.04.2016: exception handling for cx_satc_invalid_argument added.

13 Comments