I was exploring on the topic ‘ABAP Unit test ‘ and while doing so , read few very good blogs , like the one by Nithya Murugesan (can be accessed here ) . Another good one here and the standard sap help . I found the information is scattered and more can be added to it as well, so i thought of writing my own blog on the topic.
Before I show you how to do it with very simple example, let’s try to answer some basic questions…
What is ABAP Unit?
ABAP Unit is a unit-testing framework that is integrated into the ABAP language.
Unit tests are to ensure the correct behavior of the smallest testable units – such as the methods of classes , performs, .. ABAP unit lets you test the code at unit level like testing each piece separately.
What are the features of ABAP Unit?
- ABAP Unit tests are written in ABAP. You do not have to learn an additional scripting language for testing.
- You write tests with the standard ABAP Development Tools (ADT). You do not have to use additional tools for developing tests.
- ABAP Unit tests are transported with the ABAP repository objects that they test. They are therefore available in all of the systems of your development and testing landscape.
- You can run ABAP Unit tests as you develop code. You can start tests, for example, directly from the ABAP editor in the ADT.
- Code coverage measurement is integrated into ABAP Unit testing, so that you can verify the thoroughness of your unit testing and easily find untested code.
- ABAP Unit is integrated into the Checking Quality of ABAP Code with ATC, so that unit testing can be automated and is part of mass quality testing
- ABAP Unit test methods have no parameters. No special knowledge or test framework is required to run ABAP tests; they can be run by anyone, and not just by the developer.
- ABAP Unit tests cannot be executed in productively used ABAP systems.
How to write these unit tests?
For writing Unit tests, methods in global class CL_AUNIT_ASSERT are used . Local classes are implemented to insert test cases. Inside the local class the required method from the global class can be called for testing. These test classes can be written inside the program for which the test is to be done. Production code is not affected by this in anyways.
The class CL_AUNIT_ASSERT contains the following static methods for the verification of test expectations within ABAP Unit test methods:
|ASSERT_EQUALS||Ensures the equality of two data objects. Please note that the arguments are passed by reference. Don’t pass system fields like SY-SUBRC.|
|ASSERT_EQUALS_F||Ensures the inequality of two elementary data objects.|
|ASSERT_EQUALS_FLOAT||Ensures the equality of two decimal floats with a relative tolerance.|
|ASSERT_DIFFERS||Ensures the inequality of two elementary data objects.|
|ASSERT_BOUND||Ensures whether the reference of a reference variable is valid.|
|ASSERT_NOT_BOUND||Ensures whether the reference of a reference variable is invalid.|
|ASSERT_INITIAL||Ensures that a data object has its initial value.|
|ASSERT_NOT_INITIAL||Ensures that a data object does not have its initial value.|
|ASSERT_SUBRC||Requests specific value of SY-SUBRC which is passed by value.|
|ASSERT_THAT||Ensures that the actual value adheres to a given Constraint. Such a constraint can be used to implement custom assertions.|
|FAIL||Terminates the test with an error|
|ABORT||Cancels the test due to a missing context (ideally in setup method).|
All the methods have the optional importing parameters MSG, LEVEL, and QUIT, which always have the same meaning:
|MSG||CSEQUENCE||Contains a more detailed description of the error (if applicable)|
Indicates the severity of the error; the following values are possible
· TOLERABLE – Minor error (may be tolerable)
· CRITICAL – Critical error (default value)
· FATAL – Fatal error
Determines the flow control in the case of an error. The following values can be passed:
· NO – No termination in the case of an error; processing of the current method continues after the relevant method is called
· METHOD – The currently processed test method is terminated (default value)
· CLASS – The currently processed test class is terminated
· PROGRAM – The test of the currently processed main program is terminated: The current test class is terminated and all other test classes in the program are ignored.
All the assert methods have the following mandatory importing parameter:
|ACT||Any||The object to be verified|
The comparing method ASSERT_EQUALS additionally requires a parameter for the expectation:
|EXP||Any||The identically expected object|
|TOL||f||Allows you to compare floating point numbers for the passed tolerance|
What’s the difference between Normal class and Test Class?
Test class and the methods in the test class need to have “FOR TESTING” added in the definition. For e.g.
CLASS demo_class DEFINITION FOR TESTING.
METHODS demo_method FOR TESTING.
Enough of talking let’s see some code in action. I will show a very basic example to show how it works. The flow will remain same but the code complexity can go to any level.
So, I taking example where in my program ZDEMO_ABAPUT I have class lcl_Customer_SOCount with method Order_Count. The method takes Customer number as input and returns the count of sales orders created for this customer. Very simple isn’t it!!!
As you can see, nothing in the Start-of-Selection yet.
So, now we want to write ABAP unit test to check if this method works fine. To achieve that, we need to implement the local testing class with addition “For Testing” as mentioned earlier.
In the implementation of the test method, m_count in this case, we will call the ABAP unit that we want to test i.e. method lcl_Customer_SOCount to fetch the order count for customer ‘0001000030’.
The method’s result is stored in variable lv_result. Now, we can use methods of global class CL_AUNIT_ASSERT to compare the result with expected result. So in this case, we will use method ASSERT_EQUALS to check is the result value is matching with expected value or not. We need to the Expected value in parameter EXP (hardcoded here). In case the value doesn’t match the expected value it will result in test case failure and message “Something wrong” will be returned.
OK, we are done with the implementation of our test class and method. Now is the time to run the Unit test.
Shall I just execute the program?? And the answer is NO!!
The direct execution with run the program and not the Unit test and nothing will happen in this case as we have actual not written anything in the “Start-of-Selection” event. So, blank screen as shown below will appear if we try to execute the program.
How to do it then?? The answer is, we need to run the program as ABAP unit. That will call the test class and the static method that we have implemented above. To do so, right click on the program and select Coverage As=>ABAP Unit test as shown below.
As a result, you will see the ABAP unit test is trigger and we will see details like what all unit tests passed or failed or caused warning. In this case, out test method m_count got tested and passed the result as the count matched the expected value as is shown in screen shot below.
Now, let’s try the negative test case. To do so, let’s change the expected value to ‘60’ instead of 55 and see what happens.
Let’s run the ABAP Unit test again and see the result.
This time, the result is failed unit test as expected. We can see the message “something wrong’ in the output. Along with that result tells you that there is difference in Expected and Actual value as highlighted in screen shot below.
We can also check, which all pieces of code is code is covered in the ABAP Unit test in the form of code coverage. The same can be checked under “ABAP Coverage” tab as shown below. As we have only one method and we have tested it, it shows 100% covered.
We can also execute the Unit Test from SAP GUI T-Code SE38 also as is shown below.
Before we wrap this topic up, let me tell you about Test Fixture.
What is this Test Fixture now?? That’s what you must be thinking now… right?
Test fixture is the test configuration like test data or test objects. This data would be used within the test methods. Fixture methods would be executed before the actual test method gets executed. So when the test is getting performed, the test data or test objects setup in fixture method can be done. In ABAP, the test fixture is achieved using predefined methods. These methods would be called automatically by ABAP framework if they exist in the test class.
|SETUP||Instance method SETUP would be called before each test within the test class. In this method, you should generally setup your test data which can be leveraged by various different test within the same test class.|
|TEARDOWN||In contrary to SETUP, instance method TEARDOWN would be called after each test within the test class. You should use this method to clear the test data and make sure they are ready to use by the next Test method.|
|CLASS_SETUP||Similar to SETUP, static method CLASS_SETUP would be used to set up the data once before the first test in the class gets executed. The purpose of CLASS_SETUP is to set up the same data like a configuration which would be used by all test methods but NONE of the test method would be modifying it.|
|CLASS_TEARDOWN||Like TEARDOWN, static method TEARDOWN would be used to clear the data once after the last test in the class gets executed.|
So with inclusion of Fixture methods, the changed code will be like as shown below.
Test Class Definition
Test Class Implementation
So, to summarize, we saw how we can write test methods and call the ABAP unit test to test different pieces (units) of our code. Hope you finds this useful.
Keep Learning and Keep Sharing!!