Blogs

Christian Drumm

Continuous Integration using Code Inspector
Christian Drumm 
Business Card
Company: DSC Unternehmensberatung und Software GmbH
Posted on Dec. 30, 2009 09:23 PM in ABAP, CRM, ERP, Ruby, SAP NetWeaver Platform

Subscribe.Subscribe
Print. Print
Permalink Permalink
Share

Introduction

According to Martin Fowler Continuous Integration is:

a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible."

A nice introduction to the topic is available his article here. In order to support continuous integration a number of software tools are available. In case you have never seen such a tool the Wikipedia article on Continuous Integration contains links to quite some of them. The main feature of these tools is to perform an automated build, execute all the available tests and create a report of the results either after each change to the code base or in predefined intervals. How the automated builds and test are executed depends heavily on the type of development projects and the used technologies.

For software development in ABAP in the context of SAP several tools exist to enabling to ensure code quality. ABAP Unit and the SAP Code Inspector (SCI) are just two of them. This blog describes how one can setup a continuous integration server mainly based on SAP Code Inspector. Furthermore, a brief example is provided how "build results" can be exported and processed in order to integrate them with existing tools.

Continuous Integration Server using SAP Code Inspector

The SAP Code Inspector (SCI) provides most of the functionality necessary to build a continuous integration server. It can be used to perform syntax checks, check for coding conventions (although I'm not a fan of strict coding conventions; anyone who still is should read "Clean Code: A Handbook of Agile Software Craftsmanship" by Robert C. Martin), calculate program metrics, execute performance checks and also execute ABAP Unit Test. Furthermore, SCI is extensible. One can easily write own tests and execute them together with the tests provided by SAP. Possible extensions could be the evaluation of the ABAP Unit test coverage or the execution of Selenium test scripts (cf. Automate Web Application Testing with Selenium for ABAP).

The blog Automating ABAP Unit Test Runs with the Code Inspector by Stephen Pfeiffer provides a nice description on how to setup SCI to periodically execute ABAP Unit Tests. While automatically executing ABAP Unit Test periodically is a nice first step, SCI requires a user to manually check test results. As existing continuous integration servers usually either send emails to developers or create Web-based reports my goal was to setup something similar with SCI.

After creating an inspection with the name ZC_LOY_EXT_SFW_INSPECTION and setting it up for periodic execution I took a look at the background jobs using SM37. Setting up an inspection for periodic execution simply creates a background job named something like CODEINSP_<InspectionName>_<InspectionVersion>. This background job consists of only one step executing the report RS_CI_PARALLEL. The report RS_CI_PARALLEL is part of the package S_CODE_INSPECTOR. The package contains several reports (cf. following figure) including RS_CI_EMAIL which, according to the description, can be used to send email notifications of SCI results.

 

image

Execution this report with the appropriate parameters (cf. following figure) sends an email containing all results of the inspection to the email address stored in user data.

image

The Email created by the delivered template looks similar to this:

Errors occurred
Hello Christian,
during the run of inspection "ZC_LOY_EXT_SFW_INSPECTION"
Version "004"
of codeinspector in *** at 30.12.09 there
occurred the following errors:
Syntax Check - ZC_CL_SFW_DEFAULTBALLOGGER  Line 000004 :   The exception ZCX_SFW_CUTOMIZINGEXP is
neither caught nor is it declared in the RAISING clause of
"GET_INSTANCE".
ABAP Unit - ZC_CL_SFW_DEFAULTBALLOGGER  Line 000226 : 
Critical Assertion Error: 'Test is not implemented yet'
....

The next thing I did was creating a screen variant with these values. Using SM36 I added an additional step to the background job to execute RS_CI_EMAIL after each inspection run. To be able to do this I had to change the status of the exiting background job, add the step and release the background job again. Now each time an inspection is executed through the background job the latest inspection results are mailed to my.

Automating Code Inspector Execution

As setting up the email notification for inspection results manually is rather cumbersome. Instead it would be nice to have a report that automatically performs the required steps for scheduling periodic SCI runs and the result notification via email. The following code snipplet does exactly this.


TYPE-POOLS: abap.

CONSTANTS: co_job_prefix TYPE string VALUE 'CI_CODEINSP_', "prefix of the created background job
co_package_name TYPE string VALUE 'ZC_LOY_EXT_SFW', "package names
co_check_var_name TYPE sci_chkv VALUE 'MY_DEFAULT_CHECK_VAR'. "name of the used check var

DATA: inspection TYPE REF TO cl_ci_inspection,
object_set TYPE REF TO cl_ci_objectset,
check_variant TYPE REF TO cl_ci_checkvariant,

inspection_name TYPE sci_insp,
object_set_name TYPE sci_objs,
object_set_select_options TYPE scistadir,
object_set_flags TYPE sci_flgl,
job_name TYPE btcjob,
job_count TYPE btcjobcnt.

FIELD-SYMBOLS: TYPE scir_devc.


"Get the reference to the check variant that we want to use
check_variant = cl_ci_checkvariant=>get_ref( p_user = sy-uname
p_name = co_check_var_name ).

"Create an object set
CONCATENATE co_package_name '_OBJECTS' INTO object_set_name.
object_set = cl_ci_objectset=>create( p_user = sy-uname
p_name = object_set_name ).

"The object set includes the packages and its subpakages (by name)
APPEND INITIAL LINE TO object_set_select_options-sodevc ASSIGNING .
-sign = 'I'.
-option = 'CP'.
CONCATENATE co_package_name '*' INTO -low.

"All object types are included
object_set_flags-class = object_set_flags-fugrs = object_set_flags-repos = abap_true.
object_set_flags-wdyns = object_set_flags-ddics = object_set_flags-typps = abap_true.

object_set->save_objectset( p_tadir = object_set_select_options
p_sel_flags = object_set_flags ).

"Create and save the inspection
CONCATENATE co_package_name '_INSPECTION' INTO inspection_name.
inspection = cl_ci_inspection=>create( p_user = sy-uname
p_name = inspection_name ).
inspection->set( p_chkv = check_variant
p_objs = object_set ).
inspection->save( ).

"Create the background job....
CONCATENATE co_job_prefix co_package_name INTO job_name.

"First open a new job
CALL FUNCTION 'JOB_OPEN'
EXPORTING
jobname = job_name
IMPORTING
jobcount = job_count
EXCEPTIONS
OTHERS = 1.

IF sy-subrc <> 0.
MESSAGE ID 'SCI' TYPE 'E' NUMBER '146' WITH job_name.
ENDIF.

"Add the execution of the inspection
SUBMIT rs_ci_parallel VIA JOB job_name
NUMBER job_count
WITH rfcgroup = 'code_inspector'
WITH id = inspection->inspecinf-inspecid
WITH user = inspection->inspecinf-ciuser
WITH vers = inspection->inspecinf-inspecvers
AND RETURN.

"Add sending the inspection results via email
SUBMIT rs_ci_email VIA JOB job_name
NUMBER job_count
WITH user = inspection->inspecinf-ciuser
WITH inspect = inspection_name
WITH lastvers = abap_true
WITH all2me = abap_true
WITH vorlage = 'RS_CI_EMAILTEMPLATE'
AND RETURN.

"Release the job
CALL FUNCTION 'JOB_CLOSE'
EXPORTING
jobcount = job_count
jobname = job_name
prdmins = 5
strtimmed = abap_true
EXCEPTIONS
OTHERS = 1.

IF sy-subrc <> 0.
MESSAGE ID 'SCI' TYPE 'E' NUMBER '146'
WITH job_name.
ENDIF.

The code above assumes the existence of a check variant named MY_DEFAULT_CHECK_VAR. It creates an object set for the inspection that contains all objects in packages starting with the string ZC_LOY_EXT_SFW. Using the create object set and the check variant an inspection is create. Finally a background job executing the created inspection as well as the email notification is created. In this example the background job is setup to run every 5 minutes. So be careful not to flood your inbox ;)

