Code Coverage¶
Nagelfar has support for doing simple code coverage analysis.
Instrument each file:
nagelfar.tcl -instrument apa.tcl
That creates apa.tcl_i
Make your tests run the instrumented file. If a file is sourced from an instrumented file, an instrumented version (i.e. one called _i) will be read if it exists. Thus you only need to adjust the top file being called from the test, if all other files are accessed through source.
You do not need to keep the instrumented name. You can rename them back to the original if you cannot use _i or the automatic “source” redirection for some reason. Use the command line option -nosource to stop overloading of source in the instrumented file.
The source under test must terminate using the “exit” command. The instrumentation uses the exit command to produce the result, thus it needs to be called to work as expected.
If you cannot end your tests with “exit”, you can call the internal command
::_instrument_::cleanup
manually. Note that this command name is not
guaranteed, so try to use “exit”.
Running tests creates apa.tcl_log
.
Coverage data is accumulated in the log file so multiple tests can
be run. Make sure the log file is deleted before a rerun.
Create a markup file for displaying result:
nagelfar.tcl -markup apa.tcl
This reads coverage data from apa.tcl_log
and creates apa.tcl_m
. The
markup file contains markers in blocks that were not run. If -markupfull
is used instead, covered code also gets markers but with counts.
See uncovered parts by comparing original with markup in a graphical diff tool, like eskil:
eskil -noparse apa.tcl apa.tcl_m
The directory where _i, _log and _m files are stored can be redirected with
-idir <dir>
.
Pragmas¶
A branch can be ignored using the nocover pragma.
You can also collect variable usage, which reports all unique values that variable has had.
if {![file exists $file]} { ##nagelfar nocover
...
}
##nagelfar cover variable y
Example¶
Nagelfar’s testsuite has code like this to automatically run the instrumented file:
set file nagelfar.tcl
if {[file exists ${file}_i]} {
set file ${file}_i
}
Below is the makefile lines used by Nagelfar to test itself.
# Source files for code coverage
SRCFILES = nagelfar.tcl
IFILES = $(SRCFILES:.tcl=.tcl_i)
LOGFILES = $(SRCFILES:.tcl=.tcl_log)
MFILES = $(SRCFILES:.tcl=.tcl_m)
# Instrument source file for code coverage
%.tcl_i: %.tcl
@./nagelfar.tcl -instrument $<
# Target to prepare for code coverage run. Makes sure log file is clear.
instrument: $(IFILES)
@rm -f $(LOGFILES)
# Run tests to create log file.
$(LOGFILES): $(IFILES)
@./tests/all.tcl $(TESTFLAGS)
# Create markup file for better view of result
%.tcl_m: %.tcl_log
@./nagelfar.tcl -markup $*.tcl
# View code coverage result
icheck: $(MFILES)
@for i in $(SRCFILES) ; do eskil -noparse $$i $${i}_m & done
# Remove code coverage files
clean:
@rm -f $(LOGFILES) $(IFILES) $(MFILES)
Naming conventions¶
When xxx
is instrumented, result is called xxx_i
.
The “source” command is overloaded to prefer xxx_i
if
it exists, when xxx
is sourced.
Instrumented files can be renamed to the original before running, if that is desired.
The log files for xxx_i
or xxx
is called xxx_log
.
At startup any existing log is read, to accumulate info.
The “exit” command is overloaded to call ::_instrument_::cleanup
,
which produces the logs. If you cannot end your tests with “exit”,
you can call ::_instrument_::cleanup manually
. Note that this
command name is not guaranteed, so try to use “exit”.
Markup of xxx
reads xxx_log
and produces xxx_m
.