Posts

Keep your code clean with ABAP Unit Test Framework in Eclipse

KEEP YOUR CODE CLEAN WITH ABAP UNIT TEST FRAMEWORK IN ECLIPSE – PRACTICAL EXAMPLE

The today’s article is the second from a two part series which focuses on leveraging the ABAP Unit framework in Eclipse. In this second part we will demonstrate the exact procedure in a practical exampleThe first theoretical part offers you the necessary know-how to create Unit Test Cases for your code.

Practical example

As an example, we will take a global class of a calculator which defines the four basic mathematical operations: addition, subtraction, multiplication and division. This will be our codebase for which we will apply the Unit Testing technique inside the Eclipse platform.

Eclipse does not have a wizard for generating automated unit tests, but it does provide some templates you can make use of. Considering the fact that you may be new to this subject, it is far better to start writing tests by hand first. That being said, do not wait for the right moment anymore. Thus, open your Eclipse IDE, switch to the ABAP perspective and create an ABAP class with the following source code:

ABAP coding: exception divide function

Picture 1: Generating an ABAP class

ABAP class creation in eclipse

Picture 2: Generating an ABAP class (extension)

Intuitively, the smallest component of code that can be tested here is a method and this will be our ”unit” too. For instance, we will take the method ”divide” as a method under test and we will cover different cases and exceptions for it.

As presented in the theoretical part, the first step in defining the test cases is to create a test class. For that purpose, choose the ”Test Classes (non existent)” tab from the bottom of the editor view.

defining the test cases in ABAP Unit Framework

Abbildung 3: Setting up Test Classes

In the new window that will appear on your screen press the ”Create Test Classes…” button and an editor page will be displayed in changed mode. You are now ready to start coding your test class.

start coding a test class

Picture 4: Programming a Test Class

If you think of which cases to cover, you should consider different categories of input values that need to be testesd as: positive cases, negative cases, boundary values or combinations of input values. Definitely, each case will be treated in a separate test method. The best practice is to start with the simplest scenarios and than to continue adding more complex sets of values to be tested.

For executing the test methods we can use the shortcut keys CTRL + SHIFT + F10 or we can press the drop-down button ”Run As” and choose the ”ABAP Unit Test” option from the list. The status and the duration of each test case will be shown in the ”ABAP Unit” view.

In case of any failures, the test method that fails will have a different icon, to be easily spotted, and, what is more important, the error messages will be added to the ”Failure trace” section. If we double click on the path under the ”Stack” node, it will directly point us to the block of code that actually went wrong. Unit tests enable changes and that makes our testing safe.

coding failure of a test class

Picture 5: Error message

After the necessary adjustments of the code, we just have to rerun the tests and check if their statuses have changed and no failures are actually present.

Test class coding failure in ABAP Unit Test Framework

Picture 6: Status check of already run tests

Let us add a few more test cases and handle also an exception of the ”dividefunction, the well-known division by zero. Subsequently, our test class should look as follows:

Divide function in ABAP Unit Test Framework

Picture 7: Exception of the ”divide” function

ABAP Coding: divide function exception

Picture 8: Exception of the ”divide” function (extension)

ABAP Coding: exception divide function

Picture 9: Division by zero

Please notice that tests are executed in an indefinite sequence and not in the order they have been defined in the test class:

ABAP Test executed in an indefinite sequence

Picture 10: Indefinite executed tests

We invite you to create even more test cases, for the purpose of learning and for a better understanding of the ABAP Unit framework in Eclipse. Anyway, we have not come to an end yet. Our test code is functional but is it clean and optimized?

In other words, after all tests are green, we are ready to apply some refactoring to the code. Then again, what is refactoring? Refactoring is the process of changing and improving the internal structure of the existing code by reducing the complexity without altering its external behaviour. In this way, the next tests will be shorter to implement by means of code reusability and legibility.

Furthermore, we will leverage the special methods provided by the Unit framework and we will use the ”SETUP” method to implement the ”given” part defined in our test methods. This method will be executed before each test case and its ultimate purpose is to reference the code under test. On the consideration that writing tests should be efficient, we should also use ”helper methods” to make the test code readable, clean and small.

