Test driven development(TDD) on SAP release 7.4 using unit test framework.
I will write here my experiences with a journey from SAP procedural programming, manual unit testing to SAP object oriented programming and test driven development (TDD).
When I was programming my first ABAP programs I was studying also SAP educs about object oriented programming and various other non-SAP books about object oriented programming (like for Java or C# language), design patterns, clean code, test automation, openSAP online free course about how to write testable code. Putting it all together I started to feel that advantages described in these books/sources have very good sense. I was reading also lot of pessimistic info on the internet, also from SAP community, that these things can not work in SAP well. In this information chaos I was still feeling that object oriented programming , automated tests , design patterns gives very good sense. So I started to create first local classes. This was bringing only little value to my coding, but I have improved in object oriented syntax , and also this pushed me more at least to better implement rules from books about clean code (although for clean code rules, the OOP is not inevitable). Then I created my first automated tests for some local classes, so I improved in syntax of a framework of SAP unit tests (at that time I did not use mocks, neither TDD). These improvements were important for my next steps but still there was a small difference in value between my old procedural programs and new procedural programs with local classes. I have decided to get more value from OOP and TDD so I decided to start to create global classes, although I had impression that I do not need them so much , I was not sure how to create them in such a way so that they are reusable. Later I have found out that there several other reasons why coding most of my code in global classes is inevitable.
My advise here to other developers would be start to create most of the code in global classes, and very little code (for things with very limited scope ) in the local classes.
I started to think that I need global interfaces and to mock the dependencies. To fully benefit from OOP and automated unit tests we have to start create also global interfaces. They are also very useful, inevitable for this coding style.
When I was creating first automated unit tests I thought that mocks are strange and spies, or adhoc test classes are sufficient for unit tests. Very quickly I discovered the real big power of mocks in unit tests. My advise concerning mocks would be that they are very good way how to handle dependencies, make the test more maintainable and they need to be used to realize bigger potential of unit tests. I can not imagine not to use mocks now.
When I started with abstract classes and polymorphism I discovered that I started to have a lot of repeating code in unit tests so I started to use abstract test classes to have repeating code for test classes in one place.
After I had better understanding of clean code rules, OOP, global classes, global interfaces, automated unit tests, mocks, abstract test classes then I fully realized how very important is to know them all together. Now I started to see that my code started to be more reusable, maintainable, stable, testable (these are some of important software quality criteria) – these things I would not be able to do on higher level with my procedural style of coding only . Especially when I started to code big programs I realized that I am able to keep them under control.
When I was able to do automated unit tests and OOP, I started to see that creating tests firsts has more advantages as creating them after I finish my program. I saw that creating tests first really (like described in books about TDD) helps me, leads me, to create real testable code, testable OOP. I started to think more in terms of interfaces. So this was leading me to understand that TDD is in fact inevitable, when I arrived in my journey here. Why I would code automated unit tests after finishing of the program if I would then spend more time with creating these tests and I would need to redesign my program to make it testable? If I create tests first, then I can avoid this. So for me TDD is not about the personal choice, but about saving time. Of course there are situations that are causing that I write tests after I update the program- for example if I discover that I missed some scenario and the program is already coded, or if I found the defect in the test…Most of my automated tests I prepare before the my program.
Concerning the maintenance of unit tests—I was kindly surprised how little time I spent with maintenance of the past unit tests. It is almost nothing…one time I decided to create an integration test instead of unit tests ( using this SAP unit test framework ), I was updating database in the unit test, I did not mock it, and this test failed one time, although I did not touched it. Other then that maintenance time is 0. This is one of the fear, that maintenance takes a lot of time. If all dependencies are isolated in the program, and the unit tests test only internal logic of the program, then currently I do not know why the unit tests should stop work (fail), if no other developer touched them. Also I was not sure if I will be able to understand, maintain myself after some time(months) my own tests. I was kindly surprised that it is quite easy.
I can confirm that advantages, benefits described(in books, or internet blogs…) by supporters of OOP and automated tests are real, valid. The purpose of this article is not to provide lists of all these benefits, they are well described elsewhere. One purpose of this article is also add courage to SAP developers who have a feeling that these technics really works, that they are on good way and if they keep their energy to improve their coding in this way, it has its good benefits.
When I started to use code coverage features in SAP unit frameworks , I have discovered that when I create test classes I have a tendency not to have high coverage because I have feelings that I will spend uselessly time for creating automated tests were there is a very low probability that there is some defect. It was not easy, it took me months, to decrease this temptation but after I have discovered that if I have low coverage then anyway it happened that there was some defect and with lower coverage I did not have so safe feeling, after I changed something/refactor/ in my program(class), that I did not break something. I discovered that creating automated unit tests for such part of code is more timesaving like to rely on that there is no defect. Also after few months , the creation of automated tests takes me less time, since the skills how to create them are increasing. Achieve 100% branch can be sometimes impossible for me, since test coverage tool reports untested branches also those ones which are not possible to go through, if my preceding code does not allow them. So I do not try fanatically pursue 100% coverage, although I would like to have it. I use mainly code coverage to check if I did not forgot to do some automatic test for it, it is a very good tool for this task.
The questions I have encountered on my way to TDD were, do I need for my SAP coding projects:
– clean code rules ?
– global classes and interfaces ?
– design patterns ?
– testable OOP style of code ?
– mocks ?
– higher code coverage with unit tests ?
– tests first(TDD) ?
My answer is clear “yes” for all of them.
Now I started to study behavior driven development, automating of acceptance tests. I have again same feeling that they are at least as important as automated unit tests. I am currently persuaded that teams with devops targets, who want to do real agile development, have no choice , but implement also automated acceptance tests, in addition to automatic unit tests (although some smaller amount of manual exploratory testing or frontend manual testing will most probably remain for long time…until the artificial intelligence will maybe replace most of the development, testing tasks).
Great blog! You describe an important aspect, namely that it is a journey, and a long one at that. The most important bit you write is:
“Also after few months , the creation of automated tests takes me less time, since the skills how to create them are increasing.”
The key point is that it takes a lot of time and practice to get the full benefit. I’ve been using UT for over 10 years and am still learning all the time.
The same goes for using Eclipse. It is a big adjustment, and it really requires commitment to see it through until you get used to it and eventually “see the light”. Not just commitment to using it, but also reading, trying out things, continuous improvement – just like software.
Thanks Mike, there is a lot of things with SAP unit tests which I did not try until now. I'm also coding in Eclipse (1 year now), I can not now imagine that I would code
in SE38 (although I use it still for some special tasks).
Your blog describes very well the journey (which might as well be long and arduous) that one might need to take to evolve from the procedural development to OOP and eventually automated tests.
I was surprised to read that you started with the local classes first and then moved to global classes. It was the other way around for me. But this just shows that there are many ways to make the journey, not just one single "correct" itinerary. There could be many mistakes made on that journey too but we need to embrace that instead of fear it.
As Mike Pokraka also noted, the important part is practice. It takes time and continuous practice to not just learn something but to understand its' advantages.
Thank you for sharing!
Thanks Jelena, I believe that more experienced developers with broader technical skills are doing bigger leaps forward when embracing new technical domains.
For me starting with local classes was smaller, safer step forward, to learn new syntax. The developer who want to move to OOP, TDD will quickly discover limits of
The only limit to local classes is visibility. Everything else is possible as far as I am aware.
Global classes allows classes to be reusable, better testable, code is cleaner, better organized, better understandable. When I implemented a solution with 2000 lines of production code and 4000 lines of test code then doing this in local classes (in some huge program) with a lot of includes would be very difficult to manage/error prone. Global classes have their own test class section which allows to quickly find the test case for the class. You can test global class in isolation from other classes. These are huge benefits. Thinking in global classes supports reusability, testability (unit tests) which supports understandability which support maintainability. I do not know how I could achieve these software criteria without global classes. Fortunately SAP system supports well these things for my current problems/solutions.