Learn R Programming

Doctest

Documentation examples and tests are similar in some ways:

  • They are self-contained pieces of code.

  • They should cover the software’s most important functions and typical uses.

  • They should be simple and clear: complex examples are hard for users to understand, and complex test code can introduce testing bugs.

This similarity makes it attractive to use “doctests”, which combine tests and documentation. Indeed, several languages, including Python and Rust, have doctests built in.[1] R also checks for errors in examples when running R CMD check.

The doctest package extends this idea. It lets you write testthat tests, by adding tags to your roxygen documentation. This helps you check that your examples do what they are supposed to do.

Example

Here’s some roxygen documentation for a function:


#' Fibonacci function 
#' 
#' @param n Integer
#' @return The nth Fibonacci number
#' 
#' @doctest
#'
#' @expect type("integer")
#' fib(2)
#'
#' n <- 6 
#' @expect equal(8)
#' fib(n)
#' 
#' @expect warning("not numeric")
#' fib("a")
#'
#' @expect warning("NA")
#' fib(NA)
fib <- function (n) {
  if (! is.numeric(n)) warning("n is not numeric")
  ...
}

Instead of an @examples section, we have a @doctest section.

This will create tests like:

# Generated by doctest: do not edit by hand
# Please edit file in R/<text>

test_that("Doctest: fib", {
  # Created from @doctest for `fib`
  # Source file: <text>
  # Source line: 7
  expect_type(fib(2), "integer")
  n <- 6
  expect_equal(fib(n), 8)
  expect_warning(fib("a"), "not numeric")
  expect_warning(fib(NA), "NA")
})

The .Rd file will be created as normal, with an example section like:

\examples{
fib(2)

n <- 6 
fib(n)
fib("a")
fib(NA)
}

Usage

Install doctest from r-universe:

install.packages("doctest", repos = c("https://hughjonesd.r-universe.dev", 
                                      "https://cloud.r-project.org"))

Or from CRAN:

install.packages("doctest")

Or get the development version:

devtools::install("hughjonesd/doctest")

To use doctest in your package, alter its DESCRIPTION file to add the dt_roclet roclet to roxygen:

Roxygen: list(roclets = c("collate", "rd", "namespace", 
              "doctest::dt_roclet")) 

Then use roxygen2::roxygenize() or devtools::document() to build your package documentation.

For more information, see the package vignette.

  1. https://docs.python.org/3/library/doctest.html, https://doc.rust-lang.org/rustdoc/write-documentation/documentation-tests.html

Copy Link

Version

Install

install.packages('doctest')

Monthly Downloads

369

Version

0.3.0

License

MIT + file LICENSE

Maintainer

David Hugh-Jones

Last Published

January 11th, 2024

Functions in doctest (0.3.0)

expect-tag

Create an expectation
snap-tag

Create a snapshot test
dt_roclet

Create the doctest roclet
testRaw-tag

Add a line of code to the test
test_doctests

Test doctests in a package
doctestExample-tag

Add an example from a file
omit-tag

Exclude example code from a test
expectRaw-tag

Create an expectation as-is
doctest-package

Write testthat tests for your examples, using roxygen tags
doctest-tag

Start a doctest