‎2019 Oct 31 8:36 AM
Hi All
I've created the CDS table function and would like to write unit test for it:
define table function Z_COMP_CODE
with parameters
@Environment.systemField: #CLIENT
clnt : abap.clnt,
sel_opt : abap.char( 1000 )
returns
{
Client : abap.clnt;
CompanyCodeOld : bukrs;
ProfitCenter : prctr;
ValidFrom : datab;
ValidTo : datbi;
CompanyCodeNew : bukrs;
}
implemented by method
ycl_cme_table_function=>QUERY_COMPANY_CODE;
Is it possible to write unit test for table functions?
Thanks
‎2019 Oct 31 8:48 AM
Hello Anujit Marty,
Of Course you can, One simple way is write a test program where you have the required fields in the select Option. Now dynamically you have to wrap the select Option and feed into the parameters of CDS. Inside the table function method you have to use APPLY_FILTER function to apply the select options.
You can refer the below Blog which will guide you on the same.
Regards!
‎2019 Oct 31 8:53 AM
‎2019 Oct 31 10:08 AM
In case the hyperlink goes wrong in the future, the chapter is "Writing Unit Tests Using CDS Test Double Framework"
‎2019 Oct 31 10:20 AM
There is always dead link in the forum, wonder if we could create it differently ...
‎2019 Oct 31 10:37 AM
How to create abap test class for table function?
On the CDS View, you can create a ABAP Test Class but for table function not:
‎2019 Oct 31 11:49 AM
I never try, it is a next chapter of my book 😉
Core Data Services for ABAP (SAP Press)
‎2019 Oct 31 12:33 PM
Anujit Marty The documentation of method INSERT_TEST_DATA of IF_CDS_TEST_ENVIRONMENT says: "If the dependency is of type cds view or cds table function with input parameters, also provide the test data for the input parameters. Test_data for parameters will get matched against the actual parameter values by which the dependent CDS View or CDS table function is called during execution. If only both matches, the double will return the test_data."
‎2019 Oct 31 1:58 PM
sandra.rossi Could you please try to create a cds table function and then create in addition ABAP Test Class.
I can not even create the ABAP Test Class. It is impossible, please try.
‎2019 Oct 31 2:17 PM
You have a blog on this subject here https://blogs.sap.com/2018/08/30/cds-doubles-writing-unit-tests-for-abap-cds/
the interface if_cds_test_environment is unknown in my SAP Release
‎2019 Oct 31 3:57 PM
I've tried as follow:
METHOD query_with_valid_data.
data lo_environment type ref to if_cds_test_environment.
lo_environment = cl_cds_test_environment=>create( i_for_entity = 'YCME_FN_COMP_CODE' ).
break-POINT.
ENDMETHOD.And the compiler complains:
Testing of table functions is not supported
‎2019 Oct 31 4:02 PM
Anujit Marty See my reply, in a distinct answer. In fact, the CDS test double framework doesn't seem to work for table functions... (at least in my S/4HANA 7.52 SP0 system)
‎2019 Nov 01 12:15 PM
EDIT: Anujit Marty oops sorry, I was wrong. I edited my distinct answer, with a working example.
‎2019 Oct 31 3:40 PM
EDIT: this answer is wrong because I don't test the CDS Table Function, I just mock it. Thank you szebenyi_balint for notifying (see comments). Currently, I don't know how to test the CDS Table Function, sorry !
Original obsolete answer:
I could make the Unit Test of CDS Table Function work.
I had to wrap it in a CDS View.
I created a test environment for this CDS view, and inserted data for the CDS Table Function: you inject data to be returned based on the input parameters.
CDS Table Function:
define table function Z_COMP_CODE
with parameters
@Environment.systemField: #CLIENT
clnt : abap.clnt,
sel_opt : abap.char( 1000 )
returns
{
mandt : abap.clnt;
carrid : s_carr_id;
}
implemented by method
ycl_cme_table_function=>QUERY_COMPANY_CODE;AMDP Class:
CLASS ycl_cme_table_function DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_amdp_marker_hdb.
CLASS-METHODS query_company_code FOR TABLE FUNCTION z_comp_code.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ycl_cme_table_function IMPLEMENTATION.
METHOD query_company_code BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
USING scarr.
lt_scarr = apply_filter( scarr, :sel_opt );
RETURN SELECT mandt, carrid FROM :lt_scarr;
ENDMETHOD.
ENDCLASS.CDS View:
@AbapCatalog.sqlViewName: 'Z_COMP_CODEVIEW2'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'CDS view'
define view Z_COMP_CODE_VIEW
with parameters sel_opt : abap.char(1000)
as select from Z_COMP_CODE( clnt: $session.client, sel_opt: $parameters.sel_opt) {
mandt,
carrid
}<br>ABAP code:
CLASS lcl_app DEFINITION.
PUBLIC SECTION.
TYPES: ty_s_carrid TYPE RANGE OF scarr-carrid,
ty_z_comp_code_tab TYPE STANDARD TABLE OF z_comp_code WITH EMPTY KEY.
METHODS get_z_comp_code_tab
IMPORTING
s_carrid TYPE ty_s_carrid
RETURNING
VALUE(z_comp_code_tab) TYPE ty_z_comp_code_tab.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD get_z_comp_code_tab.
DATA : lt_tab TYPE TABLE OF z_comp_code,
l_where TYPE string.
" Example if s_carrid = VALUE #( ( sign = 'I' option = 'CP' low = 'A*' ) )
" and current client = '100', l_where will have value: MANDT = '100' AND ( CARRID LIKE 'A%')
l_where = cl_shdb_seltab=>combine_seltabs(
it_named_seltabs = VALUE #( ( name = 'CARRID' dref = REF #( s_carrid[] ) ) )
iv_client_field = 'MANDT' ).
SELECT *
FROM z_comp_code_view( sel_opt = @l_where )
INTO TABLE @z_comp_code_tab
##db_feature_mode[amdp_table_function].
ENDMETHOD.
ENDCLASS.
CLASS ltc_main DEFINITION
FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS: setup,
test FOR TESTING.
CLASS-DATA: environment TYPE REF TO if_cds_test_environment.
CLASS-METHODS: class_setup,
class_teardown.
ENDCLASS.
CLASS ltc_main IMPLEMENTATION.
METHOD class_setup.
environment = cl_cds_test_environment=>create(
i_for_entity = 'Z_COMP_CODE_VIEW' ). " The CDS view (calling the table function)
ENDMETHOD.
METHOD test.
TYPES: ty_scarr_tab TYPE STANDARD TABLE OF scarr WITH EMPTY KEY.
environment->insert_test_data( " stub the CDS Table Function Z_COMP_CODE
i_data = VALUE lcl_app=>ty_z_comp_code_tab(
( carrid = 'AY' ) )
i_parameter_values = VALUE #(
( parameter_name = 'CLNT' parameter_value = sy-mandt )
( parameter_name = 'SEL_OPT' parameter_value = |MANDT = '{ sy-mandt }' AND ( CARRID LIKE 'A%')| ) ) ).
DATA(z_comp_code_tab) = NEW lcl_app( )->get_z_comp_code_tab( VALUE #( ( sign = 'I' option = 'CP' low = 'A*' ) ) ).
cl_abap_unit_assert=>assert_equals(
act = z_comp_code_tab
exp = VALUE lcl_app=>ty_z_comp_code_tab( ( carrid = 'AY' ) ) ).
ENDMETHOD.
METHOD class_teardown.
environment->destroy( ).
ENDMETHOD.
METHOD setup.
environment->clear_doubles( ).
ENDMETHOD.
ENDCLASS.
DATA : carrid TYPE scarr-carrid.
SELECT-OPTIONS : s_carrid FOR carrid.
START-OF-SELECTION.
NEW lcl_app( )->get_z_comp_code_tab( s_carrid[] ).
‎2019 Nov 01 11:17 AM
‎2019 Nov 01 12:16 PM
Anujit Marty No, sorry, it works. See the last version of my answer.
‎2019 Nov 04 8:15 AM
‎2021 Mar 24 9:17 AM
Sorry but this is not testing the table function. The table function is mocked out and it stands in the comment in the ABAP code as well. If you stub out the tf behind the view then you are not testing the logic in the table function!
Observe that the test environment holds a double for the tf. Try putting an AMDP breakpoint in the AMDP method it won't stop there while unit testing, since that is mocked out, but when you run the report it will stop at the AMDP breakpoint during that real usage.
So this example is not good for unit testing it lures you into the illusion that your tf works whereas what you are doing is you are telling the system that the tf will always give back AY which you then verify that it indeed gives back AY - this is definitely a false hope regarding the tf's behaviour.
‎2021 Mar 24 10:47 AM
‎2021 Mar 24 2:28 PM
The code mocks the tf so that when it receives those parameters it will return AY - independent of the tf coding. So the actual tf is not called but mocked out. This code does not test the logic inside the tf, just checks if it is called with those parameters - in which case it returns AY.
Try removing the inner part of the tf and run the unit tests.
‎2019 Oct 31 4:41 PM
I couldn't successfully unit test the CDS table function. I recommend to ask the SAP author in this blog post: https://blogs.sap.com/2016/10/19/introduction-cds-test-double-framework-write-unit-tests-abap-cds-en...
‎2019 Nov 01 12:22 PM
I agree with sandra.rossi. Following the metioned blog you can make your test bifunctor 🙂