Skip to Content
Technical Articles
Author's profile photo Johannes Gerbershagen

SAP Community Coding challenge – Randomize Unit-Tests

As i mention in my last blog-post randomize tests help discoving issues, which aren’t found by static tests. A big challenge for randomized test is the result verification part. We need some kind of reference model for verification. In this blog-post i want to show you in the first part the creation of a simple reference model and i have a coding challenge for a more complex reference model in the second part.

Simple reference model

The SAP community coding challenge from Feb. 2020 is our system under test. The system under test should count the number of words in a sentence and the number of unqiue letters for these words.
The reference model is used for automated unit tests. Basic idea is to create a word repository with common words and with the number of unique letters for these words. Random words are picked from the repository and concatenated to sentences. These sentences are analyzed by the system under test. The result from the system under test should be equal to the words picked up from the word repository.
The implementation looks like:


TYPES:
  BEGIN OF _word,
    written                     TYPE string,
    number_of_unique_characters TYPE int1,
  END OF _word,
  _words TYPE STANDARD TABLE OF _word WITH NON-UNIQUE KEY written,
  _words_repository TYPE SORTED TABLE OF _word WITH UNIQUE KEY written,
  BEGIN OF _sentence,
    written TYPE string,
    words   TYPE _words,
  END OF _sentence.

" System under test
FORM analyse_sentence USING sentence TYPE string
  CHANGING words TYPE _words.

  DATA(number_of_words) = count( val = condense( sentence ) regex = `(\b[^\s]+\b)` ).
  words = VALUE #( FOR index = 1 UNTIL index > number_of_words
    ( written = segment( val = sentence index = index space = ` ` )
      number_of_unique_characters = count( val = segment( val = sentence index = index space = ` ` ) regex = `(\S)(?!.*\1.*)` ) ) ).

ENDFORM.

CLASS random_tests DEFINITION FOR TESTING
  DURATION SHORT RISK LEVEL HARMLESS.

  PRIVATE SECTION.

    METHODS create_random_sentence
      RETURNING VALUE(result) TYPE _sentence.

    METHODS n_words_and_unique_letters FOR TESTING.

ENDCLASS.

CLASS random_tests IMPLEMENTATION.

  METHOD create_random_sentence.
    ##NEEDED
    DATA: _text TYPE string.

    DATA(word_repository) = VALUE _words_repository(
      ( written = 'is' number_of_unique_characters = 2 )
      ( written = 'excellent' number_of_unique_characters = 6 )
      ( written = 'consider' number_of_unique_characters = 8 )
      ( written = 'it' number_of_unique_characters = 2 )
      ( written = 'with' number_of_unique_characters = 4 )
      ( written = 'great' number_of_unique_characters = 5 )
      ( written = 'pleasure' number_of_unique_characters = 7 )
      ( written = 'that' number_of_unique_characters = 3 )
      ( written = 'we' number_of_unique_characters = 2 )
      ( written = 'announce' number_of_unique_characters = 6 )
      ( written = 'a' number_of_unique_characters = 1 )
      ( written = 'new' number_of_unique_characters = 3 )
      ( written = 'community' number_of_unique_characters = 8 )
      ( written = 'activity' number_of_unique_characters = 6 )
      ( written = 'the' number_of_unique_characters = 3 ) ).

    DATA(number_generator) = CAST if_random_number( NEW cl_random_number( ) ).

    DO number_generator->get_random_int( lines( word_repository ) ) TIMES.
      DATA(idx) = number_generator->get_random_int( lines( word_repository ) ).
      IF idx > 0.
        INSERT word_repository[ idx ] INTO TABLE result-words.
      ENDIF.
    ENDDO.

    DATA(written_words) = VALUE stringtab( FOR  IN result-words ( -written ) ).
    CONCATENATE LINES OF written_words INTO result-written SEPARATED BY space.

  ENDMETHOD.

  METHOD n_words_and_unique_letters.
    DATA actual_words TYPE _words.

    DO 100 TIMES.
      DATA(sentence) = create_random_sentence( ).

      PERFORM analyse_sentence USING sentence-written
        CHANGING actual_words.

      cl_abap_unit_assert=>assert_equals( exp = sentence-words
        act = actual_words ).
    ENDDO.

  ENDMETHOD.

ENDCLASS.

Coding challenge – complex reference model

System under test should be the pastafahndung kata (german language – english translation with a solution for method your_analysis below). You should create a reference model, which enables you to write a randomized unit-test. The unit-test should create random food orders and verify the key words found by method your_analysis. You can submit your solutions via private message until 2021-11-14 and i will publish a conclusion of the received solutions.

English translation of the coding challenge (truncated)

This coding challenge is a copy from Stefans contribution to the Abapforum.
The Mafia/Triaden/park offenders/system critic people control via food orders their illegal activities. The food orders contain keywords associated with certain crimes. It was possible to extract the association, but for now the informations are just collected. It can’t post the association …
The method your_analysis should scan the food orders for keywords and extract them. The keywords are abbreviated, that just the first 3 letters occur in the food order.
Given is the following program (Please copy the original program from github, SCN always removes some lines of the code):


