Code coverage tool usage
This topic describes how to use the code coverage feature.
Steps to get coverage information
Follow the next steps to collect and interpret coverage data:
- Delete all existing coverage data files (*.42m.cov)
- Enable coverage data file generation by setting the FGLCOV environment variable to 1.
- Execute your program several times (with fglrun): This will produce module.42m.cov files.
- Use the fglrun --merge-cov command, to merge module.42m.cov coverage data files and module.4gl source files, to produce readable coverage information files (module.4gl.cov)
- Inspect the module.4gl.cov to find how many times source code lines are executed.
Cleanup coverage data files
Before starting a new coverage data collection session, remove existing *.42m.cov data files.
$ rm -f *.42m.cov
Enable coverage data generation
Before starting a program, set the FGLCOV
environment variable, to instruct fglrun to produce coverage data
files:
$ export FGLCOV=1
In this topic, we will use the following program sample, to show how coverage data is produced
(pay attention to the line containing the
IF FALSE THEN
instruction: This will
illustrate how unreachable lines are detected):MAIN
DEFINE i INTEGER
FOR i=1 TO 10
IF i MOD 2 == 0 THEN
CALL func1()
END IF
END FOR
END MAIN
FUNCTION func1()
DISPLAY "Hello"
IF FALSE THEN
DISPLAY "... world!"
END IF
END FUNCTION
A coverage data file (module.42m.cov) will be created for
each module (module.42m), when running a
program:
$ fglcomp prog.4gl
$ fglrun prog
Hello
Hello
Hello
Hello
Hello
$ ls prog.*
prog.42m prog.42m.cov prog.4gl
The coverage data file is created in the directory where the module is found.
Important:
Coverage information is collected for several program executions: If a module.42m.cov file exist for a module, the execution count of source code lines will be summed up.
Merge coverage data with source files
The .42m.cov coverage data files contain only numbers. In order to interpret coverage data properly, you need to merge the coverage data files with the source file, by using the fglrun --merge-cov command:
$ fglrun --merge-cov prog.4gl
fglcov: prog.4gl.cov created
If the .4gl source file and the .42m.cov coverage data
file are not located in the same directory as the .42m module, specify the full
path to the coverage data file as second parameter for the --merge-cov
option:
fglrun --merge-cov mymodule.4gl ../dist/lib/mymodule.42m.cov
After a first time program execution, the resulting prog.4gl.cov file
contains:
-: 1:MAIN
-: 2: DEFINE i INTEGER
11: 3: FOR i=1 TO 10
10: 4: IF i MOD 2 == 0 THEN
5: 5: CALL func1()
-: 6: END IF
-: 7: END FOR
1: 8:END MAIN
-: 9:
-: 10:FUNCTION func1()
5: 11: DISPLAY "Hello"
5: 12: IF FALSE THEN
=====: 13: DISPLAY "... world!"
-: 14: END IF
5: 15:END FUNCTION
In the above output, a couple of code coverage indicators can be interpreted as follows:
- Line #2 shows a
-
(hyphen-minus) indicator: TheDEFINE
statement is not reachable, because it is a declaration statement. - Line #3 shows the number 11: The
FOR
(head) instruction has been executed 11 times (10 + 1 = 11, to jump out of the loop) - Line #4 shows the number 10: The
IF
statement inside theFOR
loop has been executed 10 times. - Line #13 shows
=====
: This line is reachable, but is never executed, since the parentIF
condition always evaluates toFALSE
.
By executing the sample program a second time, the existing coverage data files are completed
with additional information:
$ fglrun prog
Merge again the data files with source
files:
$ fglrun --merge-cov prog.4gl
fglcov: prog.4gl.cov created
And now check the new result
file:
-: 1:MAIN
-: 2: DEFINE i INTEGER
22: 3: FOR i=1 TO 10
20: 4: IF i MOD 2 == 0 THEN
10: 5: CALL func1()
-: 6: END IF
-: 7: END FOR
2: 8:END MAIN
-: 9:
-: 10:FUNCTION func1()
10: 11: DISPLAY "Hello"
10: 12: IF FALSE THEN
=====: 13: DISPLAY "... world!"
-: 14: END IF
10: 15:END FUNCTION
You can see that the execution counts of source code lines are summed up across program execution.