All things considered, after refactoring, the test class will have the following design:

Refactoring a test class in ABAP Unit Test Framework

Picture 11: Test class design

ABAP Unit Test: refactored test class

Picture 12: Test class design (extension)

Our test class has now a better code structure, efficiency, clarity and quality. Finally, we can get another sip of coffee.

Do you think it is unrealistic having your product code and tests ready at the same time? Not anymore..

Test Driven Development – TDD

Nevertheless, when talking about Unit Testing, it is essential to mind the Test Driven Development (TDD) technique. Also known as the ”Test First” procedure, it implies starting with small requirements and creating the unit tests in the first place. To be more specific, we should outline the behaviour of the application and what should it do from a user perspective, and write the small features in a text document or even as comments in the test classes, to be further used in the development. These requirements will subsequently be converted into specific test cases.

Using the TDD technique, you will always get an answer to the question ”What code should I write next?”. For instance, each new feature will be added by firstly creating a test for a single feature and not for multiple ones at a time. Obviously, running this test will demonstrate a failure, due to the absence or deficiency of the code under test. At this point, we should write just enough of the production code to pass the failed unit test. If the test will not pass, the production code must be adjusted until it does.

Considering this technique is a development cycle, we should repeat the above steps for all the required functionalities in order to have a major code coverage. The next test will drive the next step, in other words, test development drives feature development. At the end of the cycle, when all tests are green, the production code and the test code are ready for refactoring. This phase is fundamental in order to increase readability, to reduce duplicates and to have a clean code. For more information about Unit Testing and Test Driven Development, I kindly recommend you to enroll to the OpenSAP course ”Writing Testable Code for ABAP”, which also represents a strong base of the article today.

Conclusion

Furthermore, unit testing is usually automated. As a matter of fact, Eclipse provides a Unit Test framework which is embedded in the ABAP Development Tools plugin and facilitates the process of defining and executing automated unit tests. Unit tests are simple, stable and provide a major code coverage when having a right setup. Tests can be built during the development process and they can even be transported together with the source code. Unit tests are self-dependent and their execution takes place in a random order. Keep in mind when writing tests that they should not go beyond their class edges and interact with other components. They should only test the behaviour of that class or of the small component of code under test.

As you may already be familiar with, many typical software projects are formed of multiple modules often coded by various developers. The individual modules are first tested in isolation and here is the moment when the ABAP Unit comes to help, as a first level of testing our code. After all these units are developed and tested, we can cluster the ”unit tested” components and test their behaviour using the Integration technique. But this is another story to talk about..

Looking forward to more knowledge each day? We would be very happy to see you on our Inspiricon blog again. Until then, feel free to explore the ABAP Unit framework in Eclipse. And do not forget.. ”Truth can only be found in one place: the code”. Happy coding! 😊

 

Author
Andra Atanasoaie Associate
Phone: +49 (0) 7031 714 660 0
Email: cluj@inspiricon.de
Keep your code clean with ABAP Unit Test Framework in Eclipse

Keep your code clean with ABAP Unit Test framework in Eclipse – THEORETICAL INTRODUCTION

Have you ever thought of how important is testing in our life? For instance, imagine we build a car and fit together all the pieces without even testing a single part of it. Then, when the construction is finished, we enroll in a car race, expecting it to function as designed. Do you think the engine will even start? I think we have reason to doubt it.

Therefore, what can be more satisfying than testing our products and fixing the errors to ensure the delivered quality to the customers? In the field of software development this activity is known as the so-called error analysis.

The today’s article is the first from a two part series which focuses on leveraging the ABAP Unit framework in Eclipse. This first theoretical part offers you the necessary know-how for  building Unit Test Cases for the source code using a practical example. In the second part we will demonstrate the exact procedure based on a practical example.

But first…

Why test an application?

A project lifecycle involves many procedures and stages to be followed in a methodical way. As software developers, we should be aware, that there is always the need of testing a product during the development and integration phases of an application. Our goal for it is to last for a long period of time and to perform resourcefully.

