ABAP Unit - Testable Code (Part 2)
This article is about test isolation and how it makes our code more testable.
This week the article is a bit shorter and we will only bring you closer to the topic of test isolation. Why is it important to program your own objects in a testable manner and how can you reduce the dependencies on other objects.
Test isolation is primarily about the use of test doubles to control dependent components. Without control, these can influence our own tests in different ways:
- Slow - Our own tests can become correspondingly slow due to unknown logic, as we cannot influence the runtime
- Defect - Components can be under development or broken due to an extension, so our test cases are automatically also faulty, although our logic still works
- Output - Other components can cause unwanted outputs (display, e-mail, generation of receipts, etc.)
- Input - There may be unwanted inputs or popups that pause or crash your tests
There are many other reasons why it is best to isolate such dependent components. However, the examples are intended to roughly show what can go wrong when implementing the tests.
Accordingly, such dependent components must also be identified. These can be, for example:
- Instantiating another class
- Interaction with the database
- Create and use BAdI
- Calling a function module
- Determination and comparison of the current time
How do you achieve test isolation? There is a very simple rule here, use an interface for each class and work with this in the calling code. For data management and transfer in methods, use the data type of the implementing class, but always only use the interface. In the end, the calling code does not care which object is hidden behind the reference, as long as the object uses the interface.
Hint: The creation of an interface for each class takes a lot of time and discipline, but creates just as many new objects in the system. The effort is worth it and provides you with clean and testable objects for the future.
In this article we showed you how to separate the code and how interfaces support you in writing testable code. We'll take a closer look at dependency injection in the next article.