Skip to Content
Technical Articles
Author's profile photo Vicenç Xavier Lozano

ABAP Units by -wrong- example

Warnings:

  • English is not my mother language (is not even a far long time ago lost aunt language), and I learned it just with the goal to be able to communicate, so, my apologies for all the atrocities you will find here
  • there’s a saying in my land that says something like “you can learn from a bad example”, here comes one.
  • no animals (except me) have been harmed during the building of the software exposed
  • the pieces of code in this blog entry are invented, not tested (pun intended) and not designed to work, so do NOT use them, nor take them as a good way to do things.

Acknowledgements:

This piece of cr… information has been possible by my own effort and I want to thanks me first. I deserve kuddos and a raise, but I will be happy with just a bit of ice cream (cookies and cream preferred).

The idea of writing this blog entry is mine too, but has been inspired by the titanical effort of Enno Wulff, who even has created a Git for examples about ABAP Units (I will not use it because I’m a lazy person who hates Git).

Matthew Billingham, as the guy who thinks TDD are worth the effort (as I do, but I hate the word “effort”) and has been an inspiration for me since I met him in the 2012 World Championship of Mornington’s Crescent (that I won, of course, thanks to the Richard Harper’s Tuly gambit).

Haul Pardy, who wrote books, one with a rocket in the cover (that I bought), and has give me some hints about the work (I hate the word “work” too) I’m exposing here. He must know a lot about ABAP and coding the proper way, because he has a hat.

And every one who contributed to this discussion in the Coffe Corner about Unit tests. I will not mention all of them because you will think I’m trying to write a book or something (in fact, I lost completely the notion of time while writing this… thing I don’t remember what was about), specially Michelle Crapo because she liked the club, and Jelena Perfiljeva, who has no time to learn TDD, but will do when able, I’m sure of it.

Introduction

This is the story of a journey. More than that, it’s the tale of a brave hero who embarks in an epic time travel. It begins in the early 80’s where only the music was a good thing, and ends… well, it’s about you to find it or not by completing this read.

It’s about self knowledgement, self awareness, self consciousness and selfness selfishness (and a bit about the Loch Ness, I want to visit some day).

