2021 Jun 10 2:34 PM
The following ABAP report calls p_times times a function module which does nothing ('RFC_PING'), while being supervised by the coverage API (see subroutine measure_a_nop at the bottom of the report).
The expected result would be that it reports `1 proc. executed` in the function group SRFC where the do-nothing function module resides. Unfortunately, we see that it sometimes reports 0 executions.
What is the cause of this error?
(BTW - I am using RFC_PING only for demo purposes. The problem is unrelated to the fact that RFC_PING has an empty implementation. The same happens with methods which really do something.)
*&---------------------------------------------------------------------*
*& Report ZZ_TEST_COVERAGE_ZEROES
*&---------------------------------------------------------------------*
*& Using the Coverage Analyzer API, we regularly but not always
*& experience the case that the coverage is zero although it should
*& have measured a coverage.
*&---------------------------------------------------------------------*
report zz_test_coverage_zeroes.
parameters: p_times type i default 10.
start-of-selection.
perform start.
form start.
do p_times times.
perform measure_a_nop.
enddo.
endform.
class lcl_coverage definition.
public section.
types: begin of ty_result,
procs_executed type i,
procs_total type i,
end of ty_result.
methods:
constructor importing iv_prog type csequence,
start,
stop,
get_result
returning value(es_result) type ty_result.
data:
go_cov_factory type ref to if_scv_factory read-only,
gv_prog type repid read-only,
go_cov_m type ref to if_scv_measurement read-only,
go_cov_s type ref to if_scv_selection read-only.
private section.
methods:
get_selection
importing iv_prog type repid
returning value(eo_cov_s) type ref to if_scv_selection.
endclass.
class lcl_coverage implementation.
method constructor.
gv_prog = iv_prog.
go_cov_factory = cl_scv_coverage_api=>get_factory( ).
go_cov_m = go_cov_factory->create_measurement( ).
go_cov_s = get_selection( iv_prog ).
go_cov_m->set_selection( go_cov_s ).
endmethod.
method get_selection.
eo_cov_s = go_cov_factory->create_selection( ).
eo_cov_s->set_program_range( value #( (
low = iv_prog
sign = 'I'
option = 'EQ'
) ) ).
endmethod.
method start.
check gv_prog is not initial.
go_cov_m->start( ).
endmethod.
method stop.
check gv_prog is not initial.
go_cov_m->stop( ).
endmethod.
method get_result.
check gv_prog is not initial.
data(lo_cov_r) = go_cov_m->build_program_result( gv_prog ).
data(lo_cov_proc) = lo_cov_r->get_coverage( ce_scv_coverage_type=>procedure ).
es_result-procs_executed = lo_cov_proc->get_executed( ).
es_result-procs_total = lo_cov_proc->get_total( ).
endmethod.
endclass.
form measure_a_nop.
data(lo_cov) = new lcl_coverage( 'SAPLSRFC' ).
lo_cov->start( ).
call function 'RFC_PING'.
lo_cov->stop( ).
data(ls_result) = lo_cov->get_result( ).
write: / ls_result-procs_executed, ls_result-procs_total.
endform.
2021 Jun 17 7:31 AM
I found out: when waiting 5 seconds before starting the next iteration, all the results are correct (1 or 2 seconds was not enough).
This is unsatisfactory, however: obviously, there is some "teardown" performed asynchronously by the coverage analyzer behind the scenes. How to finalize these operations programmatically? Or how to get notified when this asynchronous teardown is completed?
And, no: calling the method finalize() isn't the solution: Adding the finalize() call at the end of the measurement process, did not fix the problem. Something more is happening asynchronously.
form start.
do p_times times.
WAIT UP TO 5 SECONDS.
perform measure_a_nop.
enddo.
endform.
2021 Aug 05 10:49 AM
For those who googled this question: this is SAP's answer from the OSS message that I had opened for this problem:
the coverage analyzer only flushes coverage data to the database if more than 5 seconds have elapsed since the last flush. This behavior is intended and was implemented to avoid performance issues caused by too many flushes in a short time.This is the reason why the coverage in your test program is always measured correctly when you wait 5 seconds between the executions of your function module, instead of waiting for shorter intervals.A possible workaround to this issue would be to implement your tests as unit tests and to perform them with coverage measurement. For unit tests, coverage data will be flushed to the database even if less than 5 seconds have passed since the last flush.