Track test coverage for your R package and (optionally) upload the results to coveralls or codecov.
If you are already using Travis-CI or Appveyor CI add the
following to your project's .travis.yml
to track your coverage results
over time with Codecov.
r_github_packages:
- jimhester/covr
after_success:
- Rscript -e 'covr::codecov()'
To use a different CI service or call codecov()
locally you can set the
environment variable CODECOV_TOKEN
to the token generated on codecov.io.
Codecov currently has support for the following CI systems (* denotes support
without needing CODECOV_TOKEN
).
You will also need to enable the repository on Codecov.
Alternatively you can upload your results to Coveralls
using coveralls()
.
r_github_packages:
- jimhester/covr
after_success:
- Rscript -e 'covr::coveralls()'
For CI systems not supported by coveralls you need to set the COVERALLS_TOKEN
environment variable. It is wise to use a Secure Variable
so that it is not revealed publicly.
Also you will need to turn on coveralls for your project at https://coveralls.io/repos/new.
A shiny Application can be used to view coverage per line.
cov <- package_coverage()
shine(cov)
If used with type = "all", combine_types = FALSE
the Shiny Application will
allow you to interactively toggle between Test, Vignette and Example coverage.
cov <- package_coverage(type = "all", combine_types = FALSE)
shine(cov)
# if your working directory is in the packages base directory
package_coverage()
# or a package in another directory
cov <- package_coverage("lintr")
# view results as a data.frame
as.data.frame(cov)
# zero_coverage() can be used to filter only uncovered lines.
zero_coverage(cov)
covr
supports a couple of different ways of excluding some or all of a file.
The function_exclusions
argument to package_coverage()
can be used to
exclude functions by name. This argument takes a vector of regular expressions
matching functions to exclude.
# exclude print functions
package_coverage(function_exclusions = "print\\.")
# exclude `.onLoad` function
package_coverage(function_exclusions = "\\.onLoad")
The line_exclusions
argument to package_coverage()
can be used to exclude some or
all of a file. This argument takes a list of filenames or named ranges to
exclude.
# exclude whole file of R/test.R
package_coverage(line_exclusions = "R/test.R")
# exclude lines 1 to 10 and 15 from R/test.R
package_coverage(line_exclusions = list("R/test.R" = c(1:10, 15)))
# exclude lines 1 to 10 from R/test.R, all of R/test2.R
package_coverage(line_exclusions = list("R/test.R" = c(1, 10), "R/test2.R"))
In addition you can exclude lines from the coverage by putting special comments in your source code.
This can be done per line.
f1 <- function(x) {
x + 1 # nocov
}
Or by specifying a range with a start and end.
f2 <- function(x) { # nocov start
x + 2
} # nocov end
The patterns used can be specified by setting the global options
covr.exclude_pattern
, covr.exclude_start
, covr.exclude_end
.
Covr should be compatible with any testing package, it uses
tools::testInstalledPackage()
to run your packages tests.
Covr will not work with icc
, Intel's compiler as it does not have
Gcov compatible output.
Covr is known to work with clang versions 3.5+
and gcc version 4.2+
.
If the appropriate gcov version is not on your path you can set the appropriate
location with the covr.gcov
options. If you set this path to "" it will turn
off coverage of compiled code.
options(covr.gcov = "path/to/gcov")
covr
tracks test coverage by modifying a package's code to add tracking calls
to each call.
The vignette vignettes/how_it_works.Rmd contains a detailed explanation of the technique and the rational behind it.
You can view the vignette from within R
using
vignette("how_it_works", package = "covr")
Because covr modifies the package code it is possible there are unknown edge cases where that modification affects the output. In addition when tracking coverage for compiled code covr compiles the package without optimization, which can modify behavior (usually due to package bugs which are masked with higher optimization levels).