In the next few installments of this blog I will be inviting a good friend of mine William Craig to teach us about ABAP Unit. Like myself, bill has been around SAP quite awhile and will have an interesting perspective for all you naysayers out there around the effort involved to implement ABAP Unit to existing objects vs using it out of the gate on new development. Here is a little bit about Bill….
Bill Craig is a senior developer at IT Partners. Bill is also the president of ASAP Consulting Inc., located in Warrenton, Virginia. Bill has over 10 years of experience with SAP ECC systems and integration with SRM. His areas of expertise include SAP Business Workflow and ABAP development. His concentration is on SD, MM, and Procure-to-Pay modules. You can reach him at firstname.lastname@example.org
Using ABAP UNIT – The Turning Point
On my current project, automated testing and code coverage are the latest buzz words. One of the tools that was demonstrated was ABAP Unit. I will admit that my initial thoughts on its use was that it was more work to my already busy day. In addition, a lot of my work is fixing or changing existing code, and a lot of it is rather old and has been patched by so many developers over the years it takes several ‘page down’ clicks to find actual code and I was not sure how ABAP Unit or ABAP Unit Test could even be incorporated into this code.
Then a fortunate series of events took place and I was given the opportunity to rewrite one of these older programs, and I thought, now is the time to learn and use ABAP Unit tests.
There are some great blogs, demos and courses regarding ABAP Unit Test, automated testing, and TDD (Test Driven Development), and I wanted to share what I have learned and used so far.
One of the goals of SAP ABAP Unit test is to get as much code tested and code coverage as possible. In some of the older programs with various fixes and changes, you might find that when you are creating your test, to get as close to 100 percent code coverage as possible, you come across code that will never be called or dead code. It can be as simple as someone adding a condition to an ‘if’ statement and you find that one of the cases inside the statement can never be met.
I follow the unit testing Best Practice of breaking out the requirements into their simplest form. For example, I separate validations into their own methods, database actions into their own and so forth. This way I can create my test based on that step or the requirement and then create the productive code. Below I have created a simple class and a couple of methods. One method will determine the discount based upon a quantity and another will determine the value with the applied discount.
With this simple code I can then select the ‘Test Classes’ tab in Eclipse, or from the GUI using SE24 or SE80, I can use the wizard to generate a test class as well.
The test class has certain definition requirements so that SAP knows it is a test class. For example using ‘FOR TESTING” in the class definition denotes this as a test class
In the class implementation I define the methods for the tests. In this example I am using the SAP delivered ‘setup’ method which will be called prior to each method test by the framework, to instantiate the class I am testing. This could be done at the beginning of each test method, but again the idea is to keep it simple, as well as simple to code and use.
The first method I named meaningfully so I or the next developer would know what the test is doing. I am passing in a quantity of 100 and expect to receive a 5% discount. The CL_ABAP_UNIT_ASSERT class has several methods and for this one I am using the assert_equals. The ‘act’ parameter is the value being returned by the method I am testing. The ‘exp’ value is what I am expecting, and then the use of ‘msg’ will raise the message I want to see if the unit test fails.
When I execute the test method, I have the option to include coverage. This allows me to see not only if my test was successful, but also what code was executed. Take a look at the ABAP unit test report below…
Looking at the code coverage everything highlighted in green was executed, and since this is a simple method only one test covered the code.
For the second test method amt_100_perc_90, you can see I have added a condition statement in the determine_discount method, so if I only have a single unit test not all the code will be covered. Here is the new method …
Below is the coverage I was able to achieve. The highlighted RED areas were NOT Executed.
OK, lets create a couple of more unit tests to try and reach 100% code coverage…
We get pretty close, but I do not hit that last “Catch-All” Else statement. We’d have to go negative to catch that one.
With these tests in place I can run them anytime and include them in code inspector. This was a simple example and using a new development object. In the second part of this blog I will get more into adding ABAP unit to existing ABAP report programs as well as unit testing a select statement.