Skip to Content
Technical Articles

Clean up your unit tests – introducing zcl_abap_unit_wrapper

Today I decided to show you how having a common base class for your unit tests might help you save some time and improve the readability of your tests.

The class I use simply wraps all non-deprecated methods from cl_abap_unit_assert. This means they keep the exact same signatures and just pass them on like this:

METHOD assert_equals.
    assertion_failed = cl_abap_unit_assert=>assert_equals(
      act = act
      exp = exp
      tol = tol
      level = level
      msg = msg
      quit = quit
      ignore_hash_sequence = ignore_hash_sequence ).
ENDMETHOD.

Let’s try to apply it to the test class used in my previous unit testing blog. A diff is worth a thousand words:

You can refactor existing test classes in two steps:

  1. Add inheritance.
  2. Use find/replace to get rid of cl_abap_unit_assert=> everywhere at once.

You can download the class from my blog’s git repository.

If you want to, you can take it and add your own often-used custom assert methods to have them accessible across your codebase.

Another advantage is easier testing of legacy code – you might not have certain assertion methods available on older releases, but you can pretend you do by replacing the cl_abap_unit_assert call in the base class with your downported version.

 

As always, hope this helps!

Frederik

6 Comments
You must be Logged on to comment or reply to a post.
  • The standard CL_AUNIT_ASSERT had the same usage but was superseded by CL_ABAP_UNIT_ASSERT which cannot be inherited any more. Isn’t it because it’s not a good OO pattern to inherit from such a class? (i.e. here the inheritance is a trick to easily use methods but it’s a bad model) Isn’t it better to create a class with a singleton pattern, and a static method to return it, in the “class_constructor” method of your test class you define a class attribute with a short name that may be used in all test methods? (x->assert_equals( … ))

    By the way, is it really a problem to keep cl_abap_unit_assert? It’s quickly written with the “assert” code template in ADT, and I don’t think the class will be removed one day.

    Note: using “CL_ABAP…” in the title attracted my attention because it looked like a standard SAP class, but it’s misleading. Why not using “ZCL_ABAP…”?

    sandra

    • Hi Sandra,

      Thank you for your constructive criticism.

      It is a bad idea to leave the assert class non-final for its creators. If somebody does inherit from it and defines their own assert_true method, you can never introduce assert_true on the base class, because that would constitute a breaking change. In fact you can’t introduce anything new at all, since you can’t know who did what with your class outside of your system.

      It is quite possibly the exact reason cl_abap_unit_assert was made in the first place instead of extending cl_aunit_assert. In fact, if you browse the code, you will find out the old cl_aunit_assert is now actually also a wrapper for cl_abap_unit_assert!

      What I do is misusing the intended purpose of inheritance, but you should always consider your particular use case. Don’t blindly follow paradigms. If you could misuse inheritance to save a child from a burning building, would you not do it because it is not mentioned in any OO guidelines?

      Recently I glued three chairs together to make a “shelf”. This is not the intended use of chairs and you can’t even use them as chairs anymore. People say it’s amazing though. And it does fit my use case: I had too many chairs and no shelf.

      So let’s look at this particular use case:

      I don’t see much point for the intended use of inheritance in a test class. Having to jump around to some base class to get the full picture goes against readability of tests, which should serve as executable documentation.

      This means I’m left with an otherwise empty inheritance slot to I can use to get a different feature ABAP is missing – importing static methods. I can only do it for one class at a time, but cl_abap_unit_assert is a particularly useful one here. I’m sure you can find such imports in test classes in other languages, it’s just that ABAP doesn’t make this possible.

      The way you described is more OO-correct, but also more boilerplate.

      If ABAP introduces a better way, you will find another post from me entitled ‘You can now forget all about zcl_abap_unit_wraper‘. I agree the original title was clickbait without the Z in the class name. It now has one.

       

      All the best in your future endeavors,

      Frederik

      • Thank you Frederik for this detailed answer, I understand and I agree for the boilerplate argument.

        By the way, there’s one drawback with your method, that you didn’t mention: when an assertion fails, SAP displays the call stack where the assertion occurs in the test method but hopefully the standard removes all procedures from the stack which are part of the ABAP Unit framework. With the addition of this custom assertion class, the custom class appears in the stack. That would be nice if there was a way to remove that “boilerplate part of the stack” 😉

        • Unfortunately, there is no way to do that, but you will quickly get used to going one level above in the call stack to look for the source of the problem.

  • I took some cabinets which were intended for storing compact discs, turned them around 90 degrees, stuck them on the wall and used them for bookshelves.

    That worked great but it was not the intended use. The intended use of mobile phones was for making phone calls, nowadays my phone can do all sorts of things but when I try to call my wife I can hardly hear her.

    I don’t think SAP will get rid of the current unit test class but you never know. They changed it once, they could change it again.

    I would note that in all the Java examples you inherit your test class from the central ASSERT class.

    It does make the code easier to read, which to me is such a huge advantage it over-rides almost any contrary argument.

    Cheersy Cheers

    Paul