Integration with existing Tools

Another thing, besides the email notification, that might be required is the integration of the inspection results into existing tools. For example, in a larger project the inspection results from SCI could need to be integrated with the reports generated by other tools. An integration of SCI with existing tools can also be achieved. As an example the following code exports the inspection results as XML using simple transformations:

CONSTANTS: co_user_name LIKE sy-uname VALUE 'DRUMM',
co_inspection_name TYPE sci_insp VALUE 'ZC_LOY_EXT_SFW_INSPECTION'.

DATA: inspection TYPE REF TO cl_ci_inspection,
xml_writer TYPE REF TO cl_fx_writer,
result_list TYPE scit_alvlist,
result_xml TYPE string,
result_table TYPE TABLE OF string.

inspection = cl_ci_inspection=>get_ref( p_user = co_user_name
p_name = co_inspection_name ).

inspection->plain_list( IMPORTING p_list = result_list ).

CALL TRANSFORMATION id_par OPTIONS xml_header = 'no'
SOURCE results = result_list RESULT XML result_xml.

APPEND result_xml TO result_table.

cl_gui_frontend_services=>gui_download(
EXPORTING
filename = 'C:/tmp/results.xml'
replacement = ''
CHANGING
data_tab = result_table
EXCEPTIONS
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
not_supported_by_gui = 22
error_no_gui = 23
OTHERS = 24
).
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
 

The exported file could now be used to integrate the inspection results with exisitng tools. As an example I created a ruby script that converts the exported file into a simple HTML report. The resulting HTML report looks something like this.

image

Christian Drumm   works as a Project Manager at DSC Gmbh in Schriesheim.


Comment on this articleWhere to go from here? I guess the next logical step would be to test this setup in a real project. Furthermore an integration of the described functionality with other community tools e.g. ZAKE and the ZAKE-SVN integration would be interesting. Let me know what you think.
Comment on this weblog
Showing messages 1 through 2 of 2.

Titles Only Main Topics Oldest First

  • Version..
    2010-01-06 19:53:28 sasmito handoko Business Card [Reply]

    is the program RS_CI_EMAIL exist in all version of SAP ? or only at version ECC 6.0 ?
    im using ECC 5 and didnt find that program inside the package S_CODE_INSPECTOR
    • Version..
      2010-01-07 00:47:53 Christian Drumm Business Card [Reply]

      Hi Sasmito,


      good question. I did my experiments in systems based on NW 7.0 and NW 2004s. The report was present in both of them.


      However, if the report is not present in your system it is fairly easy to write a similar report manually. All RS_CI_EMAIL does is to read the inspection results as a plain list (cf. the second listing in my blog), create a email consisting of some initial text and the inspection results and send this email using CL_BCS.


      Hope this helps.


      Christian


Showing messages 1 through 2 of 2.