" authors Stefan Schmöcker and Christian Günter
REPORT zss_knobel_2021_06 LINE-SIZE 1000.

CLASS lcl DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES: BEGIN OF ts_result,
             offset TYPE i,
             tier   TYPE string,
           END OF ts_result.
    TYPES: tt_results TYPE STANDARD TABLE OF ts_result WITH EMPTY KEY.
    METHODS:
      constructor,
      main,
      your_analysis IMPORTING iv_order          TYPE string
                    RETURNING VALUE(rt_results) TYPE tt_results.

    DATA: mt_tiere TYPE STANDARD TABLE OF string WITH EMPTY KEY.

ENDCLASS.

PARAMETERS: p_order TYPE string LOWER CASE DEFAULT '32 Pfannkuchen mit Apfelmus und 3x Schlemmerplatte rot/weiß'.

END-OF-SELECTION.

  NEW lcl( )->main( ).

CLASS lcl IMPLEMENTATION.
  METHOD your_analysis.

    rt_results = REDUCE #(
                   INIT result = VALUE tt_results(  )
                   FOR tier IN mt_tiere
                     LET search_string = tier(3) IN
                   FOR occ = 1 WHILE occ your_analysis( p_order ).
    LOOP AT lt_suspects ASSIGNING FIELD-SYMBOL().
      AT FIRST.
        WRITE:/ 'Verdächtige Bestellung :', p_order.
      ENDAT.
      NEW-LINE.
      POSITION 20.
      IF -offset > 0.
        WRITE p_order(-offset) NO-GAP.
      ENDIF.
      WRITE p_order+-offset(3) COLOR 6 NO-GAP.
      DATA(lv_offset_plus_3) = -offset + 3.
      IF lv_offset_plus_3 < strlen( p_order ).
        WRITE p_order+lv_offset_plus_3 NO-GAP.
      ENDIF.

      WRITE AT 120 -tier COLOR 7.
    ENDLOOP.
  ENDMETHOD.

  METHOD constructor.
    DATA: lv_tiere TYPE string.
    lv_tiere =  'Aal;Bandwurm;Coyote;Eber;Fasan;Gans;Hahn;Igel;Kabeljau;Lama;Made;Nacktmull;Panda;Rabe;Sardelle;Tarantel;Wal;Yak'
             && ';Adler;Bär;Dachs;Echse;Faultier;Geier;Hai;Iltis;Käfer;Nashorn;Ratte;Säbelzahntiger;Waran;Zander'
             && ';Affe;Barsch;Delfin;Eichhörnchen;Flamingo;Gemse;Hamster;Impala;Kamel;Nilpferd;Papagei;Raupe;Salamander;Tausendfüßler;Zebra'
             && ';Aguti;Beluga;Dodo;Eisbär;Floh;Gepard;Heilbutt;Ibis;Känguruh;Laus;Makrele;Ochse;Pelikan;Reh;Thunfisch;Wasserbüffel;Ziege'
             && ';Alligator;Biber;Dogge;Elch;Flunder;Giraffe;Hering;Jaguar;Karpfen;Leguan;Manta;Okapi;Pfau;Rentier;Tiger;Weinbergschnecke;Zitronenfalter'
             && ';Ameisenbär;Biene;Dompfaff;Emu;Forelle;Goldfisch;Hirsch;Katze;Lemming;Marabu;Orang-Utan;Pferd;Riesenkrake;Seeadler;Tintenfisch;Wespe'
             && ';Amöbe;Bison;Dorsch;Ente;Frosch;Gorilla;Holzwurm;Klapperschlange;Leopard;Maulwurf;Otter;Pinguin;Robbe;Silberfisch;Trampeltier;Wiesel'
             && ';Amsel;Blattlaus;Drossel;Esel;Fuchs;Grizzlybär;Hornisse;Koala;Libelle;Pottwal;Rochen;Spatz;Truthahn;Windhund'
             && ';Assel;Grauwal;Eule;Guppy;Huhn;Kranich;Löwe;Meerschwein;Puma;Rotkehlchen;Specht;Tsetsefliege;Wolf'
             && ';Auster;Bonobo;Hummer;Kröte;Luchs;Mistkäfer;Pute;Spinn;Uhu;Wombat'
             && ';Büffel;Hund;Kuh;Lurch;Milbe;Qualle;Stachelschwein;Vielfraß;Wurm;Bussard;Hyäne;Mondfisch;Stör;Vogelspinne;Motte;Schwein;Möwe;Mungo;Mücke;Murmeltier;Muschel'.
    SPLIT lv_tiere AT ';' INTO TABLE me->mt_tiere.

  ENDMETHOD.

ENDCLASS.

The table mt_tiere provides the possible keywords.

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo emrah mutlu
      emrah mutlu

      thanks for this article;