NAME
Code::Coverage - produce code coverage reports
SYNOPSIS
use Code::Coverage;
my $coverage := Code::Coverage.new(
targets => @modules,
runners => @test-scripts
);
$coverage.run;
say .key ~ ": " ~ .value for $coverage.missed;
DESCRIPTION
Code::Coverage is a class that contains the logic to run one or more Raku programs and produce code coverage of one or more targets (usually modules).
METHODS
new
my $cc := Code::Coverage.new(
targets => @modules,
runners => @test-scripts,
extra => "-I.", # default: none
repo => $repo, # default: $*REPO
tmpdir => ".", # default: %*ENV<TMPDIR> // $*HOME
slug => "foobar", # default: "code-coverage-"
keep => True, # default: False
);
$cc.run;
say "$cc.coverage() of code was covered";
The new
method accepts the following named arguments:
:targets
The targets
named argument indicates one or more targets for which coverage information should be created. Each of these can be specified as a path (either as string, or as an IO::Path
object), or as a use
target (identity) such as "String::Utils
".
Whatever was specified, will be returned by the targets
method.
:runners
The runners
named argument indicates the paths of one or more scripts that should be executed to determine coverage information. It should specify at least one script.
Whatever was specified, will be returned by the runners
method.
The extra
named argument indicates any extra command line arguments that should be set when calling the :runners
scripts. By default, no extra arguments are added. A typical usage would be "-I." to ensure that the current source of a module is used.
Whatever was specified, will be returned by the extra
method.
:repo
The repo
named argument indicates the CompUnit::Repository
object to be used when coverable lines are being deduced from bytecode. It defaults to $*REPO
, aka the default repository chain.
Whatever was specified, will be returned by the repo
method.
:tmpdir
The tmpdir
named argument specifies the path of the directory that should be used to store the temporary coverage files. It defaults to the TMPDIR
environment variable, or the home directory as known by $*HOME
.
Whatever was (implicitely) specified, will be returned by the tmpdir
method.
:slug
The slug
named argument specifies the prefix of the coverage files to be created. It defaults to "code-coverage-".
Whatever was (implicitely) specified, will be returned by the slug
method.
:keep
The keep
named argument specifies whether the temporary coverage files should be kept or not. Defaults to False
, which means that any coverage files will be removed after each call to .run
.
Whatever was (implicitely) specified, will be returned by the keep
method.
run
$cc.run("foo"); # test the "foo" code path
$cc.run("bar"); # test the "bar" code path
The run
method will execute all of the :runners
scripts, gather the coverage information, and update all internal information as applicable.
Any positional arguments specified will be added as command line arguments to the :runners
scripts. Note that it is fully ok to call this method more than once with a different set of parameters, to test different code paths in the runners.
out
print $cc.out;
The out
method returns the collected STDOUT output of all of the :runners
scripts since the last time the run
method was executed.
err
print $cc.err;
The err
method returns the collected STDERR output of all of the :runners
scripts since the last time the run
method was executed.
coverables
for $cc.coverables.values {
say .source.relative;
say .line-numbers;
}
The coverables
method returns a Map
with Code::Coverable
objects created for the :targets
specified, keyed by coverage key that will appear in coverage logs.
keys
say "Coverage keys:";
.say for $cc.keys;
The keys
method returns the coverage keys that were found for the given targets.
covered
say "Lines covered";
for $cc.covered {
say .key ~ ":\n$_.value.join(',')\n";
}
The covered
method returns a Map
, keyed by coverage key, with all of the lines that appear to have been covered by executing the runner scripts (possibly multiple times).
missed
say "Lines NOT covered";
for $cc.missed {
say .key ~ ":\n$_.value.join(',')\n";
}
The missed
method returns a Map
, keyed by coverage key, with all of the lines that appear to have NOT been covered by executing the runners (possibly multiple times).
coverage
say "Coverage:"
for $cc.coverage {
say .key ~ ": " ~ .value;
}
The coverage
method returns a Map
, keyed by coverage key, with as value a string containing the percentage of lines that were covered so far by executing the runners (possibly multiple times).
sources
say "Source files:"
for $cc.sources {
say .key ~ ": " ~ .value.absolute;
}
The sources
method returns a Map
, keyed by coverage key, with an IO::Path
object for the associated source file as the value.
source
say "$key: $cc.source($key).relative";
The source
method returns an IO::Path
object for the source file associated with the given coverage key.
annotated
print $cc.annotated($key);
The annotated
method produces the contents of the source-file indicated by the coverage key, with each line annotated with the coverage result. The following annotations are given:
*
- line was coverable, and covered
✱
- line was not coverable, but covered anyway
x
- line was coverable and not covered
`` - line was not coverable
num-coverable-lines
say $cc.num-coverable-lines;
The num-coverable-lines
method returns the total number of lines that are marked coverable in all coverage keys.
num-covered-lines
say $cc.num-covered-lines;
The num-covered-lines
method returns the total number of lines that are marked covered in all coverage keys.
num-missed-lines
say $cc.num-missed-lines;
The num-missed-lines
method returns the total number of lines that are marked coverable, but have not been covered in all coverage keys (yet).
max-lines
say $cc.max-lines; # max number of lines that can be covered
The max-lines
method returns the maximum number of lines that can be covered. In some edge cases, this may actually be greater than the number of lines that are marked coverable because some lines may appear in the coverage log that were not marked as coverable.
AUTHOR
Elizabeth Mattijsen liz@raku.rocks
Source can be located at: https://github.com/lizmat/Code-Coverage . Comments and Pull Requests are welcome.
If you like this module, or what I'm doing more generally, committing to a small sponsorship would mean a great deal to me!
COPYRIGHT AND LICENSE
Copyright 2024, 2025 Elizabeth Mattijsen
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.