I have used this testing technique during one of my test phase, where we were testing the portal applications

This test technique is applicable where we have portal application & equivalent functionality in R/3(back-end) as well.

I will take the examples from EAM where we have portal & R/3 transactions available to create/change/display the objects Equipment, Functional Location, Orders, Task list, Notifications etc.


Portal applications have its own benefits, End User need not to remember all the transactions. But at the same time its mandatory functionality should behave same whether it’s is launched from portal or R/3 transactions.

We have tested different combinations and ensured that functionality is behaving in same manner in all the cases. Wherever this deviates from expected behavior we can analyze the behavior further & report an issue.

If we test both (R/3 & portal) of them separately without comparison, it’s difficult to validate the exact & expected behavior.

 

Prerequisites:  

  • Portal configurations for system should already be taken care.
  • User Roles

 

I have described below few aspects of functionality which we should test.

Few Combinations which we validated were:


Open the object in change mode in portal & try changing it in R/3 and vice verse.      

Expected results are: object should be locked & not available for changes.


Change few customization in R/3 and check in portal for the impact.

Expected results are: customization change should have impact on portal too.


Create Object in Portal & check in R/3 transaction/ tables & vice verse.   

Expected results are: Objects created in portal should be available in database table in back-end system.


Block the Object status as inactive in R/3.   

Expected results are:  Status should be updated on portal for respective object & we should not be able to change it any further.


There are many other cases/combinations which can be compared. With this test technique we can ensure the functionality is robust & identical, does not change its behavior with change in test environment or technology.


This article might be useful for testers who are testing the portal & will help them in designing there testing  even better.

I will further share my findings & new ways of testing for any new  functionality from my future test phases.

                           

Summary

This blog is about changing the way of work of Source Code Inspector(tcode:SCI) especially when Transport Organizer integration is activated. Transport Organizer integration can be activated using tcode SE03. Thanks to SAP for this talented and flexible tool.

 

Problem

In one of our projects we needed to seperate SCI controls according to creation date of objects. We needed this because afore mentioned project is started 12 years ago and as you guess quality and security standarts are changed over time. At sometime integration of SCI/ATC and Tranport  Organizer(SE01) is activated. So developers can not release a request before handling errors given by SCI. But how can you force developer who made just single line of change to a huge program? How can he/she handle all errors given after checks without knowing semantics of this huge program? What if this change should be transported to production system immediately? The solution was to seperate check variants according to creation date of objects .

Also periodic checks can be planned to adduct old objects to new standarts.

 

In this blog i will try to explain what I did to workaround this issue. To benefit from the solution you should be familiar with adding your own test class to SCI.

You can find information about adding your own test class to SCI at : http://scn.sap.com/community/abap/blog/2006/11/02/code-inspector--how-to-create-a-new-check and http://wiki.scn.sap.com/wiki/download/attachments/3669/CI_NEW_CHECK.pdf?original_fqdn=wiki.sdn.sap.com

 

Solution summary

First, I created a test class ZCL_SCI_TEST_BYDATE (derived from CL_CI_TEST_ROOT) that has just 2 parameters date (mv_credat) and check variant(mv_checkvar). This class decides if tests in mv_checkvar is required for the object under test by checking creation date . If object is 'new' it runs additional tests.

 

Secondly, I created two SCI check variants : BASIC_VARIANT and EXTENDED_VARIANT. The first one is for old development objects and second one is for additional tests for ‘new’ objects. ‘new’ means that object is created after certain date(ZCL_SCI_TEST_BYDATE->mv_credat). First check variant includes my custom test which is mentioned above (ZCL_SCI_TEST_BYDATE) and EXTENDED_VARIANT is given as mv_checkvar parameter. Also second check variant is complementary for the first one and includes different tests than the first one.

 

Finally, to enable navigation by double clicking at check results I had to make one simple repair and 2 enhancements.

 

Step 1 : ZCL_ SCI_TEST_BYDATE class :


 

Most important method of this class is -normally- run() .

run method checks if object is created after date mv_checkvar, gets test list for EXTENDED_VARIANT and starts new test procedure for new test list.

 

  1. METHOD run.
  2. DATA lo_test_ref TYPEREF TO cl_ci_tests .
  3. * Check whether the object is created after mv_credat
  4. IF me->is_new_object()NE abap_true .
  5. EXIT.
  6. ENDIF.
  7.   me->modify_insp_chkvar(RECEIVING eo_test_list = lo_test_ref ).
  8. * RUN_BEGIN
  9.   lo_test_ref->run_begin(
  10. EXPORTING
  11.       p_no_aunit ='X'
  12.       p_no_suppress ='X'
  13.       p_oc_ignore ='X').
  14. * RUN
  15.   lo_test_ref->run( p_object_type = object_type
  16.                     p_object_name = object_name
  17.                     p_program_name = program_name ).
  18. * RUN_END
  19.   lo_test_ref->run_end().
  20. ENDMETHOD.

 