Testing is essential and offers several advantages:

  • less defects leading to the improvement of overall capacity and accuracy
  • it is more cost effective related to future developments
  • improves the quality and ensures the application performance
  • encourages customer’s satisfaction and confidence
  • keeps your position in the business field competition

Computer systems are often complex and hard to understand. As a result, various methodologies have been implemented to evaluate the behaviour of a product. In the light of testing our software code, there are several testing practices used along the lifecycle of an application, as presented below:Testing practices development

Figure 1: Testing practices used along the lifecycle of an application

1.Unit Testing

It is the first level of software testing where individual units of code are tested to see if they work as expected. Consequently, each piece of code is subjected to a series of test cases. It can be performed manually, but usually tests are automated.

2.Integrated/Component Testing

It is a technique focused to test the integration of different modules that were previously unit tested by grouping them in multiple ways and to check their behaviour and data communication. Tests are defined in an integration test plan and applied to these aggregated components.

3.System/UI Testing

It is a testing technique that focuses on the UI (User Interface) design structure. Can be executed manually or by using automated tools. It is a practice used to confirm the properties and acknowledge the state of the UI elements. This can be effectively achieved by creating a diversity and combination of test cases.

4.Exploratory/Acceptance Testing

It unscripts the Quality Assurance (QA) technique used to investigate and discover what works and what does not work in an application. Testers have the possibility to explore, learn and check the application in real-time. Test cases are not necessary beforehand, usually testers decide on the fly what to test next and how much time to spend on a particular functionality.

Except for the Unit Testing technique, when testing an application the inside details of it are seen as a „black box” for the tester. Nonetheless, as prerequisites there should exist a basic understanding of the system design.

Automated Testing versus Manual Testing

First and foremost, what is automated testing and how can we define the manual testing?

Automated testing is a process of testing the software code by running a minimum set of scripted tests. These tests are executed using an automated tool that will eventually report the actual values and compare the results with the expected outcome. The aim of the automated testing is to minimize as much as possible the effort and the time consumed. This technique is appropriate and convenient for large projects, particularly if they are too complex to rely only on manual testing.

Manual testing , on the other hand, is a technique of finding errors and defects in a software application by performing a suite of test cases by a human. It is not necessary to have knowledge of an intermediary automated tool, but it may be very time-consuming taking into consideratio, that, to ensure the completeness of testing, testers need to a create a suitable schema that will lead to a detailed set of important test cases to be covered.

It would be ideal in the first place to manually test the code of a new application or after any major change of it and then to create new automated tests for a better coverage and understanding of the implemented functionalities.

Having said that, chances are that there we will be the need to combine automated testing with manual testing in order to provide a complete and fully covered test plan. The reality is, there is no ”better” or ”worse” procedure, they are just different.

What is Unit Testing and when should we use it?

Let us start by answering the second question. The suitable response would be: everytime we want to test a small unit and its behaviour. You may be wondering what is a unit then?

A ”unit” is defined as the smallest testable component of an application, such as a class or a method, that can be isolated from the rest of the code and controlled to investigate if it fits for use.

As opposed to the other testing techniques, there is a need for a solid understanding of the system architecture when using ABAP Unit Testing. Therefore, Unit Testing is also referred to as a „white” or „gray box” testing and consequently, unit tests should be created and defined by a developer.

Most programming languages have designated unit testing frameworks and so does ABAP. Here, all the background processes required for testing are built into an IDE (Integrated Development Environment), a fact that enables us to execute the unit tests with every compile of the test program.

The most suitable tool in SAP for Unit Testing is the ABAP Unit Framework in Eclipse IDE. This framework is part of the ABAP Development Tools (ADT), therefore, the only thing you need to do is to install the add-on into your Eclipse platform. For those who do not have it installed, yet, you can find more information along with a step-by-step tutorial on this blog article.

