Skip to Content

The ABAP Workbench and the Test-Driven Development Cycle in EHP1

Perhaps you know some of the trademark slogans of test-driven development, like ‘Red. Green. Refactor’ or ‘Test a little, implement a little, reflect a little.’

In TDD, reduced to its basic work cycle, you write a unit test and run it. The test fails because the code under test is not implemented.  So you implement the code under test such that the unit test is green. Then you repeat the cycle until eventually the method under test and the entire class are completely developed, completely documented, and completely testable (using all of the unit tests you have developed along the way).

As a purely practical matter, how do you translate the TDD work cycle into ABAP development with ABAP Unit in the ABAP Workbench?  This weblog shows what ABAP TDD in the Workbench in NetWeaver Release 7.01 (7.0 EHP1) might look like.

We aren’t talking rocket science here, of course. But the idea is to save you some time and fumbling around the first time that you try to practice TDD in the Workbench.

If you don’t know ABAP Unit, then you won’t get very far with TDD until you know a little about it.  Here, you’ll find a sample ABAP Unit implementation in the NetWeaver 7.0 documentation:

So what does practical TDD look like in the ABAP Workbench? We’ll talk only about classes (you do develop only classes nowadays, right?  See ABAP Programming Guidelines, actually – Modern ABAP Programming – by Horst Keller and Wolf Hagen Thümmel.)

So, you create a brand new class in SE80 in the ABAP Class Builder. What next?

    1. Ideally, you would like to write your first ABAP Unit test method and then go from there.Here, we have to adapt TDD to the Workbench.  In NetWeaver 7.01 (7.0 EHP1), you’ll first need to define the signature of a method to test.  There is no way to create an ABAP Unit include without a production method as a starting point. (This is fixed in EHP2.)

      So go ahead and define the signature of the first method in your class under test.  (You may want to keep on defining production method signatures first, since you can’t define a method via forward navigation from a test method.)

    2. Create the ABAP Unit include by choosing Utilities -> Test Class Generation. You’ll see the little dialog shown below. You can tell ABAP Unit to generate test methods for the production methods you specify. Choose all of the options – you’ll save yourself some typing.image

You’ll find yourself in the class editor, ready to define your ABAP Unit test method.

After this initial create-include step, you can edit your ABAP Unit class by choosing Goto -> Local Test Classes.  Or, if you are lazy, you can call Test Class Generation again and tell it to create a test method for whatever new production method you have just defined.

    1. Implement your test class. Usually, ABAP Unit test classes are local classes in the class pool of a global class.

What is an ABAP Unit test class?  Simply a class definition with the FOR TESTING option, together with method definitions that also have the FOR TESTING option. And then method implementations with calls to CL_AUNIT_ASSERT to evaluate the tests.

CLASS abap_unit_testclass
“#AU duration short
“#AU risk level harmless
METHODS test_toggle_value FOR TESTING.
DATA m_ref TYPE REF TO cl_class_under_test.
METHODS setup.      “Set up a fixture
METHODS teardown. “Clear away a fixture.

ENDCLASS.                    “abap_unit_testclass DEFINITION

CLASS abap_unit_testclass IMPLEMENTATION.
METHOD setup.
ENDMETHOD.                   “setup

METHOD test_toggle_value.
DATA: test_value TYPE i.

m_ref->toggle_value( CHANGING toggle_value = test_value ).
cl_aunit_assert=>assert_equals( exp = 1 act = test_value ).

m_ref->toggle_value( CHANGING toggle_value = test_value ).
cl_aunit_assert=>assert_equals( exp = 0 act = test_value ).

ENDMETHOD.                    “test_toggle_value
ENDCLASS.                    “abap_unit_testclass IMPLEMENTATION

    1. The big moment has arrived. Activate the entire class. Then choose Class -> Unit Test or the appropriate entry from the class context menu. Or just Local Test Classes -> Unit Test from the test class editor to run the ABAP Unit tests. Of course, your empty TOGGLE_VALUE method will fail the unit test miserably, and ABAP Unit will branch to a results display like this one.

ABAP Unit Error Display

With F3 you can leave the ABAP Unit results display and return to the Class Builder.  Or you can jump from the ABAP Unit results display to the test method and from there to the production source code. There, you can implement TOGGLE_VALUE such that it passes the ABAP Unit test. And then you can start over, casting the next requirement on the method or the class in an ABAP Unit test method.

