The extended program check performs a complete check that includes the interfaces of external procedures called from your program, for example, checking whether the number and type of the interface parameters in an external procedure call is correct. The extended program check is also only a static check. It cannot eliminate all of the circumstances that could lead to exception situations or runtime errors. For example, any statements in which you specify arguments dynamically as the contents of fields, or in which you call procedures dynamically, cannot be checked statically. To start the extended program check
Select the relevant program in the object list and choose Check -> Extended Program Check from the Program menu.
It is important to check all boxes (F6) to verify all possible problems, then choose run (F8).
Errors numbers are in red, warnings in yellow and messages in blue. Pay attention to Errors, because there will be potential dump errors. Examples: comparing fields with different type, number of with parameters in a message, obligatory FM parameters not filled or with wrong type. Warnings and messages are important too, but in minor impact, does not affect the performance at all. Example: variables declared but not used, text pool not created. Do you think that you are an exceptional programmer? This screen can be revealing... When we are writing code, is normal to forget some things, like to declare variables and use it, test and remove the code but forget to remove the declaration...
In this example, the form f_validade was declared but not called in the program. Sometimes, in interface programs (BAPIs for example) you need to create forms that the BAPI will call it. This error message will appear, but you will not need to correct it, of course. Double click in the message and you will be redirected to the code. Then, do the needed changes, active your program and do the Extended Check again!
Important:
Remember to test your program when you finish the extended check. Tip: If your program has a message error that you cant remove, use the "#EC NEEDED to hide the display, and insert a comment in your code to identify why you are using it.
ABAP Unit
So you are an ABAP developer and want to write more tests, if it was not too difficult and took too long. You would like to achieve higher quality of your programs, and are unsure of how to accomplish this. After all, you are looking for a way to improve your code without investing much additional effort. The solution for these problems is ABAP Unit, which is available with ABAP 6.40. This tool brings the well-known benefits of unit testing into the ABAP world. With ABAP Unit, testing for developers has become comfortable and far less time consuming than testing is supposed to be. This tool is highly integrated both in the programming language and the development environment you are familiar with as an ABAP developer. Above all, it supports individual and mass testing equally well. So ABAP Unit reduces the testing effort during implementation in such a way that once you have understood the way it works you will enjoy testing. Surely, you are primarily interested in going directly into the matter without much ado. So before giving you any further explanations, let us start by giving you an impression of what working with ABAP unit is like.
With this tool you test small portions of code and write the test straight into the ABAP program you want to test. Let us start with a very simple program, for those who have always felt uncomfortable with percentages:
REPORT percentages. PARAMETERS: price TYPE p. PERFORM minus_ten_percent CHANGING price. WRITE price. FORM minus_ten_percent CHANGING fprice TYPE p. price = fprice * '0.9'. ENDFORM. "minus_ten_percent
The tests are implemented in plain ABAP Objects as methods of local test classes. The test classes are part of the program under test (PUT). This can be an executable program, a module pool, a function group, or class pool. The PUT can contain many test classes, and a test class can contain many test methods. All unit tests belonging to one PUT are organized in a test task. In our fairly basic example there is only one test class with one test method. Both have FOR TESTING added to the declaration. Never forget this specification. The test method should be declared in the private section, because normally it is only called automatically by the test driver of the framework, when the test is executed, but not explicitly by any other part of your code. In our example the test method class="co">test_minus_ten_percent first calls the form class="co">minus_ten_percent and sets the change parameter to 200. We compare the result of this calculation with the value we expect (180), by passing them as the parameters class="co">act and class="co">exp respectively to the class="co">method assert_equals of the service class class="co">cl_aunit_assert.
It is this method supported by the framework which offers a great service. If there is an error, for example: if the value expected and the actual value differs, the error is shown in the ABAP Unit result view, after the test is executed. By pushing just one button, or rather selecting a menu entry (in our case it is the menu path: Program->Test->Unit Test in the ABAP Editor), all the tests belonging to one task are run, and the errors will be presented to you in a clear and concise display. In case of our example, in the result display you are easily lead to the form: FORM minus_ten_percent CHANGING fprice TYPE p. price = fprice * '0.9'. Obviously, we have mistaken the global data field class="co">price for the change parameter class="co">fprice. We change the line to: class="co">fprice = fprice * '0.9', and run the test again. This time, we get the information that the test was successfully processed, which means: There was no error. You see, with ABAP Unit the original error we had in our program was easily detected and tracked down. I will treat the details of the result display in another weblog when your knowledge of the ABAP Unit has increased after reading some of my subsequent weblogs. For the time being, I would like to address an objection that seems pretty natural, looking at the simplistic test we have written.
As it happens, the developer of the program is on holiday. So the modifications to the program are accomplished easily by a student, who is not very experienced in business programming. He is happy that just by browsing over the program he recognizes what he considers to be changed. Running the program shows the expected result: The list is sorted by price. So the modification is transported to the production system. Unfortunately for the employees and the programmer, the modification of the code has unexpected and unwanted effects: As soon as the new code is activated the program starts to behave in a strange way. Some new flights cannot be added, while adding already existing flights, which should be prevented by the program logic, is now sometimes possible.
Of course, we test a whole bunch of methods in the global class as only complete test coverage enables you to detect side effects with a decent probability:
CLASS test_flights DEFINITION FOR TESTING. "#AU Risk_Level Harmless "#AU Duration Short PRIVATE SECTION. METHODS: add_flight FOR TESTING, add_existing_flight FOR TESTING, del_flight FOR TESTING, get_planetype FOR TESTING, table_comparison FOR TESTING. ENDCLASS.
So much for the preparations for our test. Now the real test:
*** add not existing flight 4 to the initial 3 flights cut->add_flight( flight4 ). l_act = cut->get_count( ). l_exp = n_setup_flights + 1. cl_aunit_assert=>assert_equals( act = l_act exp = l_exp msg = 'flight not added.' ).
Surely, you have no trouble understanding what is happening in our test method: First, we define two variables for the expected and the actual number of flights in the internal table IT_Flights, one variable for an instance of the class we want to test and four structures of the line type of
IT_Flights. We fill these four structures, create an instance of the production class we test and add three structures to the internal table by using the method add_flight of this class. In the same manner as in our first example we perform the test in the assert_equals method. In our example we add a fourth structure to the internal table and test if the number of lines in the table has increased by one as it should be if the portion of code under test worked properly. Remember that after the modification of the program it is no longer possible to add a flight with the same price as an already existing flight to the internal table. Flight number 4 has the same price as flight number 3, and so this flight will not be added to the internal table. If the assert condition is violated, an error is raised which is shown by the ABAP Unit Tool after the test is run.
Another major advantage of unit tests stems from the fact that unit tests are written during implementation. When running out of time during implementation, you as a developer are strongly inclined to shorten or even cancel the test phase, if it is scheduled after the implementation phase. When testing is a regular part of implementation, things are different. Testing cannot be postponed or cancelled.
Since Unit tests are part of the production program they test, it is easy to take account of every change in the production code being reflected by a change in the test code, if it is necessary. Your production and your test code are always in sync without greater effort.
Regarding the last more comprehensive test example, you might still feel that one reason why the ABAP Unit test was successful in the first place went uncommented so far: It was only because we had test data sets with the same price that in our unit test the additional flight could not be added to the internal table. First, I admit that the example only worked so well because of the cleverly devised test data. But let us be honest, which examples or demo can do their job without some fiddling? But what is more important than this: The test data is a crucial aspect of every test, whether it is a unit test or an integration test. You should spend some time on finding good test data, which covers not only the bread-and-butter cases, but also some exotic cases which might happen every now and then. With ABAP Unit it really pays to invest in searching good test data, because you can use the same test data time and again with the push of one button. In the next weblog I will tell you in some detail what exactly happens after you have pushed the button and run the test.
In this weblog I would like to tell you something more about the ABAP Unit result display. By showing the result display of the flight example from a former weblog, I will explain to you which information you can draw from this display. One way to start the test is the menu path: Class->Unit Test in the class builder.
Looking at the highlighted error, you realize at once: the information shown in the list at the top is the text we passed to the parameter msg of the method assert_equals of the test method add_flight of the class test_flights. The detail analysis pane below gives you more details about the error: the expected and actual value and the name of the method where the error occurred. Keep in mind: Always pass a meaningful description of what went wrong to the msg-parameter of the method assert_equals. Otherwise, some days later, you will probably still agree that 180 does not equal 200, but you will not have the slightest idea of what this means and what the error is about.
in the status bar of the program instead of the ABAP Unit result screen. Apparently, a test result without error is only displayed in the status bar.
Of course, there are far more features in ABAP Unit, more parameters in the method assert_equals and a whole bunch of service methods in the class cl_aunit_assert, which serve different purposes. To learn more about all these features and more interesting information on ABAP Unit you can attend the forthcoming article in the SAP Professional Journal on ABAP Unit which treats the topic in far more depth than I do here in these weblogs. I will restrict myself in a last forthcoming weblog in this series to answering some common objections to unit testing. There are always some reasons at hand why not to write tests. I will show that at second sight they are not convincing. So there will be no pretext to refrain from writing units tests on a large scale, once you have read the next weblog on ABAP Unit.
So you have learned now quite a lot about ABAP Unit: How and why to implement simple tests, what the ABAP Unit Result Display looks like, and some basics about the background of Unit Tests. But you might still oppose the idea that you as a developer should write unit tests. As this reservation towards Unit Testing might be pretty strong I would like to consider some of the main arguments against the proposal that developers benefit from using ABAP Unit extensively.
Though this is all quite impressive, you may feel convinced that you have still no time for testing. The answer to this is quite obvious: First of all, you write fragmented tests even without ABAP Unit. So why not systemize these tests with ABAP Unit? Secondly and more importantly: Writing ABAP Unit test may cost you some more time. But in the long run, writing no tests will be quite more time consuming for you, because you will spend considerably more time looking for bugs.
Its Not a True Developer's Job to Test?
You may believe that writing tests is a useful thing. But it is not your affair as a developer. This objection is based on an utterly wrong conception of what unit tests are good for. On the one hand, only white box tests as unit tests can really deliver results that clearly point to very small, delimited portions of code. No quality manager knows your code well enough to write such white box tests that test your code on such a fine grained level. Writing good unit tests may even help you to get a better understanding of your own program: If it takes you a lot of time to think of a test method for a certain portion of your code, this may give you a hint, that you have no clear, explicit idea what the job of this portion of code is. And this of course, fosters error-prone code. It might even be a good idea to write the unit tests before implementing the productive code: You can have a clear idea of what a certain part of the code should do and condense it in a test method, while you have still not found a good way to implement this portion of code. So write your test method and by using it find out, if the production code you write later does its job.
Why Spend Time to Write Trivial Unit Tests?
You may think that what you test in unit testing is so trivial that it is not worth the time to devise a unit test for it and write it down: "Of course, if I put 5 into the variable, there will be 5 in it." This objection also misses the point and ignores how many benefits you get for free when using ABAP Unit: Even if all unit tests in a program were as trivial as this example, you still might not be able to survey how all the different trivial parts of the program interact.
After all, every program consists just of a huge number of trivial commands. But many trivial commands may sum up to quite a complex behavior or quite a mess. It all depends on how well the code is controlled by the developer. The very fact that your unit tests offer a complete coverage of the program increases the probability that you may detect unexpected side effects of seemingly correct modifications.
Testing With the Debugger or Running Through Traces is Easier?
You may feel more comfortable with testing in the debugger or running through traces. So you are probably the one who likes repeating things over and over again? Or you have not really grasped by now how much effort ABAP Unit saves you? Imagine, you will run the same debugging sessions after every modification of your program. A dim prospect indeed. With ABAP Unit, you just press a button and a whole battery of tests is executed over and over again. You get the results presented in a perspicuous way with all the detail analyses of the errors described above.
Why not Focus on Integration Testing?
You may believe that only integration testing is the real testing. If there is good integration testing, unit test is not necessary. This objection gets the relationship of unit testing and integration testing wrong: They cannot substitute each other. If all the errors showed up only in the integration tests, there would be not a lot of time left to fix them, because these tests can only be run in a very late stage of the development. Moreover, if an integration test fails, you need more fine grained tests, that is: unit test, to locate the source of the error. Of course, there may be errors due to bad integration of different programs that cannot be detected in unit tests. Taking these facts into account, it is a good and effective strategy to reserve the integration test for detecting those errors that cannot be found beforehand in unit tests.
Hopefully Determined to Write ABAP Unit Tests After All?
Taking all the benefits of ABAP Unit testing into account, I hope even the skeptic ones among you agree: A complete test coverage of your program with good unit tests diminishes mistakes in your program without much effort and, above all, the probability that unwanted side effects of modifications are detected. After a while you will run ABAP Unit tests after every modification of a program as regularly as you check the oil after fueling your car. Of course, no amount of unit tests can guarantee you that your program is error free. You may still have overlooked some far off case for which you have made no provision in your program and your tests. But though no absolute certainty is possible, good unit tests surely enhance the quality of your programs, save your time and money and contribute to a stable development progress. The more errors are found and removed before integration testing, the smoother and faster the different parts of a component will interact in the component they belong to. So writing Unit tests is not a matter of taste, but an indispensable ingredient in the process of writing high quality software. And above all, don't forget: It is also fun to use ABAP Unit.
Code Inspector
Features The Code Inspector is a tool for checking static ABAP coding and DDIC objects (i.e. generally all objects of the Object Repository) under aspects of functional correctness, performance, security, reliability, and statistical information. It helps developers to adhere to programming standards and guidelines by creating messages on less-than-optimal coding. The Code Inspector offers various possibilities to define object sets and to combine multiple single checks in so-called "check variants". These functions, and the tool's parallel processing framework, make the Code Inspector a flexible and effective development assistant. The Code Inspector can be used in various scenarios with different types of checks, thus providing insights into the code quality from various angles. Usage scenarios
1. Single object checks from the Development Workbench
You can check a single object with the Code Inspector from the ABAP Editor (transaction SE38), the Function Builder (transaction SE37), the Class Builder (transaction SE24), or the ABAP Data Dictionary (transaction SE16). To do this, choose <object> > Check > Code Inspector from the menu, where <object> can be a program, function module, class, or table. The respective single objects are then checked with a default check variant.
2. Checks on transport objects from the Transport Organizer
You can invoke the Code Inspector from within the Transport Organizer (transaction SE09) to check objects in a transport request. To do this, choose Request/Task > Complete Check > Objects (Syntax Check).
3. Checks on sets of objects from transaction SCI
The Code Inspector (transaction SCI) itself enables you to create a wide range of object sets using standard selections via package, software and application component, source system, transport layer, responsible, object type, object name and so on. In addition, special object collectors are available that allow you to read objects from a file, for example. An object set can be combined with a check variant to a so-called "inspection" that can be executed in a single process or in parallel. For a more details see Code Inspector User Manual Types of checks and check variants Below is a short extract of the types of checks and functions that are offered by Code Inspector. New checks can be implemented if required, see for example Code Inspector - How to create a new check.
Syntax Syntax check; extended program check Performance Analysis of WHERE clauses for SELECT, UPDATE and DELETE; SELECT statements that bypass the table buffer; Low performance operations on internal tables ; table attributes check
Security Usage of critical statements; dynamic and cross-client database accesses; use of ADBCinterface Robustness Check of SY-SUBRC handling; suspect conversions; activation check for DDIC objects Programming Conventions Naming conventions Search Functions Search of ABAP tokens; search ABAP statement patterns; search for ABAP statements with regular expressions Metrics and Statistics Program complexity test; statement statistics
You can combine any of these single checks into so-called "check variants", for example to check for the adherence to given programming guidelines. Best Practices Developers can use the Code Inspector to support their everyday work. For example, the search functions or metric checks of the tool can be a great help when restructuring the code. The Code Inspector allows developers to define which objects are to be checked and which quality aspect of the code is to be inspected (e.g. performance, security). It is also possible to define global check variants as general programming guidelines, to ensure standardized programming within a development community. Check variants can prescribe for example naming conventions or other rules. The global check variants 'DEFAULT' and 'TRANSPORT' inspect objects in the development workbench and in transport requests, respectively. These check variants contain SAP-defined settings, but can be modified as needed. Another global check variant delivered with every SAP system is 'PERFORMANCE_CHECKLIST' which helps to detect less-than-optimal coding with regard to application performance. Related tools Syntax checks: standard syntax check is integrated into the ABAP editor. Extended syntax check (transaction SLIN) Dynamic performance checks: performance trace (transaction ST05) for SQL(database access)/Enqueue/RFC trace analysis, ABAP runtime trace (transaction SE30) for application code Performance in a system landscape: global performance analysis (transaction ST30)