In the eighties we had ABAP. And in the eighties we had R3 and some things called EXITs (as the current enhancements, but easier to find, use and abuse.

And some people decided the 80’s were fine enough to not move to the XXIst Century, and kept developing things the same way for 40 years.

This is the story about a not-so-young hero who tried to change that.

MV45AFZZ

This is an include used to enhance some sales delivery transactions (not sure which ones). The enhancement works this way:

in the standard SAP code, there are calls to FORMs in this include in some points of the process, each one intended to allow the coder to mess with the data processed by those transactions.

This process is intended precisely to allow ABAPousaurus (more on them some other day) to fill those forms with a thousands of lines of code, with unlimited IF…ELSE nested blocks and dark, obscure code because yes, we hate you, future dude who will stole our job.

So, when someone asks you to add a single, little, tiny modification in the quotation-to-offer process, you must waste few days of your live trying to understand where your modification will fit, how to add it without breaking that toothstick Eiffel Tower that supports a two liters nitroglyceryine bottle.

Then you realize you cannot do it.

Encapsulation, OOP and the mole’s mother

Step 1- put your code into a class

So I (the hero, if you have forget it) decided to encapsulate the whole include into a collection (of maybe one) classes, and leave all the two thousand line FORMs like this:

form userexit_move_field_to_vbak.
  zcl_exits_for_sd_docs=>moveheaderchecks( ).
endform.

Amazing, right? I deserve a medal just because the intention.

But reality hits. And hurts. A lot. And you notice the process must evolve, because there are popups, and error messages and dark unicorns trying to bite your nose, and you want not to put popups, error messages and unicorns into a neat-wannabe class.

So, you go this way:

form userexit_move_field_to_vbak.
  data: myclass     type ref to zcl_exits_for_sd_docs,
        messagetype type symsgty,
        messagetext type string,
        texts       type zcl_exits_for_sd_docs=>tabtexts.
  myclass = new #( ).
  myclass->moveheader( 
    exporting header = vbak currentposition = vbap
    changing newpositions = xbvap[] newpartners = xvbpa[]
             messagetype = messagetype messagetext = messagetext
             texts = texts ).
  if messagetype is not initial.
    message messagetext type messagetype.
  endif.
  if lines( texts ) > 0.
    CALL FUNCTION 'POPUP_WITH_TABLE_DISPLAY_OK'
      EXPORTING
        endpos_col   = 80
        endpos_row   = sy-tabix
        startpos_col = 10
        startpos_row = 10
        titletext    = 'some weird title'
      IMPORTING
        choise       = lv_tabix
      TABLES
        valuetab     = texts
      EXCEPTIONS
        break_off    = 1
        OTHERS       = 2.
  endif.
endform.

I don’t really like this approach, I’m deciding if I move the popup and so into another class (and even change the CALL FUNCTION thing for another class, but hey, this post is not about my code, but about me.

Step 2- refactor (you will keep doing it the rest of your working life)

Then I copied the whole content of the FORM, and put it in the moveheader method. A whole mess. But as I am a cool guy (although too modest to be noticed), I decided to keep working the proper way, and split all those lines of hell into other methods… to end with something like:

method moveheader.
  case transaction.
    when 'VA01'.
      dothis( header ).
      dothistoo( exporting header = header changing newpositions = newpositions ).
    when 'VA21'.
      dothis( header ).
      checkthat( exporting header = header changing texts = texts ).
      checkthattoo( exporting header = header newpositions = newpositions
                    changing  messagetype = messagetype msgtxt = messagetext ).
...
endmethod.

So, in the future, my future me (or the poor guy who inherits my chair) will be able to know anything that happens just by looking this first method.

I know, we are supposed to deliver dark, complex, unreadable code to be able to keep our jobs (and, to be honest, to punish people who stole our jobs), but been myself in the past unable to understand my own code, I decided to keep my sadistic inclinations away from work. Apologies.

Apologies accepted.

Step 3- release to production and test it

THE WHAT????

Well, that was my sadistic side acting again, sorry. I needed a way to be sure all my refactoring did not break anything but my soul. So I needed a set of tests.

Doh! If I could manage to have those tests while building the whole thing, I’d be able to more-or-less safely release it to QA without messing with users yet.

Introducing TDD and ABAP Units

Let’s stop for a bit. I’m sure you need a rest of all that wonderfully amazingness. Let’s talk about how an intelligent mammal (an orangutan, a chimp or maybe even a human being) would do that work from scratch: Test Driven Development.

In a nutshell, because I want not to talk too much if it’s not about me, TDD is a way to build software from tests. The what? Just keep it with me for a bit.

The TDD building process

Test list

First, you split your requirements into a list, and build a list of tests, one for each requirement. You split each test in as many smaller tests as possible. Then you add some other obvious tests to the collection (like “am I breathing?”).

You sort that test list from the easiest (and obviousest) to the complexest (or the least obvious). Let’s say you are creating a calculator with an “add” functoin. Your test list should be something like:

  • two numbers are provided
  • the result is the sum of both

But you must split those tests, and add some others:

  • two parameters are provided
  • check first parameter is a number
  • check second parameter is a number
  • check the output is a number

And then some other trivial ones, just for fun:

  • one plus one is two
  • one plus two is three

And now you can launch Eclipse and begin to work (hey! I’ve been working since I grabbed the first coffe before getting the requirements!). Yes, but your boss will not admit you are working if you don’t have a matrix-like set of screens full of code lines, right?.

Building from tests

The process is easy:

  • create a test
  • fail it
  • dirty-fix the code until you pass the test
  • refactor (and test again for mind peace)
  • rinse and repeat

So, you create a first test, let’s say

test test_1plus1equals2

if ( add 1 1) != 2 kill_the_guy

You run the test, and it fails, because you don’t have even the functionality. So you create the functionality (pseudocode in an invented language)

class calculator

method add importing first second returning result.

return 2

You run the test, and it works, You refactor the code (uh?) and test again. It’s still working.

So you rinse, and repeat with a new test

test test_2plus2equals3

if ( add 1 2 ) != 3 kill_the_guy

And it fails (because 1+2 = 2 … anything added equals 2 within our calculator, remember? we did it dirty).

So, you go to the code and put a sum on it:

class calculator

method add importing first second returning result

return first + second

And it works!! Now you can keep adding tests to the collection (what if no numbers provided, or whatever suits you the most). You add them one by one, you fail them (or don’t), you fix and refactor, and ask your boss for a raise, because you are (now) worth it.

Congratulations, you are a decent XXIst century developer

ABAP Units in a nutshell

(in a nutshell because this entry is not about them, it’s about me)

ABAP Units is a tool within SAP (in the GUI and in the eclips ADT or whatever the name is) that allows you to create “parallel” code to keep your tests. Basically, it’s like having a second program that automatically runs your first one, does all the checkings and returns the errors without effort (except for the whole building process).

Imagine it: you build your program, you press Ctrl+Shift+F10 and a small screen appears with all the mistakes you’ve made. Yes, you want to cry in the corner (again), but at least you know what the heck you ruined this time.

Benefits of this approach

Using TDD you build robust and efficient tools..

WRONG! your tools will be as robust and efficient as always

So, what then? Why all that pain?

Safety

Basically, because during the building process you will be able to detect desing/requirements flaws, and because you will know at each step you are going the right way (to the delivery and the money!).

More safety

Because every time you (or that guy who will stole your job) change any bit of code, the code will be able to test itself, and tell you (or that evildoer) what you have break this time.

Even more safety

Because every time a requirement changes you can change your tests before change your code. So your tests will guide you to the modifications to be make.

Uh?

Ok, let me explain. Imagine our user wants our add method to subtract. Just for fun, he’s a user, and he hates you.

So, before you change your class, you change your tests. Just the first one to allow you to grasp it (now, add 1 and 1 must return zero)

test test_1plus1equals0

if ( add 1 1) != 0 kill_the_guy

You run the test, it fails, so you fix the class. Theoritecatelly (or whatever) you should dirty fix it (lets say “return 0”), but as you know the whole class, and you have changed all the calculated tests, you can change your class directly to the goal

class calculator

method add importing first second returning result

return first – second

You should add some interesting tests to the class now, because subtraction has some weird behaviour (like negative numbers and so). But it’s up to you to follow this derrailed example. We were talking about me, my work and why am I that cool.

Back to the future – why my example is a wrong one?

Well.. let’s assume that I finished my work. I build a lot of tests and passed all of them. My code now is safe, and I can probably release it to production knowing it will not break anything. Of course, by the time I’ll do it, the requirements of the enhancement will be different, or my company declared bankrupcy, but (this time) it will not be my fault.

So, if I am delivering a safe (even safe) modification, why I am telling you this is a wrong example?

Because I did it the opposite way.

But this is not evil. TDD teaches us to move forward, and to build nice code (sometimes even cooler than that dude’s t-shirts with fractals) to embarrass our colleagues when we tell them “yes, we do TDD and your shirt sucks”.

But ABAP Units allow us to build tests after the work is done. That’s what I did (or that what’s I was doing before getting fired for spending too much time writing about me).

I made a massive rebuild of a critical chunk of code, and I am able to release it (to QM) with some degree of confidence. This time I don’t need to pack my stuff before the release, and I will (I wish) not have that termination letter, nor the citation for the suing process my company does to me for breaking his systems.

And now I have a bigger chunk of code, because I have the original functionality, plus all those “method endmethod” lines, declarations and local classes for testing.

BUT my code (let me repeat it) it’s safer than ever. And I will be able to change it the proper way (TDD) next time.

Conclusions

ABAP Unit is not only a tool for TDD geeks.

To spend time learning ABAP Unit and TDD is not a waste, it’s an invest (do you get it, Jelena?).

To wear a hat not just protects you from sun burns, but also helps you to write nice books.

Epilogue

Here I am. Twenty years in the future, reading this entry and feeling amazed about how great I were. Almost as great I am now.
Since that discussion in the Coffe Corner, I’ve been working TDD, and I made a lot of cash while keeping my users and my colleagues happy. They love me. Even more.

So yes, TDD and ABAP Units payed the effort I put on learning them. And now, while I turn off the computer and go to my retirement surprise party (I will put a surprise face, and I will tell them “doh, it’s not necessary, you could spend that money in charity… but thanks for the titanium watch”), I feel the proud of a work nicely done.

May be the change be with you.

Assigned Tags

      11 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Enno Wulff
      Enno Wulff

      haha Vicenç Xavier Lozano 😅! A very unconventional and humorous post about using unit tests. I laughed and smiled a lot and will go buy me a hat for reasons...

      thanks for this happy day starter!

      Author's profile photo Manfred Klein
      Manfred Klein

      ROFLMAO

      Especially: if <fail> kill_the_guy

      Author's profile photo Vicenç Xavier Lozano
      Vicenç Xavier Lozano
      Blog Post Author

      Long time ago, in another life, I had a colleague who put a message in a "this will never happen" case condition. The message said "Impossible error: kill the programmer".
      Five minutes after deploying the program, I received an email from the user asking me who the programmer was, because he had been said to kill him.
      Since that day, I don't put these kind of messages in "will never happen" cases or elses, just the classical "send this to your IT" thing.

      (although an assert or an X message may be more advisable)

      The colleague is still alive, but we had a lot of fun because him (really, we had a very good relationship with the users).

      Author's profile photo Manfred Klein
      Manfred Klein

      Cool story.

      Had learned myself also a long time ago that the computer has it's own definition of 'impossible'. So don't write what is not meant to be read.

      Sometimes your impossible stays really impossible for years. But one day the user changes the rules by behaving different. Because, as you said, he hates you. And voila: The impossible turns to the rule.

      Did you ever see one of those not-implemented-yet exceptions? Perhaps they are the perfect placeholders for today's impossible cases...

       

      Cya

      Author's profile photo Matthew Billingham
      Matthew Billingham

      I have a hat too. And Harper's gambit was invalid, because it wasn't followed by an "idiot" finesse. Which means it's my go. Bethnal Green.

      Author's profile photo Vicenç Xavier Lozano
      Vicenç Xavier Lozano
      Blog Post Author

      Bethnal having a hat? Are you sure about that?

      I will assume we are playing a recreation game, because the Campionship is over... If we ignore the current recreational games rule, and we do not use the current ruleset of that year, your move has sense... but because the hat.

      You cannot wear a hat in Tower Hamlets, mate. You could not do it even in 2012 because the Sunlight Restrictions (never supported those, I think they were too directed to give advantage to Brit tourists with flip-flops).

      So, I still win.

      Author's profile photo Michelle Crapo
      Michelle Crapo

      There are some awesome messages (learning points)  here.   I loved the humor and am laughing as I type this.

      Messages:

      1. Vicenç Xavier Lozano Lozano pretends he doesn't speak/write in English well.  It is a lie.  OK stretch of a truth.
      2. Vicenç Xavier Lozano needs to write more blogs.
      3. Create interesting messages.   I always liked the old SAP one - something about "working go take a coffee break".  That one wasn't a fun one for the users.   I kind of like "hate the programmer" or "kill the programmer" in my case would work because I don't live in the same state.
      4. Pokes a bit of fun at me.  (and others that haven't stated their TDD journey.  Or like me - that started it and then let it go to the end of the priority to learn heap.)    Which I always love.  IF I can't laugh at myself who can I laugh at? And it has my name in it.   Guarantees I'll read it.
      5. Great message of evolving and changing to meet the new technology.  His journey we all have our own.   Challenge to you who have read this far "Add your technology Journey".
      6. Wonderful example of using unit tests.  If for nothing else to catch things that "should never happen".

      TDD -  I showing lack of knowledge here - and yes I'll look it up later.  I wonder if it works with AMDP?  I also have been working with gateway services a lot.  Depending on how they are built.  I think I can add TDD to them.  Would I want to?  Trying to mix and match some of the "newer to me" coding with TDD.   Do other languages use something similar?

      Yes I have the books.  No, I usually don't read them cover to cover.  I use them more as an index or when I'm learning something new.   Perhaps I should rethink that.  (I Snap up a certain author's books almost as soon as they become available.)

      And I will go buy a hat.  I have several.  I'll dig them out for something fun.  Oh by the way - yes I can write a text book in my comments.

      If you have time - there are others not quite so entertaining of blogs from this post:

      My learn it later TDD - Explain my strange list for the last couple of years.

      The chicken or the Frog -  Pro TDD Sort of from Paul Hardy

      The original post on TDD - Do unit tests exist? - Enno Wulff

      The Coffee Corner Unit Tests in an SAP Customer Environment - "Free for all" basically say whatever you think...  Open Debate... It's a lot of fun.

      And if you want to have some fun start your own Coffee Corner discussion.   It might be like this one and the start of different blogs.  Or it could just be fore fun.  It is not formal, and you can even leave a open one line question.

       

      Author's profile photo Vicenç Xavier Lozano
      Vicenç Xavier Lozano
      Blog Post Author

      I've been lucky today to get my hands over another of Haul Pardy's great books: "Refactoring Legacy ABAP Code" (available at SAP PRESS) and I'm going through it while I keep my journey with those VA* "enhancements" thing.
      I loved to see I was going the right direction with my self-learning approach, and now I have even more hints to keep that way (use factory methods to ease the tests and make more robust code, a nice GIT repository about logging and a few more minor ones). I wll make a whole refactor over my refactor when I'll have time enough (an urgent matter has fallen over my head, and I have no hat at the office).

      I plan to keep working at my current place until my retirement, and we have had SAP only by just a couple of years, but we have our system full of legacy code. It looks like my old place, who was running SAP for over a decade. There's nothing worse than a I-want-your-cash consultant company: they don't invest on formation, and their crews are too burned out to think themselves about learn things in their free time (I cannot blame them).

      So, if you are enough lucky to get your hands over any Haul's books (or your heads under any of his hats), trust me, they are worth the cash and the time spent reading them.

      Author's profile photo Michelle Crapo
      Michelle Crapo

      Oh so true.  It's hard with the "I-want-your-cash" consultant.   I love it when we get a great consultant that can teach me things.

      I was - unfortunately - at times that consultant.  I always worked at a consulting firm.  One day - "I, the expert" had a manual in hand to learn the new thing while doing it.  At one time I had to learn about installing the Ethernet cables - yes that long ago, the I believe it was Pearl connection to SAP, and the software for the network.   That was VERY interesting.  Yes, I didn't work for that firm for very long after that. And I said "I will never work for a consultant firm again".

      Yes, I plan on working for my current place until...  Put anything in there.  I, at one time, worked for a company that went to all consultants.  They called my job redundant, or long term layoff.   Crazy.  So my future is always open to change.  "Never say never".  In between jobs I worked as a consultant.  Luckily I did know what I was doing for that job.

      Yes - Haul's are the best.  Well worth the expense, and they are fun to read.  Anything that keeps my attention is amazing.

      Author's profile photo Vicenç Xavier Lozano
      Vicenç Xavier Lozano
      Blog Post Author

      Never ever be that kind of consultant. You'll get the most for the first project, but you will never get the second one.

      Sadly, consultant companies do not understand it, because they will get the second project from the rivals and vice-versa ("vice" is key here)

      Author's profile photo Michelle Crapo
      Michelle Crapo

      Ha!!!   That would be why I got a different job.