Another important method is modify_insp_chkvar which returns test list for EXTENDED_VARIANT.

 

  1. METHOD modify_insp_chkvar.
  2. * Returns test list for mv_checkvar(EXTENDED_VARIANT).
  3. * Also this method combines BASIC_VARIANT and EXTENDED_VARIANT's test lists
  4. * on INSPECTION. Just needed when check results double clicked.
  5. * (I could not handle it with MESSAGE event of CL_CI_TEST_ROOT)
  6.   DATA lo_check_var TYPE REF TO cl_ci_checkvariant .
  7.   DATA lo_check_var_insp TYPE REF TO cl_ci_checkvariant .
  8.   DATA lt_var_test_list TYPE sci_tstvar .
  9.   FIELD-SYMBOLS : <l_var_entry> TYPE sci_tstval .
  10.   CLEAR eo_test_list .
  11. * Get reference for EXTENDED_VARIANT - additional checks for new objects
  12.   cl_ci_checkvariant=>get_ref(
  13.     EXPORTING
  14.       p_user = ''
  15.       p_name = mv_checkvar
  16.     RECEIVING
  17.       p_ref = lo_check_var
  18.     EXCEPTIONS
  19.       chkv_not_exists = 1
  20.       missing_parameter = 2
  21.       OTHERS = 3 ) .
  22.   IF sy-subrc NE 0 .
  23.     MESSAGE e001(z_sci_msg) WITH mv_checkvar description . "Check variant &1-&2 does not exist.
  24.   ENDIF.
  25.   IF lo_check_var->variant IS INITIAL .
  26.     lo_check_var->get_info(
  27.       EXCEPTIONS
  28.         could_not_read_variant = 1
  29.         OTHERS                = 2 ) .
  30.     IF sy-subrc NE 0 .
  31.       EXIT .
  32.     ENDIF.
  33.   ENDIF.
  34. * Get test list of EXTENDED_VARIANT - addional checks for new objects
  35.   cl_ci_tests=>get_list(
  36.     EXPORTING
  37.       p_variant      = lo_check_var->variant
  38.     RECEIVING
  39.       p_result        = eo_test_list
  40.     EXCEPTIONS
  41.       invalid_version = 1
  42.       OTHERS          = 2 ) .
  43.   IF sy-subrc NE 0.
  44.     EXIT .
  45.   ENDIF.
  46. *...
  47. ENDMETHOD.

 

 

Important points about my custom class definition is ok now. I attached full source code.

If you want to add parameters to your custom test classes look at query_attributes, get_attributes, put_attributes methods of ZCL_SCI_TEST_BYDATE.

 

To add new test class to SCI test list I opened SCI->Management of tests and chose my new test class and clicked save button.

 

 

Step 2 : Check variants

As I mentioned before I created 2 checkvariants. Below is BASIC_VARIANT which is valid for all programs.Selected test list in figures below is just an example. Notice that my new test ‘Additional tests for new programs’ is selected. Parameters of new test can be seen in this picture.

 

 

Next picture depicts second checkvariant which is valid for objects created after ’01.01.2014’ (mv_date).

 

 

PS: SE01 uses SCI checkvariant TRANSPORT as default. But there is a way to change this – thanks to SCI : I changed default checkvariant with my BASIC_VARIANT. To achieve this I changed the SCICHKV_ALTER table’s record which has ‘TRANSPORT’ at CHECKVNAME_DEF field.

Note that AFAIK DEFAULT checkvariant is used by SE80, so it is modifiable too .


Step 3 : Adding check results of custom test class to SCI.

 

-This step is not related to the main idea, first 2 steps are sufficient to express my idea-

 

After creation of new test class and checkvariants I had been able to run additional checks for new objects but SCI result list was not navigating to EXTENDED_VARIANT’s test results when I double clicked. As I guess SCI is just aware of BASIC_VARIANT’s test list and can not navigate to unknown test’s results. I should add my additional tests to inspection object’s test list.

I made a single line of repair(CL_CI_INSPECTION->EXECUTE_DIRECT) and enhancement to CL_CI_TESTS->GET_LIST. The aim of these modifications is to fill the ‘inspection’ property of ZCL_SCI_TEST_BYDATE .( ZCL_SCI_TEST_BYDATE has a property named inspection inheriting from CL_CI_TEST_ROOT but it is empty when tests are running. I don’t know if it’s a bug or not ).

 

PS: CL_CI_TEST_ROOT class has method ‘inform’ and event Message. But I could not be able to pass  my additional check results to SCI result list . I will work on this and if its ok step3 will be useless.

 

CL_CI_TESTS->GET_LIST enhancement

 

 

  1. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class CL_CI_TESTS, Method GET_LIST, End                                                                                                          A
  2. *$*$-Start: (1)---------------------------------------------------------------------------------$*$*
  3. ENHANCEMENT1  Z_SCI_ENH_IMP2."active version
  4. *
  5. IF p_inspection ISNOTINITIAL.
  6.     p_result->inspection= p_inspection .
  7. LOOP AT p_result->listINTO l_ref_test .
  8.       l_ref_test->if_ci_test~inspection = p_inspection .
  9. ENDLOOP.
  10. ENDIF.
  11. ENDENHANCEMENT.
  12. *$*$-End:  (1)---------------------------------------------------------------------------------$*$*

CL_CI_INSPECTION->execute_direct , repair
  1. *...
  2. call method CL_CI_TESTS=>GET_LIST
  3. exporting
  4.       P_VARIANT      = CHKV->VARIANT
  5.       p_inspection = me “added line
  6. receiving
  7.       P_RESULT        = L_TEST_REF
  8. exceptions
  9.       INVALID_VERSION =1
  10. others=2.
  11. *....

