{"id":24510430,"url":"https://github.com/mindsquare-custom-solutions/tdd_samples","last_synced_at":"2025-03-15T09:40:44.880Z","repository":{"id":168887279,"uuid":"644704528","full_name":"mindsquare-Custom-Solutions/TDD_Samples","owner":"mindsquare-Custom-Solutions","description":"Test Driven Development Examples","archived":false,"fork":false,"pushed_at":"2024-08-16T12:03:30.000Z","size":28,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-22T00:33:44.910Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"ABAP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mindsquare-Custom-Solutions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-24T04:52:09.000Z","updated_at":"2024-08-16T12:03:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"31bca5ee-0804-4b16-bc5d-3de1941bb458","html_url":"https://github.com/mindsquare-Custom-Solutions/TDD_Samples","commit_stats":null,"previous_names":["mindsquare-custom-solutions/tdd_samples"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsquare-Custom-Solutions%2FTDD_Samples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsquare-Custom-Solutions%2FTDD_Samples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsquare-Custom-Solutions%2FTDD_Samples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsquare-Custom-Solutions%2FTDD_Samples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mindsquare-Custom-Solutions","download_url":"https://codeload.github.com/mindsquare-Custom-Solutions/TDD_Samples/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243713392,"owners_count":20335566,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-22T00:28:59.738Z","updated_at":"2025-03-15T09:40:44.861Z","avatar_url":"https://github.com/mindsquare-Custom-Solutions.png","language":"ABAP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://mindsquare.de/files/logo-mindsquare-176x781.png\" alt=\"mindsquare Logo\" title=\"mindsquare AG\" align=\"right\"\u003e\n\n# Begleitmaterialien zur Test Driven Development (TDD) Schulung\n\nCodebeispiele für die [mindsquare Test Driven Development Schulung](https://mindsquare.de/schulung/test-driven-development-mit-abap-unit/)\n\n## Beispielcode\n\n### zcl_aunit_calculator\n\n```abap\nCLASS zcl_aunit_calculator DEFINITION\n  PUBLIC\n  FINAL\n  CREATE PUBLIC .\n\n  PUBLIC SECTION.\n    METHODS add\n      IMPORTING number_1      TYPE i\n                number_2      TYPE i\n      RETURNING VALUE(result) TYPE i.\n    METHODS divide\n      IMPORTING number_1      TYPE i\n                number_2      TYPE i\n      RETURNING VALUE(result) TYPE i\n      RAISING   cx_sy_zerodivide.\n  PROTECTED SECTION.\n  PRIVATE SECTION.\nENDCLASS.\n\n\n\nCLASS zcl_aunit_calculator IMPLEMENTATION.\n  METHOD add.\n    result = number_1 + number_2.\n  ENDMETHOD.\n\n  METHOD divide.\n    IF number_2 = 0.\n      RAISE EXCEPTION TYPE cx_sy_zerodivide.\n    ENDIF.\n\n    result = number_1 / number_2.\n  ENDMETHOD.\nENDCLASS.\n```\n\n### zcl_aunit_converter\n\n```abap\nCLASS zcl_aunit_converter DEFINITION\n  PUBLIC\n  FINAL\n  CREATE PUBLIC .\n\n  PUBLIC SECTION.\n    METHODS: add_and_convert\n      IMPORTING number_1      TYPE i\n                number_2      TYPE i\n                currency      TYPE waers\n                bukrs         TYPE bukrs\n      RETURNING VALUE(result) TYPE char20.\n  PROTECTED SECTION.\n  PRIVATE SECTION.\nENDCLASS.\n\n\n\nCLASS zcl_aunit_converter IMPLEMENTATION.\n  METHOD add_and_convert.\n    data: sum_in_target_currency TYPE f.\n\n    select single waers from t001 where bukrs = @bukrs into @data(target_currency).\n    if sy-subrc \u003c\u003e 0.\n        result = 'invalid bukrs'.\n        return.\n    endif.\n\n    data(calculator) = new zcl_aunit_calculator(  ).\n\n    data(sum) = calculator-\u003eadd( number_1 = number_1 number_2 = number_2 ).\n\n    call function 'CONVERT_TO_LOCAL_CURRENCY'\n        EXPORTING\n            date = sy-datum\n            foreign_amount = sum\n            foreign_currency = currency\n            local_currency = target_currency\n        IMPORTING\n            local_amount = sum_in_target_currency\n        EXCEPTIONS\n            NO_RATE_FOUND = 1\n            OVERFLOW = 2\n            NO_FACTORS_FOUND = 3\n            NO_SPREAD_FOUND = 4\n            derived_2_times = 5\n            OTHERS = 6.\n\n    result = |{ sum_in_target_currency } { target_currency }|.\n  ENDMETHOD.\n\nENDCLASS.\n```\n\n## Injektionstechniken\n\n### Constructor Injection\n\nProduktivcode\n\n```abap\nCLASS … DEFINITION … .\n  PUBLIC SECTION.\n    METHODS \n      constructor \n        IMPORTING \n          i_cash_provider TYPE REF TO if_cash_provider OPTIONAL.\n  \n  PRIVATE SECTION.\n    DATA m_cash_provider TYPE REF TO if_cash_provider.\n  …\nENDCLASS.\n\nCLASS … IMPLEMENTATION.\n  METHOD constructor.\n    m_cash_provider = COND #( WHEN i_cash_provider IS BOUND\n                                THEN i_cash_provider\n                              ELSE NEW cl_cash_provider( ) ).\n  ENDMETHOD.\n  \n  …\nENDCLASS.\n```\n\n### Setter Injection\n\nProduktivcode\n\n```abap\nCLASS … DEFINITION … .\n  PUBLIC SECTION.\n    METHODS \n      set_cash_provider \n        IMPORTING \n          i_cash_provider TYPE REF TO if_cash_provider.\n  \n  PRIVATE SECTION.\n    DATA m_cash_provider TYPE REF TO if_cash_provider.\n  …\nENDCLASS.\n\nCLASS … IMPLEMENTATION.\n  METHOD set_cash_provider.\n    m_cash_provider = i_cash_provider.\n  ENDMETHOD.\n  …\nENDCLASS.\n```\n\n### Parameter Injection\n\nProduktivcode\n\n```abap\nCLASS … DEFINITION … .\n  PUBLIC SECTION.\n  METHODS \n    get_amount_in_coins\n      IMPORTING\n        i_amount TYPE i\n        i_cash_provider TYPE REF TO if_cash_provider OPTIONAL\n      RETURNING VALUE(r_value) TYPE i.\n\n  PRIVATE SECTION.\n    DATA m_cash_provider TYPE REF TO if_cash_provider.\n  …\nENDCLASS.\n\nCLASS … IMPLEMENTATION.\n  METHOD get_amount_in_coins.\n    DATA(cash_provider) = CAST if_cash_provider( COND #( \n      WHEN i_cash_provider IS BOUND\n        THEN i_cash_provider\n      ELSE NEW cl_cash_provider( ) ) ).\n    …\n  ENDMETHOD.\n  …\nENDCLASS.\n```\n\n### Backdoor Injection\n\nProduktivcode\n\n```abap\nCLASS … DEFINITION … .\n  PRIVATE SECTION.\n    DATA m_cash_provider TYPE REF TO if_cash_provider.\n  …\nENDCLASS\n```\n\nTestcode\n\n```abap\nCLASS ltc_get_amount_in_coins DEFINITION DEFERRED.\nCLASS cl_money_machine DEFINITION LOCAL FRIENDS ltc_get_amount_in_coins.\n\nCLASS ltc_get_amount_in_coins DEFINITION FOR TESTING … .\n  …\nENDCLASS.\n\nCLASS ltc_get_amount_in_coins IMPLEMENTATION.\n  METHOD setup.\n    \"given\n    m_cut = NEW #( ).\n    m_cut-\u003em_cash_provider = NEW ltd_cash_provider( ).\n  ENDMETHOD.\nENDCLASS.\n```\n\n## Test Double Terminologie\n\n### Stub\n\nErmöglicht das Setzen des indirekten Inputs aus der Testklasse heraus.\n\nAblauf:\n\n1. Test setzt gewünschten Rückgabewert in Stub\n2. Stub gibt den gewünschten Wert an den zu testenden Code\n\n```abap\nCLASS ltd_stub DEFINITION FOR TESTING.\n  PUBLIC SECTION.\n    INTERFACES if_cash_provider PARTIALLY IMPLEMENTED.\n    \n    DATA m_notes TYPE if_cash_provider=\u003ett_change.\nENDCLASS.\n\nCLASS ltd_stub IMPLEMENTATION.\n  METHOD if_cash_provider~get_notes.\n    r_notes = m_notes.\n  ENDMETHOD.\nENDCLASS.\n```\n\n### Spy\n\nErmöglicht das Logging der vom Produktivcode an die Dependent On Komponente übergebenen Parameter.\n\nAblauf:\n\n- Spy protokolliert den vom Code under Test übergebenen Wert\n- Der Test verifiziert den aufgezeichneten Wert\n\n```abap\nCLASS ltd_spy DEFINITION FOR TESTING.\n  PUBLIC SECTION.\n    INTERFACES if_cash_provider PARTIALLY IMPLEMENTED.\n\n    DATA m_currency TYPE string.\nENDCLASS.\n\nCLASS ltd_spy IMPLEMENTATION.\n  METHOD if_cash_provider~get_notes.\n    m_currency = i_currency.\n  ENDMETHOD.\nENDCLASS.\n```\n\n### Fake\n\nStellt eine einfache Implementierung der Dependent On Komponente dar.\n\n### Mock\n\nErweiterung der Konzepte Stub, Spy und Fake. Verifiziert je nach Anforderung den indirekten Output und/oder stellt indirekten Input zu Verfügung.\n\nAblauf:\n\n- Test setzt gewünschten Wert im Mock\n- Spy protokolliert den vom Code under Test übergebenen Wert\n- Stub gibt den gewünschten Wert an den Code under Test zurück\n- Der Test verifiziert den aufgezeichneten Wert\n\n```abap\nCLASS ltd_mock DEFINITION FOR TESTING.\n  PUBLIC SECTION.\n    INTERFACES if_cash_provider PARTIALLY IMPLEMENTED.\n  \n    DATA m_currency TYPE string.\n    DATA m_currency_exp TYPE string.\n    DATA m_notes TYPE if_cash_provider=\u003ett_change.\nENDCLASS.\n\nCLASS ltd_mock IMPLEMENTATION.\n  METHOD if_cash_provider~get_notes.\n    m_currency = i_currency.\n    r_notes = m_notes.\n  ENDMETHOD.\n\n  METHOD assert_expectations.\n    cl_abap_unit_assert=\u003eassert_equals( act = m_currency\n                                        exp = m_currency_exp ).\n  ENDMETHOD.\nENDCLASS.\n```\n\n### Dummy\n\nEin Dummy erfüllt die syntaktischen Anforderungen ohne weitere Logik.\n\n## Test Double Frameworks\n\n[Übersicht über die verschiedenen Test Double Frameworks](https://help.sap.com/docs/ABAP_PLATFORM_NEW/c238d694b825421f940829321ffa326a/04a2d0fc9cd940db8aedf3fa29e5f07e.html?locale=en-US)\n\n### ABAP OO Test Double Framework\n\n\u003e Verfügbar ab:\n\u003e\n\u003e - globale Interfaces: SAP NetWeaver 7.4 SP9\n\u003e - globale Klassen: AS ABAP 7.53\n\n- [ABAP Test Double Framework – An Introduction](https://blogs.sap.com/2015/01/05/abap-test-double-framework-an-introduction/)\n- [Short examples of CL_ABAP_TESTDOUBLE](https://blogs.sap.com/2018/04/03/short-examples-of-cl_abap_testdouble/)\n- [Beispielcode auf GitHub](https://github.com/sandraros/Demo-ATD/blob/master/src/z_atd_demo.prog.abap)\n\n### ABAP SQL Test Double Framework\n\n\u003e Verfügbar ab: AS ABAP 7.52\n\n- Beispielcode: `SABP_UNIT_DOUBLE_OSQL_DEMO`\n- Dokumentation: [ABAP SQL Test Double Framework](https://help.sap.com/docs/btp/sap-abap-development-user-guide/abap-sql-test-double-framework?locale=en-US)\n\n### ABAP CDS Test Double Framework\n\n\u003e Verfügbar ab: AS ABAP 7.51\n\n- Beispielcode: `SABP_UNIT_DOUBLE_CDS_DEMO`\n- Dokumentation: [ABAP CDS Test Double Framework](https://help.sap.com/docs/btp/sap-abap-development-user-guide/abap-cds-test-double-framework?locale=en-US)\n\n### ABAP Function Module Test Double Framework\n\n\u003e Verfügbar ab: AS ABAP 7.56\n\n- Beispielcode: `SABP_UNIT_DOUBLE_FUNCTION_DEMO`\n- Dokumentation: [Managing Dependencies on ABAP Function Modules with ABAP Unit](https://help.sap.com/docs/ABAP_PLATFORM_NEW/c238d694b825421f940829321ffa326a/75964f284aa9435da40c4d82e111f276.html?locale=en-US)\n\n### ABAP Authority Check Test Helper API\n\n\u003e Verfügbar ab: AS ABAP 7.55\n\n- Beispielcode: `SABP_UNIT_AUTHORITY_DEMO`\n- Dokumentation: [Managing Dependencies on ABAP Authority Checks with ABAP Unit](https://help.sap.com/docs/btp/sap-abap-development-user-guide/managing-dependencies-on-abap-authority-checks-with-abap-unit?locale=en-US)\n\n### Test Seams\n\n\u003e Verfügbar ab: SAP NetWeaver 7.5\n\n- [SAP Help](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentest_seams.htm)\n- [Working effectively with ABAP legacy code – ABAP Test Seams are your friend](https://blogs.sap.com/2016/02/06/working-effectively-with-abap-legacy-code-abap-test-seams-are-your-friend/)\n- [ABAP Test Seam for Unit Test with external dependencies – Personal guideline](https://blogs.sap.com/2018/06/08/abap-test-seam-for-unit-test-with-external-dependencies-personal-guideline/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindsquare-custom-solutions%2Ftdd_samples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmindsquare-custom-solutions%2Ftdd_samples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindsquare-custom-solutions%2Ftdd_samples/lists"}