{"id":8440,"date":"2019-11-04T15:12:58","date_gmt":"2019-11-04T14:12:58","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=8440"},"modified":"2023-01-20T13:15:13","modified_gmt":"2023-01-20T12:15:13","slug":"abap-unit-framework","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/abap-unit-framework\/","title":{"rendered":"ABAP Unit Framework"},"content":{"rendered":"\n<p>Nieod\u0142\u0105czn\u0105 cz\u0119\u015bci\u0105 programowania jest testowanie. Wszyscy (oby!) programi\u015bci po napisaniu kodu testuj\u0105 sw\u00f3j program w poszukiwaniu b\u0142\u0119d\u00f3w.&nbsp;Kiedy znajd\u0105 b\u0142\u0105d, poprawiaj\u0105 go i ponownie testuj\u0105 w poszukiwaniu kolejnego. Przy okazji dobrze by by\u0142o sprawdzi\u0107&nbsp; czy kolejne poprawki nie popsu\u0142y wcze\u015bniejszych. Ca\u0142y ten proces jest bardzo czasoch\u0142onny i mozolny. Wielokrotnie musimy testowa\u0107 te same elementy. Powoduje to nud\u0119 i zniech\u0119cenie. Dodatkowo potrafi by\u0107 bardzo demotywuj\u0105cy i frustruj\u0105cy kiedy kolejne poprawki generuj\u0105 nowe b\u0142\u0119dy. Sk\u0142ania to cz\u0119sto programist\u00f3w do \u201eodhaczania\u201d test\u00f3w jako z\u0142o konieczne. Jednak nie musi tak by\u0107. Cz\u0119\u015b\u0107 test\u00f3w mo\u017cemy zautomatyzowa\u0107 dzi\u0119ki czemu oszcz\u0119dzimy sobie czasu i niepotrzebnych nerw\u00f3w. Tu z pomoc\u0105 przychodzi nam ABAP Unit Framework. Jak sama nazwa wskazuje, s\u0142u\u017cy on do wykonywania test\u00f3w jednostkowych.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Czym s\u0105 wi\u0119c testy jednostkowe?<\/h3>\n\n\n\n<p>Jest to metoda testowania oprogramowania polegaj\u0105ca na testowaniu najmniejszych element\u00f3w naszego programu. Zazwyczaj s\u0105 to klasy, a dok\u0142adniej ich metody. Testowany element poddawany jest testowi, kt\u00f3ry sprawdza wynik zwracany przez element z oczekiwanym przez programist\u0119. Przy czym testy te powinny by\u0107 zautomatyzowane i powtarzalne.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Troch\u0119 praktyki<\/h3>\n\n\n\n<p>W celu przetestowania wybranej klasy edytujemy j\u0105 w transakcji\u00a0<strong>SE24<\/strong>\u00a0lub\u00a0<strong>SE80<\/strong>. W naszym przypadku jest to klasa przyk\u0142adowa\u00a0<em>ZTM_DATE_UTILS<\/em>\u00a0z 4 metodami. Ka\u017cda z tych metod\u00a0<strong>nie jest<\/strong>\u00a0jeszcze zaimplementowana. Z g\u00f3rnego menu wybieramy \u201eLocal Test Classes\u201d.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/1.png\"><img decoding=\"async\" width=\"949\" height=\"404\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/1.png\" alt=\"Klasa poddawana testom\" class=\"wp-image-18710\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/1.png 949w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/1-300x128.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/1-768x327.png 768w\" sizes=\"(max-width: 949px) 100vw, 949px\" \/><\/a><figcaption>Klasa poddawana testom<\/figcaption><\/figure><\/div>\n\n\n\n<p>Powinni\u015bmy zobaczy\u0107 ekran, gdzie mo\u017cemy zacz\u0105\u0107 pisa\u0107 nasz pierwszy test. W tym celu musimy stworzy\u0107 nasz\u0105 klas\u0119 testuj\u0105c\u0105. Dobrze przyj\u0119tym zwyczajem jest by klasa zaczyna\u0142a si\u0119 od przedrostka&nbsp;<em>LTC<\/em>&nbsp;(Local Test Class), a nast\u0119pnie nazwy klasy, kt\u00f3r\u0105 testujemy. Skoro nasza klasa, kt\u00f3r\u0105 testujemy nazywa si\u0119&nbsp;<em>ZTM_DATE_UTILS<\/em>&nbsp;to nasza klasa testowa b\u0119dzie mia\u0142a nazw\u0119&nbsp;<em>LTC_DATE_UTILS<\/em>.<\/p>\n\n\n\n<p>Dodatkowo do definicji klasy musimy doda\u0107 kilka s\u0142\u00f3w kluczowych:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Najwa\u017cniejszym z nich jest&nbsp;<em>FOR TESTING<\/em>. Bez tego ABAP Unit Framework nie b\u0119dzie uruchamia\u0142 test\u00f3w zawartych w naszej klasie.<\/li><li>Kolejnym jest&nbsp;<em>DURATION<\/em>&nbsp;+&nbsp;<em>SHORT<\/em>\/<em>MEDIUM<\/em>\/<em>LONG<\/em>. Okre\u015bla on czas wykonywania naszych test\u00f3w. Konfiguracja systemu, w kt\u00f3rym wykonujemy testy okre\u015bla dok\u0142adn\u0105 definicj\u0119 czasu wykonania i reakcj\u0119 na przekroczenie tego czasu (przerwanie testu, test zako\u0144czony niepowodzeniem, brak reakcji itp.)<\/li><li>Ostatnim&nbsp;<em>RISK LEVEL<\/em>&nbsp;+&nbsp;<em>HARMLESS<\/em>\/<em>DANGEROUS<\/em>\/<em>CRITICAL<\/em>. Okre\u015bla on poziom ryzyka akceptowalnego przez system. Je\u017celi nasz test ma wy\u017cszy poziom ryzyka ni\u017c akceptowany przez system to taki test nie zostanie wykonany.<\/li><\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCLASS ltc_date_utils DEFINITION FOR TESTING\n                                DURATION SHORT\n                                RISK LEVEL HARMLESS.\nENDCLASS.\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Generator<\/h3>\n\n\n\n<p>Dla tych, kt\u00f3rzy nie lubi\u0105 r\u0119cznie pisa\u0107 kodu istniej mo\u017cliwo\u015b\u0107 skorzystania z generatora.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-generator-SAP.png\"><img decoding=\"async\" width=\"791\" height=\"360\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-generator-SAP.png\" alt=\"Generator klasy testowej\" class=\"wp-image-18714\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-generator-SAP.png 791w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-generator-SAP-300x137.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-generator-SAP-768x350.png 768w\" sizes=\"(max-width: 791px) 100vw, 791px\" \/><\/a><figcaption>Generator klasy testowej<\/figcaption><\/figure><\/div>\n\n\n\n<p>Jednak kod wygenerowany przez generator pozostawia wiele do \u017cyczenia. Co prawda kompiluje si\u0119 bez problemu, jednak wymaga wielu poprawek jako\u015bciowych, kt\u00f3re potrafi\u0105 zaj\u0105\u0107 wi\u0119cej czasu ni\u017c stworzenie kodu od podstaw.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Pierwszy test<\/h3>\n\n\n\n<p>Kiedy mamy ju\u017c definicj\u0119 to mo\u017cemy przyst\u0105pi\u0107 do pisania pierwszego testu. Ka\u017cdy pojedynczy test w naszej klasie to jedna metoda. Przy czym metoda ta musi by\u0107 prywatna i zawiera\u0107 w definicji s\u0142owa kluczowe&nbsp;<em>FOR TESTING<\/em>. Metody testowe nie mog\u0105 przyjmowa\u0107, ani zwraca\u0107 \u017cadnych parametr\u00f3w. Mog\u0105 jednak rzuca\u0107 wyj\u0105tki.<\/p>\n\n\n\n<p>Zdefiniujmy zatem pierwszy test, w kt\u00f3rym przetestujemy metod\u0119\u00a0<em>GET_FIRST_DAY_OF_MONTH<\/em>. Chcemy otrzyma\u0107 pierwszy dzie\u0144 maja wi\u0119c nazwijmy nasz test\u00a0<em>GET_FIRST_DAY_OF_MAY<\/em>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCLASS ltc_date_utils DEFINITION FOR TESTING\n                                DURATION SHORT\n                                RISK LEVEL HARMLESS.\n  PRIVATE SECTION.\n    METHODS:\n      get_first_day_of_may    FOR TESTING\n      .\nENDCLASS.\n<\/pre><\/div>\n\n\n<p>Nast\u0119pnie dodajmy jego implementacj\u0119.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nMETHOD get_first_day_of_may.\n    &quot;Given\n    DATA(lo_cut) = NEW ztm_date_utils( ).\n\n    &quot;When\n    DATA(lv_first_day_of_may) = lo_cut-&gt;get_first_day_of_month( 5 ).\n\n    &quot;Then\n    cl_abap_unit_assert=&gt;assert_equals(\n      act = lv_first_day_of_may\n      exp = &#039;20190501&#039;\n      msg = &#039;Wrong first day of may&#039;\n    ).\n  ENDMETHOD.\n<\/pre><\/div>\n\n\n<p>Om\u00f3wmy sobie implementacj\u0119 naszego testu. W pierwszej kolejno\u015bci tworzymy instancj\u0119 klasy, kt\u00f3r\u0105 chcemy testowa\u0107 (<em>ZTM_DATE_UTILS<\/em>) pod nazw\u0105<em>&nbsp;lo_cut<\/em>. Nazwa ta nie jest przypadkowa. Przyj\u0119te jest, \u017ce instancje klas, kt\u00f3re testujemy nazywamy&nbsp;<em>CUT<\/em>&nbsp;(Class Under Test). Nast\u0119pnie wywo\u0142ujemy metod\u0119, kt\u00f3r\u0105 chcemy przetestowa\u0107 (<em>GET_FIRST_DAY_OF_MONTH<\/em>), a wynik jej dzia\u0142ania zapiszemy pod zmienn\u0105&nbsp;<em>lv_first_day_of_may<\/em>. Na samym ko\u0144cu sprawdzamy czy faktycznie otrzymany wynik to pierwszy maja.<\/p>\n\n\n\n<p>W tym miejscu po\u015bwi\u0119\u0107my chwil\u0119 uwagi na sam\u0105 struktur\u0119 testu oraz na sprawdzaniu wynik\u00f3w.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Struktura<\/h4>\n\n\n\n<p>Mo\u017cemy wyodr\u0119bni\u0107 trzy zasadnicze bloki w te\u015bcie, a mianowicie Given, When oraz Then. Czym s\u0105 zatem te bloki:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><em>Given \u2013<\/em>&nbsp;tutaj definiujemy stan pocz\u0105tkowy dla testu oraz wst\u0119pne za\u0142o\u017cenia<\/li><li><em>When \u2013&nbsp;<\/em>W tej sekcji wykonujemy wszystkie akcje, kt\u00f3re stanowi\u0105 test. Zazwyczaj powinno by\u0107 to wykonanie metody, kt\u00f3r\u0105 testujemy<\/li><li><em>Then \u2013&nbsp;<\/em>&nbsp;Sprawdzamy wyniki testu czyli czy nasza metoda zachowa\u0142a si\u0119 tak jak tego oczekiwali\u015bmy<\/li><\/ol>\n\n\n\n<p>Struktura&nbsp;<em>Given-When-Then<\/em>&nbsp;jest podej\u015bciem standardowym w przypadku test\u00f3w jednostkowych. Nie jest obowi\u0105zkowa, jednak zdecydowanie u\u0142atwia p\u00f3\u017aniejsze czytanie i analiz\u0119 test\u00f3w.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Sprawdzanie wynik\u00f3w testu<\/h4>\n\n\n\n<p>W tym celu stosujemy standardow\u0105 klas\u0119 ABAP czyli&nbsp;<em>CL_ABAP_UNIT_ASSERT<\/em>. Klasa ta zawiera wiele metod, kt\u00f3re pomagaj\u0105 w sprawdzaniu stanu testu. Mo\u017cemy dzi\u0119ki niej sprawdzi\u0107 czy tabela wynik\u00f3w zawiera konkretny rekord, czy zmienna referencyjna wskazuje na instancj\u0119 obiketu, czy pole systemowe&nbsp;<em>SY-SUBRC<\/em>&nbsp;zawiera konkretn\u0105 warto\u015b\u0107 itp. Zach\u0119cam do samodzielnego sprawdzenia metod tej klasy oraz ich parametr\u00f3w. W pierwszym te\u015bcie zastosowali\u015bmy metod\u0119&nbsp;<em>ASSERT_EQUALS<\/em>, kt\u00f3ra przyjmuje dwa obowi\u0105zkowe parametry czyli&nbsp;<em>act<\/em>&nbsp;(aktualnie sprawdzana przez nas warto\u015b\u0107),&nbsp;<em>exp<\/em>&nbsp;(oczekiwana warto\u015b\u0107) oraz dodatkowy parametr&nbsp;<em>msg<\/em>&nbsp;(tre\u015b\u0107 wiadomo\u015bci je\u017celi test nie zostanie spe\u0142niony).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Uruchamianie test\u00f3w<\/h3>\n\n\n\n<p>Skoro mamy ju\u017c pierwszy test to pora go uruchomi\u0107. W tym celu u\u017cyjemy skr\u00f3tu klawiszowego Ctrl+Shift+F10 (musimy ci\u0105gle znajdowa\u0107 si\u0119 klasie, kt\u00f3r\u0105 testujemy!). Po u\u017cyciu skr\u00f3tu naszym oczom powinien ukaza\u0107 si\u0119 ekran:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-results2-SAP-1024x396-1.png\"><img decoding=\"async\" width=\"1024\" height=\"396\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-results2-SAP-1024x396-1.png\" alt=\"ABAP Unit results2 SAP 300x116 - ABAP Unit Framework\" class=\"wp-image-18716\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-results2-SAP-1024x396-1.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-results2-SAP-1024x396-1-300x116.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-results2-SAP-1024x396-1-768x297.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption><em>Ekran z wynikami test\u00f3w<\/em><\/figcaption><\/figure><\/div>\n\n\n\n<p>Ekran ten sk\u0142ada si\u0119 z 3 pod ekran\u00f3w, kt\u00f3re om\u00f3wimy:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Lista wszystkich testowanych klas wraz testami jakie si\u0119 w nich znajduj\u0105 (mo\u017cna na raz uruchomi\u0107 wi\u0119cej ni\u017c jeden test)<\/li><li>Typ wiadomo\u015bci oraz jej tre\u015b\u0107. W naszym przypadku znajdziemy tam tekst podany w parametrze msg<\/li><li>Spodziewan\u0105 i aktualn\u0105 warto\u015b\u0107 jakie by\u0142y sprawdzane oraz stack trace naszego testu<\/li><\/ol>\n\n\n\n<p>Dlaczego nas test nie przeszed\u0142? Ot\u00f3\u017c nie stworzyli\u015bmy implementacji metody\u00a0<em>GET_FIRST_DAY_OF_MONTH<\/em>. Dodajmy zatem bardzo prost\u0105 implementacj\u0119<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nMETHOD get_first_day_of_month.\n    IF iv_month_number &lt; 10.\n      rv_first_month_day = sy-datum(4) &amp;&amp; '0' &amp;&amp; iv_month_number &amp;&amp; '01'.\n    ELSE.\n      rv_first_month_day = sy-datum(4) &amp;&amp; iv_month_number &amp;&amp; '01'.\n    ENDIF.\n  ENDMETHOD.\n<\/pre><\/div>\n\n\n<p>Nie jest ona idealna, ale na nasze potrzeby w zupe\u0142no\u015bci wystarczy. Ponownie stosujemy skr\u00f3t klawiszowy Ctrl+Shift+F10. Powinni\u015bmy teraz zobaczy\u0107 kr\u00f3tk\u0105 informacj\u0119 na pasku wiadomo\u015bci o pomy\u015blnym dzia\u0142aniu testu. Co je\u015bli chcieliby\u015bmy mimo wszystko zobaczy\u0107 wynik testu w tej samej formie jak w przypadku niepowodzenia? Nic prostszego. W tym celu musimy skorzysta\u0107 z menu kontekstowego :<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-context-menu-SAP.png\"><img decoding=\"async\" width=\"961\" height=\"404\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-context-menu-SAP.png\" alt=\"ABAP Unit context menu SAP 300x126 - ABAP Unit Framework\" class=\"wp-image-18712\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-context-menu-SAP.png 961w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-context-menu-SAP-300x126.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/11\/ABAP-Unit-context-menu-SAP-768x323.png 768w\" sizes=\"(max-width: 961px) 100vw, 961px\" \/><\/a><figcaption>Menu kontekstowe do uruchomienia test\u00f3w<\/figcaption><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Podsumowanie<\/h3>\n\n\n\n<p>Uda\u0142o nam si\u0119 stworzy\u0107 test dla metody&nbsp;<em>GET_FIRST_DAY_OF_MONTH<\/em>. W naszej klasie pozosta\u0142y jeszcze 3 metody bez test\u00f3w. Sugeruj\u0119 w ramach \u0107wicze\u0144 samemu napisa\u0107 test dla nich. Poniewa\u017c nasz test jest zapisany, to mo\u017cemy go wykonywa\u0107 wielokrotnie. Je\u017celi zdarzy nam si\u0119 z jakiego\u015b powodu zmieni\u0107 metod\u0119 to kilkoma klikni\u0119ciami jeste\u015bmy w stanie szybko sprawdzi\u0107 poprawno\u015b\u0107 naszych zmian. Dodatkowym plusem pisania test\u00f3w jest mo\u017cliwo\u015b\u0107 szybkiego debugowania ma\u0142ych kawa\u0142k\u00f3w kodu. Zamiast \u201eprzeklikiwa\u0107\u201d si\u0119 przez ca\u0142\u0105 aplikacj\u0119, \u017ceby sprawdzi\u0107 czy nowa metoda dzia\u0142a, wystarczy napisa\u0107 kr\u00f3tki test, w kt\u00f3rym mo\u017cemy bez problemu ustawi\u0107 break-point. Przyspiesza to znacznie pisanie kodu.<\/p>\n\n\n\n<p>Mam nadziej\u0119, \u017ce cho\u0107 w minimalnym stopniu uda\u0142o mi si\u0119 przybli\u017cy\u0107 czym jest ABAP Unit Framework. Poniewa\u017c temat jest bardzo obszerny, zach\u0119cam do jego wi\u0119kszego samodzielnego zg\u0142\u0119bienia oraz \u0107wicze\u0144.<\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;8440&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;4&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 4)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;ABAP Unit Framework&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 4)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Nieod\u0142\u0105czn\u0105 cz\u0119\u015bci\u0105 programowania jest testowanie. Wszyscy (oby!) programi\u015bci po napisaniu kodu testuj\u0105 sw\u00f3j program w poszukiwaniu b\u0142\u0119d\u00f3w.&nbsp;Kiedy znajd\u0105 b\u0142\u0105d, poprawiaj\u0105 &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/abap-unit-framework\/\">Continued<\/a><\/p>\n","protected":false},"author":225,"featured_media":8446,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[548,807,860,811,859],"class_list":["post-8440","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-sap","tag-testowanie","tag-abap-unit","tag-sap-abap","tag-tests"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/10\/Testing-SAP.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/8440"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/225"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=8440"}],"version-history":[{"count":3,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/8440\/revisions"}],"predecessor-version":[{"id":18720,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/8440\/revisions\/18720"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/8446"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=8440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=8440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=8440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}