--- title: "One function at a time" date: "2020-03-10" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{One function at a time} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- 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. ```r 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: ```r setwd("tempkg/") ``` and set the active project: ```r 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): ```r #' 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()`: ```r make_test_shell_fun("str_detect", open = FALSE) ``` This outputs a `test-str_detect-examples.R` file in the `tests/testthat` folder with contents ```r 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 ```r 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. ```r make_test_shell_fun("str_detect", roxytest = TRUE) ``` ``` #> ℹ 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 ```r knitr::opts_knit$set(root.dir = tempdir(check = TRUE)) ``` ```r if (fs::dir_exists("tempkg")) fs::dir_delete("tempkg") knitr::opts_knit$set(root.dir = init_wd) ```