Unit tests do not interact with the environment or with external systems of the codebase. They are always running in a simulated and isolated environment, in most of the cases, as a separated program in which unit tests are defined as test methods in local test classes. Thus, when the application changes in the real, productive environment, the unit part will not be automatically informed due to isolation from the system.

In order to make your tests effective, you need to structure the code in a way that makes it easy to unit test. Nevertheless, it requires a bit of practice to get good at it and to understand what to test in isolation.

Unit testing should be applied where tests have a clear meaning. The Business Layer code is commonly suitable for running tests and, hence, it represents the main area where unit testing is focused.

Our goal is to write efficient automated tests alongside with testable code. For instance, when running unit tests we have the flexibility to change the source code and to adjust it to fix the errors and to make it testable. Above all, the most obvious benefit is knowing down the road that when a change is made no other individual units of code are affected.

writing efficient automated tests

Figure 2: Writing efficient automated tests

Advantages and benefits

Naturally, as the first level of performing test cases in an application, unit testing provide some notable advantages. Not only that, when having a proper setup, unit tests are:

  • Fast – typically can be run thousands of tests/second
  • Simple – unit tests focus on small parts of the application
  • Timely – tests are written alternatively with the product code

But also, Unit Tests are very effective because they provide:

  • Major code coverage – in many cases up to 80-90% code coverage
  • Easy error analysis – unit tests point exactly to the place where the code goes wrong
  • Stability – unit test repeatability result in a constant behaviour, fact which makes them stable.

Creating a Test Class

In the SAP field, unit tests have been introduced as part of the Object-Oriented design. On that consideration, we can intuitively notice that unit tests work perfectly with classes. In a scenario where we are not able to test all of the report flow, we should at least try to unit test small parts of it.

Moreover, we should only test the public interface of an application and not the private parts. Normally, we are not allowed to test directly blocks of a report, as INITIALIZATION or START-OF-SELECTION, but we can implement the same logic by converting these into object methods and test them afterwards. Worth to notice here is that modularization is very important for a better programming.

The idea is that we define and implement test classes in the same way we define a regular ABAP Objects class. However, what makes a difference is the  ”FOR TESTING” statement we have to add to the test class definition. Keep in mind that this addition basically separates the application into two different parts: the test code and the production code.

Even though there is not a standard naming convention yet official, SAP suggests us to add a prefix to the test classes names as in ”LTC_<class_name>”, in order to emphasize that they are local test classes and to distinguish their focus. Moreover, what we also need to specify for a test class are the two class attributes, RISK LEVEL and DURATION, used by the ABAP Unit runner to interpret the properties of that class.

The RISK LEVEL attribute is referring to the side effects that could impact the system:

  • HARMLESS – no existing process will be affected by the unit test
  • DANGEROUS – the unit test could make changes to a database or persistent data
  • CRITICAL – both customization and persistent data could be modified

Kindly keep in mind that every unit test should be defined with the scope of being ”harmless”, hence not to modify the environment in any way.

The DURATION attribute is referring to the expected execution time of the unit tests and it can be:

  • SHORT – less than a minute
  • MEDIUM – less than five minutes
  • LONG – longer than five minutes, relatively one hour

Eventually, these intervals can be customized. Yet, what we need to take into consideration is, that if the execution time exceeds the specified parameter, the ABAP Unit runner will throw an error.

In the end, to give a short illustration, a test class definition should have the following format:

CLASS ltc_my_test_class DEFINITION FOR TESTING

RISK LEVEL Critical|Dangerous|Harmless

      DURATION Short|Medium|Long .

[…]

ENDCLASS.

Worth to mention is, that the part of code in an application, that is unit tested, is usually called ”CUT” = Code Under Test.

If you are eager to find more about test classes, I suggest you to read the SAP Press E-book publication ”ABAP Unit: Writing and Executing Unit Tests”, written by James Wood and Joseph Rupert.

That being said, we have now arrived at the point of…

Creating a Test Method

A test method can be implemented exclusively in a test class. As a matter of fact, during a test run, test methods are called as individual tests and that means we will only have one instance of the test class per test method.

