One function at a time

2020年03月10日

This vignette will teach you how to create a unit test shell for the examples in a single function’s documentation.

Setup

First, let’s set up a dummy package called tempkg with just the detect.R and match.R files from the source code of the stringr package.

usethis::create_package("tempkg", open = FALSE)
fs::file_copy(
 system.file("extdata", c("detect.R", "match.R"), package = "exampletestr"),
 "tempkg/R/"
)

Now let’s move into the tempkg directory:

 setwd("tempkg/")

and set the active project:

usethis::proj_set(".")
#> ✔ Setting active project to '/private/var/folders/l_/2mwm03p55zg7zjykv084hhvr0000gn/T/RtmpPdOSWX/tempkg'

Main event

The detect.R file looks like this (well, I’ve abbreviated it slightly):

 #' Detect the presence or absence of a pattern in a string.
 #'
 #' Vectorised over `string` and `pattern`.
 #'
 #' @param string Input vector. Either a character vector, or something
 #' coercible to one.
 #' @param pattern Pattern to look for.
 #'
 #' @return A logical vector.
 #'
 #' @export
 #' @examples
 #' fruit <- c("apple", "banana", "pear", "pinapple")
 #' str_detect(fruit, "a")
 #' str_detect(fruit, "^a")
 #' str_detect(fruit, "a$")
 #' str_detect(fruit, "b")
 #' str_detect(fruit, "[aeiou]")
str_detect <- function(string, pattern) {
 switch(type(pattern),
 empty = ,
 bound = str_count(string, pattern) > 0,
 fixed = stri_detect_fixed(string, pattern, opts_fixed = opts(pattern)),
 coll = stri_detect_coll(string, pattern, opts_collator = opts(pattern)),
 regex = stri_detect_regex(string, pattern, opts_regex = opts(pattern))
 )
}

We can make the unit tests shell file for the str_match() function using make_test_shell_fun():

 make_test_shell_fun("str_detect", open = FALSE)

This outputs a test-str_detect-examples.R file in the tests/testthat folder with contents

 test_that("`str_detect()` works", {
 fruit <- c("apple", "banana", "pear", "pinapple")
 expect_equal(str_detect(fruit, "a"), )
 expect_equal(str_detect(fruit, "^a"), )
 expect_equal(str_detect(fruit, "a$"), )
 expect_equal(str_detect(fruit, "b"), )
 expect_equal(str_detect(fruit, "[aeiou]"), )
 expect_equal(str_detect("aecfg", letters), )
})

which can be sensibly completed as

 test_that("`str_detect()` works", {
 fruit <- c("apple", "banana", "pear", "pinapple")
 expect_equal(str_detect(fruit, "a"), rep(TRUE, 4))
 expect_equal(str_detect(fruit, "^a"), c(TRUE, rep(FALSE, 3)))
 expect_equal(str_detect(fruit, "a$"), c(FALSE, TRUE, FALSE, FALSE))
 expect_equal(str_detect(fruit, "b"), c(FALSE, TRUE, FALSE, FALSE))
 expect_equal(str_detect(fruit, "[aeiou]"), rep(TRUE, 4))
 expect_equal(
 str_detect("aecfg", letters),
 letters %in% c("a", "c", "e", "f", "g")
 )
})

Roxytest functionality

Alternatively, we can use the roxytest (https://github.com/mikldk/roxytest) package’s @testexamples roxygen tag for testing examples.

 make_test_shell_fun("str_detect", roxytest = TRUE)
#> i Running `roxygen2::roxygenize` . . .
#> Updating roxygen version in /private/var/folders/l_/2mwm03p55zg7zjykv084hhvr0000gn/T/RtmpPdOSWX/tempkg/DESCRIPTION
#> Loading tempkg
#> ✔ Roxygenized :-)
#> @testexamples
#> #' expect_equal(str_detect(fruit, "a"), )
#> #' expect_equal(str_detect(fruit, "^a"), )
#> #' expect_equal(str_detect(fruit, "a$"), )
#> #' expect_equal(str_detect(fruit, "b"), )
#> #' expect_equal(str_detect(fruit, "[aeiou]"), )
#> #' expect_equal(str_detect("aecfg", letters), )
#> [Copied to clipboard]
#> くろまる Paste the block into your roxygen documentation.
#> くろまる Complete the tests in the block.
#> くろまる Run `devtools::document()` to generate the tests in 'tests/'.

RStudio addin for roxytest functionality

This can also be done by highlighting the function name and selecting the RStudio addin Copy roxytest @testexamples to clipboard.

Cleanup

knitr::opts_knit$set(root.dir = tempdir(check = TRUE))
 if (fs::dir_exists("tempkg")) fs::dir_delete("tempkg")
knitr::opts_knit$set(root.dir = init_wd)

AltStyle によって変換されたページ (->オリジナル) /