Introduction

library(roxytest)

There are a number of roclets included:

  • testthat_roclet: Write testthat tests in the roxygen2 documentation
    • @tests: Generate test skeletons
    • @testexamples: Generate test skeletons with @examples included first such that e.g. variables can be reused
  • tinytest_roclet: Write tinytest tests in the roxygen2 documentation
    • @tests: Generate test skeletons
    • @testexamples: Generate test skeletons with @examples included first such that e.g. variables can be reused
  • param_roclet: Checks for consistency in documentation of parameters (too many/too few)
  • return_roclet: Checks if @exported functions has @return documentation (possibly just @return None)
  • examples_roclet: Checks if @exported functions has @examples documentation

To use the package in your own package you do not need to add any additional dependencies in your package’s DESCRIPTION file apart from the usual Suggests: testthat that is required for testing with testthat or the Suggests: tinytest that is required for testing with tinytest. (If you only use param_roclet, return_roclet or examples_roclet you do not need to add anything to Suggests.)

Suggests:
  testthat # or tinytest

However, any developer working on your package needs to have roxytest installed to be able to successfully run roxygen2::roxygenise() (or devtools::document()). For this reason you may consider adding roxytest to Suggests, but this is not required.

testthat roclet

Add the following lines to your package’s DESCRIPTION file (along with Suggests: testthat):

Roxygen: list(roclets = c("namespace", "rd", "roxytest::testthat_roclet"))

(Or make appropriate changes to obtain similar results.)

Then run the following:

roxygen2::roxygenise()

Similarly for the other roclets.

Multiple roclets

You can of course also add multiple, e.g.:

Roxygen: list(roclets = c("namespace", "rd", 
                          "roxytest::testthat_roclet",
                          "roxytest::param_roclet",
                          "roxytest::return_roclet"))

(Or make appropriate changes to obtain similar results.)

Then run the following:

roxygen2::roxygenise()

Examples

Below we show based on testthat, but it is the same for tinytest except the output which then happens at inst/tinytest without contest() and testthat() boilerplate.

testthat roclet

As mentioned above, there are two tags available:

  • @tests: Generate test skeletons
  • @testexamples: Generate test skeletons with @examples included first such that e.g. variables can be reused

Note that both can be used at the same time.

We first demonstrate @tests and afterwards @testexamples.

@tests tag

For example, if the file R/functions.R contains this code (from roxytestdemo):

#' A function to do x
#' 
#' @param x A number
#' 
#' @tests 
#' expect_equal(foo(2), sqrt(2))
#' expect_error(foo("a string"))
#' 
#' @return something
foo <- function(x) {
  return(sqrt(x))
}

#' A function to do y
#' 
#' @param x Character vector
#' @param y Character vector
#' 
#' @tests 
#' expect_equal(bar("A", "B"), paste("A", "B", sep = "/"))
#' 
#' @export
bar <- function(x, y) {
  paste0(x, "/", y)
}

Then roxygen2::roxygenise() will generate (with the testthat_roclet roclet) the file tests/testthat/test-roxytest-tests-functions.R with this content:

# Generated by roxytest: Do not edit by hand!

context("File R/functions.R: @tests")

test_that("Function foo() @ L10", {
  expect_equal(foo(2), sqrt(2))
  expect_error(foo("a string"))
})


test_that("Function bar() @ L23", {
  expect_equal(bar("A", "B"), paste("A", "B", sep = "/"))
})

@testexamples tag

For example, if the file R/functions.R contains this code (from roxytestdemo):

#' A function to do w
#' 
#' @param x A number
#' 
#' @examples 
#' x <- 2
#' foo(x)
#' 
#' @testexamples
#' expect_equal(foo(x), foo(2))
#' 
#' @return something
foo2 <- function(x) {
  return(sqrt(x))
}

Then roxygen2::roxygenise() will generate (with the testthat_roclet roclet) the file tests/testthat/test-roxytest-testexamples-functions.R with this content:

# Generated by roxytest: Do not edit by hand!

context("File R/functions.R: @testexamples")

test_that("Function foo2() @ L13", {
  
  x <- 2
  foo(x)
  
  expect_equal(foo(x), foo(2))
})

Note that:

  • \dontrun: Everything including content is removed
  • \donttest: Only the tag itself is removed
  • \dontshow: Only the tag itself is removed

param roclet

To demonstrate the param_roclet roclet assume that this block of documentation exists:

#' Summing two numbers
#'
#' @param x A number
foobar <- function(x, y) {
  x + y
}

When the package is documented, the following output will be displayed:

Functions with @param inconsistency:
  * Function 'foobar' with title 'Summing two numbers': 
    - Missing @param's: y

Similarly if there are too many documented arguments.

return roclet

To demonstrate the return_roclet roclet assume that this block of documentation exists:

#' Summing two numbers
#'
#' @param x A number
#' 
#' @export
foobar2 <- function(x, y) {
  x + y
}

When the package is documented, the following output will be displayed:

Functions with @export but no @return:
  * Function 'foobar2()' with title 'Summing two numbers'

examples roclet

To demonstrate the examples_roclet roclet assume that this block of documentation exists:

#' Summing two numbers
#'
#' @param x A number
#' 
#' @export
foobar2 <- function(x, y) {
  x + y
}

When the package is documented, the following output will be displayed:

Functions with @export but no @example(s):
  * Function 'foobar2()' with title 'Summing two numbers'