Notably here, the method that is going to be tested, actually the unit, is usually referred to as the ”Method Under Test” and it is part of the production code.

Test methods have no parameters but, similar with test classes, they have a ”FOR TESTING” addition at the end of the DEFINITION part. Another key point to remember is that a test method is declared in the PRIVATE SECTION of the class definition to underline that it can only be used in the context of its test class and not in other derived classes, as follows:

CLASS ltc_my_test_class DEFINITION FOR TESTING

      […] .

      PRIVATE SECTION.

      METHODS:

          test_method1 FOR TESTING.

          test_method2 FOR TESTING.

ENDCLASS.

The only situation where the test methods can be declared in the PROTECTED SECTION is when these methods are part of a superclass and are inherited by another test class.

The IMPLEMENTATION part of a test method should always tell us a story about what is going to be tested and this should also be reflected in the test method name. It usually follows the ”given – when – thenpattern that associates with the initialization, execution and result phases of the test case. We should think of a test method similar to a logical story in the following way:

given -> a particular environment

This is an initialization part where our global class is instantiated.

when -> we execute this CUT (code under test)

Here we normally call the method that is going to be tested together with the specified input values.

then -> this outcome is expected

A test method has one or a few inputs and usually a single output.

Significantly, in the ”then” part of the test method, the outcome is validated through a comparison between the actual value that the method under test is returning and the real expected value. If the results do not match, the Unit test framework will throw an error. This comparison is made using one of the utility methods provided by the ABAP class ”CL_ABAP_UNIT_ASSERT”, which is called ”ASSERT_EQUALS”.

The most often used utility methods alongside with their SAP documentation are:

– ASSERT_EQUALS – ensures equality of two data objects

– ASSERT_BOUND / ASSERT_NOT_BOUND – ensures the validity / invalidity of the reference of a reference variable

– ASSERT_INITIAL / ASSERT_NOT_INITIAL – ensures that data object value is initial / is not initial

– ASSERT_TRUE / ASSERT_FALSE – ensures that a boolean equals ABAP_TRUE / ABAP_FALSE

– ASSERT_SUBRC – ensures a specific value of the return code

– FAIL – report unconditional assertion

– ABORT – abort test execution due to missing context.

They are also known as ”assertion methods” and their ultimate purpose is to pass messages to the ABAP Unit runner.

Naturally, it is not necessary for a test method to follow the above pattern, it is just a style of writing tests that helps for a better understanding of them. Instead, it is mandatory for it to include the logic inside these three parts.

Importantly to know about is that there are several special private methods used in test classes which are provided by the ABAP Unit framework. They implement a unique test behaviour and include the test objects and the connections needed for a proper execution. These are:

  • SETUP( ) – instance method that is executed before each individual test or before each execution of a test method

The ”given” part of the tests can be implemented in the SETUP method, only if the test methods have the same code under test.

  • TEARDOWN( ) – instance method that is executed after each individual test or after each execution of a test method
  • CLASS_SETUP( ) – class method which is executed once before all tests of the class.
  • CLASS_TEARDOWN( ) – class method which is executed once after every test of the class.

Actually, they are also called ”fixture methods” and have predefined names so that the ABAP Unit could recognize them at runtime. These methods are optional and should be used only if we need them.

There are already several software companies that have adopted the Unit Testing technique as part of their development process. Although it may be difficult to get used to it or to figure out what cases to cover, in a long-term perspective, unit tests lead to less maintenance efforts and costs. Unit tests are likely created by the developer, the reason for we call it ”white-box” testing, and it makes sense because the person who wrote the product code is the most qualified to know about what and how can be easily accessed and tested. Additionally, having a lot of tests for the small components of the application will demand much less debugging overall and that will also save our time. And time is very important for a developer, isn’t it?

Now, that you completed the theoretical part, you are ready to practice. Do not miss the second part of this series, which will show you how to build Unit Test Cases for the source code based on a practical example.

Sources of the images: https://open.sap.com

Author
Andra Atanasoaie Associate
Phone: +49 (0) 7031 714 660 0
Email: cluj@inspiricon.de