While there are quite some good documents about the setup of the ABAP Test Cockpit (ATC) on SDN (cf. http://scn.sap.com/docs/DOC-32791 and http://scn.sap.com/docs/DOC-32628) I haven't seen any experience reports about a roll out of ATC yet. Therefore I decided to blog about my current experiences in rolling out the ATC in our development organization.

 

Step 0: Some Background

Before starting to describe what we did in our ATC roll out I want to give you some background about the environment of the roll out. At my company we are managing and maintaining several SAP system landscapes for different customer. A typical customer landscape consists of a SAP CRM, a SAP IS-U (ERP) and a SAP BW together with several non-SAP systems (e.g. an output management system and an archive system). In addition to that we have a central development which is used to develop core functionality and distribute these across the customer systems. These core functionalities are typically developed in our own namespace. Therefore, each of our customer system contains a set of custom development in the customer namespace and a set of developments in our own namespace.

The second important aspect of our environment is the diversity of developers developing in the system. Firstly, we have a core development team. This team consists of people with a deep knowledge around software development and mostly some formal training (e.g. a computer science degree) in the area. Secondly, we have a team of functional consultants with a wide range of development skills, ranging from some basic ABAP knowledge to very deep knowledge. And finally we usually have several external consultants developing in the different customer systems as well.

As you might have guessed the result of this environment is a quite diverse code base containing anything from well designed, reusable components to unmaintainable one-time reports.

 

Step 1: Analysis of our Custom Code

The first step I took in order to roll out ATC was to perform a first check run using a default check variant in the customer system with the largest code base as well as in our central development system. The result of this first analysis was quite disillusioning. The first run of the default check variant of the ATC across this code base resulted in roughly 700 priority 1 errors, 2500 priority 2 errors and nearly 10.000 priority 3 errors.

 

Step 2: Discussion within the Core Developer Team

The next step was to discuss the check results with the core development team. This discussion basically consisted of two parts.

 

Firstly, when I presented the tool everyone agreed that it would be very useful and we should use it. When we then had a detailed look at the check results from the two systems they were not that positive any more. The main criticism was around the errors raised by the ATC. Especially some of the more common errors lead to quite some discussions whether the reported error was really an error or rather a false positive. Furthermore, it turned out that some of the default checks simply are not valid in our system landscape. An example of such a check is the Extended Program Check that checks for conditions that are always false. In the context of SAP IS-U the pattern "IF 1 = 2. MESSAGE..." is used extensively throughout the SAP standard. Consequently, it is also widely used in our custom code. However, the Extended Program Check reported each of these if statements. There reason is, that the check only allows for the pattern "IF 0 = 1. MESSAGE....".

 

Secondly, we discussed extensively how we should approach the large number of issues in our code base. It was obvious that we wouldn't be able to fix all reported issues. This would also have been not very sensible. One reason is that a lot of the programs for which issues were reported might not be in use any more.

 

As a result of the discussion we decided to:

  • define a custom check variant including only the relevant checks
  • define a custom object set.

 

Step 3: Definition, Testing and Rollout of a custom Check Variant

The next step we took was the definition of a custom check variant. The process of the definition of the custom check consisted of several parts. We started by defining an initial set of checks that we wanted to use. Furthermore, we adjusted the priorities of the checks to our need. It's pretty obvious that each error that might cause a short dump needs to be error of priority one. However, with other checks the correct priority is not that clear. Consider for example the check for an empty where clause in a select. A program containing such a statement might cause severe performance problems in production if it is executed on a large table, nevertheless it might be fine in a small correction program that is only executed once. Last but not least we modified some of the default checks (cf. the IF 1 = 2 pattern mentioned above) to suite ore needs. Unfortunately, the modification of the default checks required a modification of the SAP standard in some cases.

After the initial definition of the check variant we set up daily check runs in the QA system including the replication of the results into the development system. With this set up we worked for some weeks and iteratively refined our default check variant.

 

Step 4: Definition of a custom Object Set

Besides the executed checks we also needed an approach to cope with the large number of errors present in our code base. For this we decided that from now on we only wanted to transport objects into the production system without any priority 1 or priority 2 errors. However, we also decided that we didn't want to correct legacy code unless we were modifying it anyway (for example as a result of a bug fix or new feature request). Therefore we created a custom object set and a custom object collector. The custom object collector will only ad objects to the object set if it has been modified after a certain date. This way we were able to get check results only for new or recently modified objects.

Note that this approach has an important drawback. If for example the interface of a method is changed (e.g. by adding a additional required parameter) this might cause a syntax error in some other program using the class. However, with our custom object collector ATC will not be able to find this error as the program using the class itself is not changed. Nevertheless this was the approach we choose to cope with the large amount of legacy code.

 

Step 5: Rollout across all Developers

After the core development team had been working with the described set up for a while we were quite comfortable with the results that the ATC produced. Therefore we decided to roll out the ATC to all developers working in our system. This was done by informing everybody about the ATC as well as setting up the execution of the ATC checks upon release of transport request. Note that we for now only executed the checks upon release of a transport but did not block any transports because of ATC errors.

As a result of executing ATC upon the release of a transport request basically every developer was immediately using ATC, even if they had not integrated it into their workflow yet. This proved very successful, especially with the less experienced developers. As the ATC provides useful explanations together with each error it resulted in quite some discussion and learning regarding good ABAP code that wouldn't have happened otherwise.

 

Summary and Next Steps

After working with the described set up now for a few weeks the roll out of ATC proved quite successful in or development organisation. Especially the detailed documentation of the ATC errors help to improve the knowledge across the organisation. With respect to the roll out I think involvement of the core developers from the very beginning was very important. Only by agreeing on a set of ATC checks, sometimes only after a few discussions, everyone accepts the raised errors and fixes them. If we would have simply used the default check variants without the adaptations mentioned above I don't thinks the ATC would have been accepted as a tool to improve the code quality (e.g. due to a large number of false positives).

 

The next step we will take is the roll out of the ATC exemption process in our development organisation.The reason is that we already noticed that some priority 2 errors can't be fixed due to different restrictions (e.g. usage of standard SAP functionality in custom code that leads to error messages). Therefore we need the exemption process in order to remove the errors in those special cases. Furthermore, I see the exemption process also a prerequisite to disable the release of transport request as long as ATC errors are present.

 

Finally, I'd be happy to discuss experiences with other ATC users.

 

Christian

Bugs in your custom ABAP code can be quite expensive when they impact critical business processes, which is why quality assurance of custom ABAP code is receiving more and more attention in business. Detecting bugs early in the development stages before they can be moved across the landscape ensure that the cost and risk impact is minimal. To reach this goal, SAP offers the ABAP Test Cockpit (ATC) and Code Inspector as quality assurance tools.

 

The ATC is available with EhP2 for SAP NetWeaver 7.0 support package stack 12 (SAP Basis 7.02, SAP Kernel 7.20) and EhP3 for SAP NetWeaver 7.0 support package stack 5 (SAP Basis 7.31, SAP Kernel 7.20).

 

General process for releasing a transport request

The transport organizer is a tool for managing the objects that gather the changes carried on during the development and configuration phases, and for transporting them across the landscape. The two kinds of objects used are the Request and the Task.

The Request is the main container, which contains zero to any number of Tasks.The CTS automatically creates one task for each user who adds objects to the Request. An ABAP transport request may contain many tasks that are assigned to different users.When you want to transport the Request, you have to first release all the tasks of the request, and then the request itself. When it is released, the transport is done automatically or manually by the administrator. The transport goes towards the systems and clients defined in the transport routes.

 

Current behavior of Code Inspector checks during the release of a transport request or a transport task

Releasing a transport request or a task can be considered as the first quality gate to ensure that poor quality custom code is not transported across the landscape. Currently, Code Inspector checks can be activated during the release of a transport request. To activate this feature, perform the following steps

  1. Go to transaction SE03
  2. Double click on the entry 'Global Customizing' (Transport Organizer)
  3. Under 'Check Objects when Request Released' , select the option 'Globally Activated'.

 

Now this activates the check of a transport request. But there may be the requirement to check also the single 'tasks'. Currently, automatically triggering  Code Inspector checks during the release of a 'task' is not available as a standard. To address this requirement, SAP provides a standard BAdI 'CTS_REQUEST_CHECK, that can be implemented by customers to trigger code inspector checks during the release of a task.

 

In this blog, I will illustrate the steps required to implement the BAdI, which when activated will trigger the checks during the release of a task.

(please adapt the naming conventions, texts, badi names, class names etc as per your requirement)

Steps for triggering Code Inspector Checks during the release of tasks

  1. Go to transaction SE19
  2. At the create implementation box provide the name of the classic BAdI „CTS_REQUEST_CHECK‟ and click on the button „Create Impl.‟

Image_1.png

   3. Provide a BAdi implementation name

badi_impl_name.png

   4. Provide a short text. Click on the „Save‟ button. Provide package details when prompted

badi_short_text.png

   5. Double clicking on the method ‚check_before_release„ of the BAdi interface takes you to the method implementation of the generated ABAP object class that was created during BAdi impl creation.

5_badi.png

   6. In the method „CHECK_BEFORE_RELEASE‟ first check if the release concerns a transport request or a transport task.Code the following portion in the method 'CHECK_BEFORE_RELEASE'

Code1.PNG

     7. For calling the actual Code inspector check itself create a new private method sci_check in the class „ZCL_IM__CTS_REQUEST_CHECK‟

  sci_chk1.png

     Provide the following parameters for the method SCI_CHECKsci_check2.png 

     create the method exception

sci_chk3.png

  8. The rest of the method SCI_CHECK contains the various steps of creating Code inspector check, assigning variants, object sets etc.It is sufficient if you copy the piece of code from the attachment 'sci_check.txt.zip'


  9. Finally create the message class „ZSCI‟ with the following valuesmsg_class.png

  10. Save and activate all your changes. Do not forget to activate the BAdI implementation in transaction SE19.

 

* Deactivate the BAdI in SE19, if you do not wish to use this feature

 

 

 


Sometimes we need to debug a process but the logic that you need to debug is after a button event after 3 pop-ups. So, what you do? Debug everything trying to figure it out when your point starts...  NO! You can create a shortcut on your desktop and drop down it into your pop-up or before the event and the debug will start after it.

 

Creating a debug shortcut:

Shorcut_step1.png

 

Change the title to help you to identify the client, change the tcode to /h and chose a place to save the shortcut

Shorcut_step2.png

 

And Finish.

 

Go to your desktop and find your shortcut:

Shorcut_step3.png

 

Now, how the magic happens:

 

Shorcut_step3.png

 

A message will be shown...

Continue the process... And the debbug will starts after your click event!

 

 

 

Hope it helps

Tarun Telang

Overview of Eclipse IDE

Posted by Tarun Telang Aug 5, 2013

Below is the easy to remember short description of Eclipse IDE

(E)ditor for many programming language

(C)ode Faster

(L)ess Typing with Code Completion

(I)ntegrated Development Environment

(P)latform

(S)yntax Highlighting

(E)xtensible

 

Note: This is not an official expansion of Eclipse.

 

If you are still wondering what does it means. Please read ahead.

 

Following are the advantages of using Eclipse as Development tool.

  • providing an open and extensible development environment - open plug-in architecture provides suitable platform for extending it with more specific features and combining it together.
  • cover full/holistic software life cycle (they can develop, build, deploy, and execute applications directly from the - design (modeling), construction (coding) and maintenance (deploying, debugging, monitoring, testing..) tools..
  • Integrated environment - seamless integration

 

It openness and inter operability through standards and facilitate open source integration.


Following are the Components of Eclipse Platform

  • Eclipse SDK
    • Eclipse JDT
    • Eclipse PDE
    • Eclipse Platform (RCP)
      • Eclipse UI
      • Eclipse File System
      • Eclipse Runtime
    • Eclipse Modeling Framework

 

References

The SAP Eclipse Story  - http://www.sdn.sap.com/irj/sdn/nw-devstudio?rid=/library/uuid/10c671f2-6364-2a10-8d96-8b3145d4a478]


Tutorials

  1. Eclipse IDE Tutorial - http://www.vogella.de/articles/Eclipse/article.html
  2. OSGi with Eclipse Equinox - Tutorial -http://www.vogella.de/articles/OSGi/article.html
  3. Eclipse Plugin Development Tutorial = http://www.vogella.de/articles/EclipsePlugIn/article.html
  4. Eclipse RCP Tutorial- http://www.vogella.de/articles/EclipseRCP/article.html
  5. Eclipse Modeling Framework (EMF) - Tutorial - http://www.vogella.de/articles/EclipseEMF/article.html

Introduction

In this video, we will discuss test data container, "Internal" and "External" variants. We will see how to import parameters we defined in our test script (discussed in part 5 of this video series). Finally, the internal variants defined will be used to create a template file for creating external variant file.

 

Lesson 6 : Creating Test Data Container

 

Best Regards,

Gopal Nair.

In this video, we will be editing the test script we recorded, and replacing the hardcoded values with parameters.

 

Lesson 5 :Creating Test Script Parameters

 

Best Regards,

Gopal Nair.

Preface

Inspired by video tutorials made by Thomas Jung and also open sap course (http://open.sap.com), I decided to try my hands on video tutorials. I have always liked the "seeing and learning" experience, especially, when starting out with a new technology.

 

Lesson 4 :Test Script Recording Initial Dry Run

 

 

 

Best Regards,

Gopal Nair.

Preface

Inspired by video tutorials made by Thomas Jung and also open sap course (http://open.sap.com), I decided to try my hands on video tutorials. I have always liked the "seeing and learning" experience, especially, when starting out with a new technology.

 

Lesson 3 :Test Script Recording

 

Best Regards,

Gopal Nair.

Preface

Inspired by video tutorials made by Thomas Jung and also open sap course (http://open.sap.com), I decided to try my hands on video tutorials. I have always liked the "seeing and learning" experience, especially, when starting out with a new technology.

 

Lesson 2 : Test Script Initial Creation & Testing

 

 

Best Regards,

Gopal Nair.

Preface

Inspired by video tutorials made by Thomas Jung and also open sap course (http://open.sap.com), I decided to try my hands on video tutorials. I have always liked the "seeing and learning" experience, especially, when starting out with a new technology.

 

Lesson 1 : System Data Container

 

 

Best Regards,

Gopal Nair.

Hi,

 

In this short blog I would like to explain how can we write unit test for method which throws exception. Even if it is simple case for many, I got at least one question about it and it means that hints may be useful for others.

 

As far as I know there is no assertion method or built in feature in ABAP unit test framework that would check if method throws exception. It would be a good candidate to extend framework by the way. We need to handle exception situation ourselves.

 

Normally if exception is thrown during test method execution, test is marked as failed. We need to avoid error escalation and implement test logic in the way that controls exception and verifies if it actually has occured. I propose two similar variants for that:

 

Variant 1:

If exception is not thrown, we call fail method which makes test not passing. If method that we test raises exception as expected, then fail line will never be reached and test will pass automatically:

 

        TRY.
            mo_cut->raise_exception( ).
             cl_abap_unit_assert=>fail( 'Exception did not occur as expected' )
        CATCH cx_root.
        ENDTRY.

 

Variant 2:

We introduce flag that monitors if exception occurs. It has abap_false value by default and it changes only if we enter into CATCH section:

 

     DATA l_exception_occured TYPE abap_bool VALUE abap_false.
    
        TRY.
            mo_cut->raise_exception( ).
        CATCH cx_root.
            l_exception_occured = abap_true.
        ENDTRY.
    
        cl_abap_unit_assert=>assert_true(
          act = l_exception_occured
          msg = 'Exception did not occur as expected'
        ).

 

First variant is shorter but second is more self explained.

 

If you already use ABAP in eclipse, I recommend to create new template (Window -> Preferences -> ABAP Development -> Source Code Editor -> Templates), call it assert_exception and use it while unit tests creation just by typing "assert", CONTROL + SPACE + assert_exception + ENTER. That helps.

 

It is also worth to mention that there is already assertion that checks the system status code: cl_abap_unit_assert=>assert_subrc. This method is similar to assert_equals, the difference is that we can skip act parameter as it is by default sy-subrc.

 

Kind regards

Adam

Most of the programs, especially reports which are generated during year-end or reports run once in every month, every quarter etc. takes lot of time.These reports will be run in background because it takes long time or sometimes automatic execution of these reports happens by Job scheduling.

There are various ways of improving the performance or rather reducing the time taken for execution, so that the report output is available ahead of time or at least within some timelines which the user or customer desires.

 

Here are some of the different ways on how to reduce the run-time of batch program, which I have come across, worked on and which would be helpful to all of you in some way or the other. This can be applied not only to the existing programs which takes lot of time, but also can be applied before creating such kind of report programs. There are two kinds of reports: standard and custom created report programs.

 

1. Standard programs:

 

When talking about the run-time of standard batch programs,  we don't have many things to control over it. As an ABAPer or developer, what can be done is to go and check for SAP notes available for the program which takes long time, as SAP would have released some notes if the program is generally run as batch program and many customers would have raised message to SAP. Implementing the SAP notes, would mostly resolve the issue or would reduce the run-time.

Sometimes, it would need some memory parameter setting or system setting in addition to the note implementation.

 

In case, if the SAP note not available, then we can raise a message to SAP after checking for the other parameters which can be configured such as memory, system parameters,etc.

 

Apart from setting or configuring of the parameters for the job, there are some things which needs to be taken care mostly related to the program logic i.e.performance of the program/job, in standard program - to check if there is any customer exit coding or BADI coding available which might need fine tuning.

 

2. Custom programs:

 

In case of custom programs, there are lot of things which as a ABAPer we can plan out before creating a report program or for tuning the existing program to reduce the run-time. Some existing programs can even be changed to run in foreground( if needed) from background if most of the below things are taken care.

There are two ways in which run-time can be reduced: one is the memory, system settings for the job/program and second is the coding part.

We have to concentrate more on the coding part, to improve the performance or reduce the run-time of the program. The report program has to be coded considering all the performance tuning techniques. Each and every performance technique plays a vital role in reducing the run-time of the program. For example, populating the internal table as below :

 

                         itab[] = itab1[].  ~ would be faster

 

                         LOOP AT itab.               ~ will take time when comparing above statement.

                          APPEND itab TO itab1.

                         ENDLOOP.

 

This will reduce some seconds depending on the total records in ITAB[]. However, writing code like this, as a whole makes a big difference and will reduce run-time of the program. Also,clearing the memory space used by the internal table at end of the perform if the data of that internal table is not needed later, will increase the memory space thereby indirectly helping in performance.

 

When it comes to performance tuning in coding, there are three things, .i.e. ABAP statements, Database statement or queries and system. Out of which ABAP and database statements can be controlled.

 

ABAP statements:

Each and every ABAP statement has a specific execution time. Thus, when coding, not only think of statement which suits requirement but we also need to analyse best statement which can be used i.e. as in my above example for populating internal table data if data type for both are same.

ABAP statements sometimes takes more time when compared to database statement when written without analysis or without knowing the impact. It is better to analyze even while writing a simple ABAP statement in a program.

 

For understanding on what is time taken for execution by different ABAP statements, login to SAP, execute program RSHOWTIM, alternatively we can use the path to navigate there, i.e. In menu bar->Environment->Examples->Performance Examples. This will be useful.

 

There are lot of artifacts, documents already available in SDN wiki, forums which might be useful to you for performance tuning.

http://wiki.sdn.sap.com/wiki/display/ABAP/ABAP+Performance+and+Tuning

 

Database statements:

 

Most of the time, when we do a run-time analysis, the percentage of  time consumed by the database hit or when pulling data from database table or updating/deleting/inserting data to the table is more. Hence proper analysis has to be done when coding queries. It is better to understand the requirements on what the program is going to do, how frequently it will run, how many records, how many tables, what kind of tables, whether the program be enhanced later etc. (Most of the programs are initially created without knowing it will be enhanced later or not).

We can take more time in analyzing on which type of query should be coded, whether going for joins like INNER JOIN,OUTER JOIN or FOR ALL ENTRIES, depending on the tables which are used, i.e. especially when using Cluster tables and views.

Sometimes FOR ALL ENTRIES takes less time when compared to using INNER JOIN, hence depending on the tables, use the proper query. Use the primary keys in where clause and in the same order it is there in table, while picking up data from tables.

Try to use standard FMs if available in place of SELECT queries, as it will not only reduce the execution time, but will also have error handling and query written in a better way.

 

There is also an option to configure the setting for every job/batch program with different parameters like priority or job class which will control the run-time of the program. This can be done for both custom and standard batch programs.

 

Existing custom programs:

For existing custom programs, if we want to reduce the run-time, then we can go for below approaches.

Do the run-time analysis in SE30 transaction, and check execution time for ABAP, database or system.After that, then we will get know which one we need to fine tune, either ABAP or database statements or anything needs to be done for system settings.Also go for performance analysis in ST05, activate trace and execute program and analyze how much time each select query of the program has taken.

 

The above approaches will also be applicable to Function modules, Class methods or Module pools.

 

Any additional information to this blog are welcome.

Hi,

 

I believe that writing unit tests is very important to have reliable and good quality software. I heard many times from other developers that customers are not interested in unit tests as they do not want to pay for that, but do they want to pay for even higher maintenance costs? Unit tests are not additional feature, they are part of good clean code that works. In this blog I want to present you how simple it is to create basic unit tests and what is the difference between SE80 and eclipse in this area. Even if you have already learned how to create unit tests in SE80, it may be difficult to start again in eclipse.

 

This article has few sections:

  1. Why we need unit tests
  2. Where to use unit tests
  3. Unit test class format
  4. Predefined unit test methods
  5. How to build single unit test case
  6. Unit tests in SE80
  7. Unit tests in eclipse
  8. Executing unit tests
  9. Summary

 

 

1. Why we need unit tests?

 

- They verify if code behavior is correct.

- They run fast and give quick status feedback.

- They lead to more reliable code, main bugs are found earlier.

- They lead to better and simpler code design.

- They help to consider all possible input/output values.

- They can be automated.

- In long term they reduce maintenance costs much.

 

Having just few unit tests is not a lot, but it is a good start. If every developer starts to create unit tests regularly, there will be small islands of tested code which finally will lead to larger, well tested areas.

 

 

2. Where to use unit tests?

 

Unit tests works easiest with classes. They are built inside class and are integrated part of object oriented design. However it is possible to write unit tests for function modules as well. Block of code (method, function, form) is easy to test if it is isolated - works only on input and output parameters and does not use external or global variables. That is why it becomes more difficult to test old legacy code and much easier to test new development - active usage of unit tests leads to better code design.

 

In general unit tests, as name suggests, are designed for limited scope, basic unit behavior testing. It is easy to test smallest methods but not complex logic of report. If we are not able to test full report flow, then try to test small parts of it, so we have solution tested on components level but not as a whole. For example lets have one method run_program_logic and 10 sub-methods inside. If we test all 10 sub-methods without testing main method, probably main flow logic will still work correctly, at least we will not experience problems with basic things like calculations, data conversion or format display. End to end testing must be anyhow done in user acceptance tests, not as unit tests. Testing full report in unit tests requires more time because we need to simulate many database queries etc. but at least we can try to test main business logic.

 

We cannot test directly blocks of report like INITIALIZATION, but we can implement these with object methods and then test them. For example:

 

INITIALIZATION.
lo_report->initialize_screen_fields( ).

 

For such code we can write unit tests for lo_report->initialize_screen_fields( ). Modularization is important.

 

 

3. Unit test class format

 

Unit tests are built in a class (local or global) with specific additions in definition part:

class ltcl_my_test_class

definition for testing

duration short

risk level harmless

.

 

Duration and risk level are test class attributes. Duration describes how long system accepts test run before termination, risk level allows to disable test execution in case of high risk. Good unit tests should have default values as above - run quickly with no harm to the system.

 

Usually global class will have local class for own code testing, but it is possible to use global test class if we want to share test code for more objects and reuse it outside class.

 

 

4. Predefined unit test methods

 

There are some method names that are already reserved and if we implement them, they will be automatically called by unit tests framework:

- class_setup - class method called once before all tests are run. Place for general initialization for static variables.

- class_teardown - class method called once after all tests are executed.

- setup - method called before each single test, commonly used for data preparation.

- teardown - method called after each single test.

 

All these methods are optional. I recommend to always use at least setup method to create new object for testing. Each single test case should perform steps on clear instance.

 

 

5. How to build single unit test case.

 

Single unit test is implemented as method in unit test class. We can identify 3 phases of test:

1. Initialization.

2. Code execution.

3. Results validation.

 

First two are nothing new - we need to write some code that will prepare data and run production code that we want to test, for example single method of a class. Third phase however requires additional, special methods to be called that will validate if results are correct. We call them assertion methods.

 

There are different types of assertions, they can be found as static methods in standard class cl_abap_unit_assert. Most popular assertions are:

- assert_equals - check if values are same,

- assert_initial - check if value is initial,

- assert_true - check if condition is true.

 

The goal of assertion method is to compare actual and expected value and raise error to unit test framework in case of not matching results. Important parameters are:

- act - what is the actual value retrieved from code execution (phase 2).

- exp - what is the value that we expect. Some assertions does not need it, like assert_initial or assert_true - only act value is needed.

- msg - what should be the message shown to user in case if test fails. I recommend to use it often although it is optional parameter - help others to understand what is the meaning of test case.

 

Example of method assertion:

 

    cl_Abap_Unit_Assert=>assert_Equals(
      act   = lo_calculator->add(
        i_num1 = 5
        i_num2 = 10 )
      exp   = 15          
      msg   = '5 + 10 must be 15'
    ).

 

Example above shows case when all three test phases are written as one statement: initialization (i_num1 = 5 and i_num2 = 10), execution (lo_calculator->add) and verification (assert_equals). This flexible call is possible with object oriented approach and I recommend to use it as it saves space.

 

In general each test method should perform single scenario validation, so it is good to separate methods for different variants. As example consider test methods like:

METHODS divide_success.

METHODS divide_div_zero_exception.

METHODS divide_missing_params.

 

It is better to have 3 methods instead of one that tests all 3 cases inside. Why? If test case fails, we know from name what exactly stopped to work (let say only divide_div_zero_exception failed). In this case name of test is description not only which method was tested, but also which case of that method was run. It brings value especially if we have automated tests scheduled periodically and general overview of all tests. Of course it is also acceptable to have only one test method "divide" and test different scenarios inside - we will still see that "divide" method fails. Sometimes it is easier to have more scenarios in one test method as we do not need to copy paste same code, however in general it is better to split scenarios to different test methods and assign meaningful name.

 

 

6. Unit tests in SE80

 

It is easy to create unit tests for global class in SE80. There is a nice wizard (Utilities -> Test Classes -> Generate), that helps us to create unit tests for chosen methods of a class:

se80_wizard_methods.png

 

In the wizard we can also decide which predefined methods we want to have and what are attributes of class.

- Fixture creates setup and teardown methods.

- Class fixture creates class_setup and class_teardown methods.

- Invocation creates method execution and default initial parameters assigned.

- Default Assert Equals syntax may be also created.

I recommend to select all options to have full test class generated so we can remove later some parts if we do not need.

se80_wizard_predefined.png

 

After we go through wizard, local class with unit tests is automatically generated. If we selected "Generate Fixture" option, setup method will be created together with f_cut object which means class under test (f_ prefix although convention for object is mo_). And we see that new object instance is created in setup, so each test will have fresh instance to test.

 

Now the only thing we need to do is to update test methods content with test case scenario. In addition from source code editor we can add new test cases to the class if we want.

 

Wizard creates same names for test methods as in tested class. I think this is good approach. Normally we could add test_ prefix but there are only 30 characters available for method name.

 

 

7. Unit tests in eclipse

 

Eclipse does not have wizard for automatic tests creation. Initially I was missing that very much so I was creating unit tests from embed SAP GUI and then updating tests code again in eclipse. However after some time I learned how to write unit tests even more efficiently in eclipse and I do not need wizard any more. Eclipse offers dynamic and flexible templates. It is important to use them and be aware of that feature. These templates may be used for efficient code handling.

 

First difference that we see in eclipse are tabs on the bottom of source code, where we clearly see which part of class is global class (production code), which are local types or test classes. I like it, because it is easy now to find out place where to write different code.

 

bottom_tabs.PNG

 

To create class, just type "test" in "Test Class" view and press CONTROL + SPACE to see templates suggestions:

test_template.png

 

After choosing "testClass - Test class(ABAP Unit)" , initial version of test class is generated. In templates there are predefined variables which are marked with editor frame. We can jump by TAB pressing between variables and change names. Renaming single variable changes all occurrences in source code, that is convenient. In default template we need to update local test class name, test attributes and first method name. If we press enter, variables edition mode is finished and we have standard source code editor mode. Notice that default prefix for local class is "ltcl_" (local test class) and I use it as well.

 

source_template_variables.png

 

Templates are very powerful and useful. It is possible to change existing templates or create new. They can be used for any development not only related to unit tests. Templates can be modified in " ABAP templates" settings in  Window->Preferences menu:

 

templates_settings.png

 

In my example standard testClass template is extended with mo_cut object, which is by default created in setup method as I know I use this pattern often.

 

With default template we have only one test. How to add new tests now? Quite simple. Just type new line in definition section:

 

METHODS my_second_test FOR TESTING.

 

Then point mouse course to my_second_test and press CONTROL + 1 (Quick Fix) and confirm with ENTER that you want to create new method:

 

new_test_method.png

 

This will create empty implementation of your method and cursor jumps inside that method so you can immediately start to write code. Initialize variables, execute method that you want to test and write assertion. You do not need to remember syntax of assertions, again templates come with help. Just type assert and press CONTROL + SPACE and choose assertEquals template. By default assertion is written in one line, I updated my template to have each parameter in new line as it suits my needs better.

 

These small tricks with CONTROL + SPACE and CONTROL + 1 for automated code generations speed up development much and makes me working faster than in SE80. Technically it is now easier to practice Test Driven Development (TDD) in eclipse as we can write tests first and design global class by creating empty methods by CONTROL + 1 Quick Fix feature from test class.

 

Unfortunately there is no wizard which automatically generates tests for all methods as in case of SE80. On the other hand, it is now up to developer to decide which methods should be tested and it does not take much time to auto-generate methods signatures. Other option is to use wizard from embed GUI.

 

 

8. Executing unit tests.

 

CONTROL + SHIFT + F10 is the shortcut worth to remember. It runs unit tests for current object. We can also execute unit tests on package level, by right click and Execute Tests option. In eclipse there is also convenient shortcut CONTROL + SHIFT + F11 which runs unit tests with code coverage, which is useful to see how well unit tests are covering tested class functionality. In SE80 we must run it from menu - Local Test Classes -> Execute -> Execute Tests with -> Code Coverage.

 

It is possible to schedule automated tests run by:

  • code Inspector (SCI) with check variant that contains unit tests execution,
  • rs_aucv_runner program where we can specify packages/programs and automatic emails notification.

 

 

9. Summary


Unit tests are important. However it is not so easy to start creating them. Once I compared learning unit tests to trip to high mountain - it is hard to climb, you may think it is not worth to try. But if you reach the top, there are beautiful views and you do not regret decision. This is how I feel - standing on top, being happy with my unit tests as part of daily development. Unit tests make you thinking wider about code aspects, you need to consider all input and output parameters. You see wider horizon as you are on the top of that mountain.

 

It is easier to start unit tests in SE80 because there is automatic wizard. On the other hand it is more efficient to write them in eclipse as there are flexible templates and code completion. I spent more time on explaining eclipse part not because it is more complex, but it has more potential and tricks that are worth to know.

 

If you want to write more advanced unit tests without database dependency, please read also my blog:

http://scn.sap.com/community/abap/testing-and-troubleshooting/blog/2013/03/21/abap-unit-tests-without-database-dependency--dao-concept

 

Good luck with unit testing!

Actions

Filter Blog

By author:
By date:
By tag: