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_failurecx_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_typeobj_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.