Coming up: Managing Dependencies for ABAP Unit testing

You must be Logged on to comment or reply to a post.
  • Thanks for the blog about this important subject.
    I like to add some further thougths:

    Simple methods not reading the database can really be tested fine.
    But how can methods with database-access be tested? Writing test-records into the database during the setup-method and deleting them in the teardown-method may be one way ( if the db-tables are simple ). But when you have to deal with BSEG or COVP-table this way surely reaches its limit.

    In other languages like JAVA you have frameworks to create mock-classes that pretend to read the database. How can we do this in ABAP without changing the productive code to  much?

    A possible example would be:

    data: g_classname type classname value ‘ZPRODUCTIVE_CLASS’,
    g_instance type ref to ZPRODUCTIVE_CLASS.

    create object g_instance TYPE (g_classname).

    and then in the test-unit switch g_classname to the mock-class used during tests:

    method setup.
    g_classname = ‘LCL_TESTMOCK’.


    class lcl_testmock inheriting from ZPRODUCTIVE_CLASS.


    But this requires a  huge amount of discipline to create all instances of ZPRODUCTIVE_CLASS in the above way and not just by writing

    CREATE OBJECT g_instance.

    Has any one suggestions how to decouple the unit-tests from the database?


    • Hi!  You’re right – one has to break the dependency in some way and doing so requires a lot of programming discipline.  There are two further weblogs in this series that show constructor injection and private injection of dependencies in ABAP, in principle similar to your approach.  Michael Gutfleisch and Yekaterina Zavozina are presenting their workshop on TDD in ABAP at TechEd 2010 – with lots of information on practical TDD in ABAP.  It’s worth seeing the video if you are not there.

      As to database accesses, the answer is separation of concerns. In modern ABAP, access to the database should not be entwined in application code but should have its own ABAP objects-encapsulated layer. Once database accesses are encapsulated, then it becomes possible to break the dependency on the database. ABAP Unit also offers setup and teardown methods with which one can provide mock data – and the table tool in the new ABAP debugger offers, by the way, an excellent way to download real-life table data for re-use in testing, for example.

      Regards, Stephen

      • Hi Stephen, ecxcellent blog!
        Just a clarification — when you say

        “In modern ABAP, access to the database should not be entwined in application code but should have its own ABAP objects-encapsulated layer”

        do you mean we should use SAP’s “Persistent classes”, or or is that just one of several alternatives?

        • Hi!

          I was less interested in the particular implementation of the database accesses, more that they should be encapsulated in their own layer.

          The main thing is that the use of the database is not embedded directly in the application code as a unbreakable dependency.

          Regards, Stephen

          • OK, thanks — I’m curious if the persistent class option is used much, and what benefits there are to it as opposed to just implementing a “regular” class on my own, but I guess that’s a subject for a blog on its own.
          • Hi,
            maybe we shouldn’t say database, but “data-source” which also might be a RFC-Call or Webservice as in todays system landscapes it is no longer granted that the data is stored in the original database of the SAP-System.
            And the “other side” of for instance a RFC-Call has to be simulated during unit tests to make them runnable independently.


          • As to using persistent classes (when the database really is the data source), I asked around, not having used them myself ever. The word is that this comment in SDN provides a fair representation – the persistent classes don’t offer what would be considered an object-relational mapping infrastructure, because you have to do a lot of stuff yourself, but you could still use them:

            Re: Why do we need Persistent Classes ?   
            Posted: Jul 14, 2010 2:56 PM    in response to: Suhas Saha         Reply 

            I would like to know what is the advantage of Persistence Classes over Open SQL.
            Let’s first start with what SAP says about the persistence service:
            The Persistence Service lets the ABAP programmer work with relational database data in an object-oriented way.So we’re talking here about an ORM framework. I.e. the persistent storage of data is realized in SAP via a relational database, where the data model is not object oriented. Let’s say that you have created a class sales order and want to store and retrieve sales order objects (i.e. specific instances of this class). If you have a relational database, you have to model a corresponding schema for representing your sales order class and then “handcode” the translation from database tables into sales order objects and vice versa.

            Now imagine a world where you have a nice ORM, that does the work for you. E.g. look at web frameworks like grails making heavy use of convention over configuration, which allow you to easily generate database representations from your objects (without tons of coding/effort!). Essentially you can start off with your class definitions, define some attributes and the framework (ORM) will automatically generate the corresponding database tables for you.

            Contrast that with SAP (see online help on mapping assistant for persistence classes):
            You may have to create new database tables, database views, or structures for the object model in the ABAP Dictionary. At present the system does not perform this function automatically.
            So in general the ORM is supposed to make the developer’s life easier by providing a framework for translating objects into (relational) database tables. However, sometimes the automatic translation/generation along with the default access methods is not optimal and that’s where you actually go back to code your own SQL statements for doing the database-to-object conversions and vice versa. So the SAP persistence classes still use OpenSQL under the hood, but in some cases (e.g. mass processing), you might want to tune the used SQL statements yourself…

            I apologize for the long excursion, but in the end my view on persistence classes is quite simple: Use them if they make your life more simple and your coding less complex, without causing any bigger performance hit – otherwise stick to handcoded SQL statements… (long live KISS!) 😉

            Cheers, harald

  • Stephen,

    The first two blogs in this series have been great. Hopefully you continue on … and on … and on 🙂

    I may be a bit out of date, but back in the early EHP1 days when I was doing my ABAP TDD investigations I found that ABAPUnit will stop attempting to run tests after the first failure.

    I remember remarking to myself at the time that this would be a major problem for running a TDD cycle in even a medium-sized project because of the centralized nature of the ABAP code repository. Specifically, in TDD or BDD we are supposed to write a test, run the test and see it fail, then fix it. This is imperative to make sure that the test is actually testing something, and is therefore useful later as a regression test. If two programmers write failing tests at the same time and run the test suite, then only one of the tests will fail before the test execution is aborted, so one programmer will not be able to verify his/her test failure.

    Has this changed? If not, are there plans to change it?

    • Hi! 

      It’s true that ABAP Unit stops running tests with the first assert within a single test method (so that you should implement one test per test method), but ABAP Unit runs all test methods it finds. Even a short dump in the code under test can’t stop ABAP Unit – it captures dumps and presents in the test results.  Perhaps you were thinking about the behavior within a single test method?

      Sometimes of course you may want to run just a single test method, for example if you find a problem in regression testing and you don’t want to run the other hundred tests that aren’t failing.  That’s possible with a ‘favorite’ in the ABAP Unit Browser in transaction SE80, in which you can activate and deactivate individual tests. 

      BTW – if you can, be sure to watch Michael Gutfleisch and Yekaterina Zavozina’s TechEd 2010 workshop on TDD – it’s a really excellent and detailed guide to TDD in ABAP. All I’ve done is translate their ideas from EHP2 to EHP1. 


      • Ah, I see – yes, I must have been thinking of the behavior within a single method. That’s pretty normal behavior for a unit testing library then. Thanks for setting me straight! I think my conclusion at the time was a misguided.

        Regarding the workshop on TDD, I’m not planning to attend at this time, but I’ll be following your future blogs closely. Thanks again for the three you’ve done so far.


        • If you notice, by the way, my example test method does have two asserts in it – for effect but incorrect. 

          I hope that Michael’s and Katja’s workshop will be available on video – if so, it is worth seeing. 

          Regards, Stephen

  • Thanks for your instructions. Since i have experience in .Net TDD, i found that we hardly involve others to join or even understand the TDD. It seems taking a double time to do coding, expecially the project is urgency.

    Besides, dumping at the first error makes me headache while i want to check a complex function, which can save my time.

    So can you give me some suggestions? Thanks a lot.

    • Hi!

      I find as well that it takes me longer to develop (or in my case re-factor) code using TDD techniques. As with any technique that you learn, there is a learning curve – I’m already faster than I was the first time I refactored code using TDD.

      But in the end, with urgent projects, we come down to the classical arguments over the tradeoff between speed and quality. Yes, we tell our bosses, we can hack out a fast solution to top-urgent project X. But, Boss, you’re going to regret it down the line.

      As Michael Gutfleisch argues in his workshop on TDD in ABAP (see it or get the video at TechEd 2010 – it’s terrific), he’s seen all kinds of ‘revolutions’ in programming come and go, each promising a revolution in quality and efficiency. But he has seen no technique that fulfills this promise like test-driven development. Any up-front cost in development time you get back with interest in reduced maintenance, higher customer satisfaction, and easier modification.

      In my own case, I just had to take over a classical procedural report that someone else had written and adapt it to our own (hi-prio) purposes.

      After a bit of hesitation, I decided to encapsulate the different functions of the report in local classes and to drive the implementation of these local classes with ABAP Unit tests. I could have hammered out modifications directly into the procedural code. It would have been ugly, but it would have been fast. It took longer to go the TDD route.

      But then the project leader said – uh, we actually need a second variant of this program for a related purpose, and could you please combine these two reports in one UI? 

      Well, TDD paid off after all!  Because I had refactored the old procedural report and had the ABAP Unit tests in place, it was much easier and faster to implement the combo program with the additional functionality.

      As to one ASSERT per test method – I understand your point. You’d like to write your test code once and run multiple tests against it.

      Well, two answers to that criticism. First, as Michael Gutfleisch and Katja Zavozina say in their workshop, your test methods should be as clean and simple as possible. You should be able to move a lot of preparation and set up to the ABAP Unit SETUP (and TEARDOWN) methods. Ideally, you’ll find only the code-under-test method call and an ABAP Unit ASSERT in a test method.

      If your test methods require all kinds of different setup, then perhaps you need a second test class – you’re trying to cover too much territory with one ABAP Unit test class.

      The second answer is, you don’t want to pack a lot of orthogonal tests into a single ABAP Unit test method, because then a failure in the first test might temporarily hide the fact that your code under test has more than one problem. 

      But why not run a range of related tests in a single test method?  If you want to verify that your code under test method handles a variety of inputs correctly, why not put all of those tests in a single test method?  If one of the tests fails, well, you know that you have a problem in that method. No big deal. You have a problem isolated to one method, and you have to get the method green for all inputs no matter what.

      It’s quite a different story if you have a whole set of unrelated tests in a single test method – you can easily lose efficiency because you don’t have an overview over all of the problems in the code under test.

      Hope this helps!


      • Yes, i strongly agree with you that we should balance the time limitation and quality requirement. TDD is not only worthy for our software building but also for the clients’ usage. So i will insist on it to improve my job quality.

        Thanks a lot for your exhaustive reply and i’ll also follow your blogs closely.

  • I have recently moved from the Java world to the ABAP world.  In our old project we used TDD extensively.  However, for some of the people we have working on our develop in ABAP it is unheard of to do TDD.  Thanks again.

    • Hi Marc,
      I just tried to create a unit test in a user exit. I put the unit-class definition and implementation in the top-include and when running the unit test got a short dump in method TADIR_TO_PROGNAME of class CL_AUNIT_PROG_INFO. In this method the object_type ( PROG, FUGR, CLAS ) is translated into the program name. In my case the parameter OBJECT_TYPE is FUGS, which triggers a message of type X.
      So there seems to be no chance to run unit tests for user-exits.

      Kind regards

      • This doesn’t get at exactly what you are looking for, but you may want to consider encapsulating any complex functionality in your user exit into one or more re-usable classes. Then you can write unit tests for the classes used in the user exit. Thoughts?
        • This solution ended up working perfectly for me.  I am only getting back now because it took me a while to implement the solution.

          But I did want to thank all for the insights and suggestions.

    • Hi!

      I had to go back to the father of ABAP Unit for help with this question.  Klaus says that the visibility of ABAP Unit tests depends on a somewhat complicated interaction between the include technology, ABAP Unit, and the various enhancement technologies.

      ABAP Unit tests are always associated with a parent program, Klaus said, and so it is best to 1) ensure that there is a clear relationship between ABAP Unit tests and a parent program and 2) to run them in the context of that parent program. 

      As Ethan Jewett wrote immediately above, you could encapsulate the exit functionality in a global class and implement and run the unit tests there. It’s recommended anyway to do as much implementation as possible in ABAP Objects rather than in procedural ABAP.

      For the immediate case, Klaus recommends setting a breakpoint in the user exit code and then checking the SY-REPID system field when you reach the breakpoint. SY-REPID will give you the name of the program that considers itself to be the parent of the ABAP Unit tests in the include. 

      Cheers, Stephen