Skip to content

Commit decf39d

Browse files
olivroyjennybc
andauthored
Add use_test_helper() (#1978)
* save progress * Scrub helper- to enable 3 way jumping easily r/foofy <-> test-foofy <-> helper-foofy * Refine function + add test * Add a section. * Preventively error when calling `use_r()`, `use_test()` if active file is `tests/testthat/helper.R` * Update R/r.R * Update tests/testthat/test-r.R * Update _pkgdown.yml * Make it possible to do `helper-foo.R`; * Tweak NEWS * Tweak docs * Add missing param name * Name this bullet * Document `open` --------- Co-authored-by: Jennifer (Jenny) Bryan <[email protected]>
1 parent 1128379 commit decf39d

File tree

8 files changed

+155
-3
lines changed

8 files changed

+155
-3
lines changed

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export(use_spell_check)
174174
export(use_standalone)
175175
export(use_template)
176176
export(use_test)
177+
export(use_test_helper)
177178
export(use_testthat)
178179
export(use_tibble)
179180
export(use_tidy_coc)

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# usethis (development version)
22

3+
* `use_test_helper()` is a new function to create a test helper file (@olivroy, #1822).
4+
35
* `use_cpp11()` makes it easier to update `NAMESPACE` (@pachadotdev, #1921).
46

57
* `pr_merge_main()` now offers the choice to not open the files with merge conflicts (@olivroy, #1720).

R/r.R

+64-1
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,12 @@
4343
#' @param name Either a string giving a file name (without directory) or
4444
#' `NULL` to take the name from the currently open file in RStudio.
4545
#' @inheritParams edit_file
46-
#' @seealso The [testing](https://r-pkgs.org/testing-basics.html) and
46+
#' @seealso
47+
#' * The [testing](https://r-pkgs.org/testing-basics.html) and
4748
#' [R code](https://r-pkgs.org/code.html) chapters of
4849
#' [R Packages](https://r-pkgs.org).
50+
#' * [use_test_helper()] to create a testthat helper file.
51+
#'
4952
#' @export
5053
#'
5154
#' @examples
@@ -85,6 +88,55 @@ use_test <- function(name = NULL, open = rlang::is_interactive()) {
8588
invisible(TRUE)
8689
}
8790

91+
#' Create or edit a test helper file
92+
#'
93+
#' This function creates (or opens) a test helper file, typically
94+
#' `tests/testthat/helper.R`. Test helper files are executed at the
95+
#' beginning of every automated test run and are also executed by
96+
#' [`load_all()`][pkgload::load_all]. A helper file is a great place to
97+
#' define test helper functions for use throughout your test suite, such as
98+
#' a custom expectation.
99+
#'
100+
#' @param name Can be used to specify the optional "SLUG" in
101+
#' `tests/testthat/helper-SLUG.R`.
102+
#' @inheritParams edit_file
103+
#' @seealso
104+
#' * [use_test()] to create a test file.
105+
#' * The testthat vignette on special files
106+
#' `vignette("special-files", package = "testthat")`.
107+
#' @export
108+
#'
109+
#' @examples
110+
#' \dontrun{
111+
#' use_test_helper()
112+
#' use_test_helper("mocks")
113+
#' }
114+
use_test_helper <- function(name = NULL, open = rlang::is_interactive()) {
115+
maybe_name(name)
116+
117+
if (!uses_testthat()) {
118+
ui_abort(c(
119+
"x" = "Your package must use {.pkg testthat} to use a helper file.",
120+
"_" = "Call {.run usethis::use_testthat()} to set up {.pkg testthat}."
121+
))
122+
}
123+
124+
target_path <- proj_path(
125+
path("tests", "testthat", as_test_helper_file(name))
126+
)
127+
128+
if (!file_exists(target_path)) {
129+
ui_bullets(c(
130+
"i" = "Test helper files are executed at the start of all automated
131+
test runs.",
132+
"i" = "{.run devtools::load_all()} also sources test helper files."
133+
))
134+
}
135+
edit_file(target_path, open = open)
136+
137+
invisible(TRUE)
138+
}
139+
88140
# helpers -----------------------------------------------------------------
89141

90142
compute_name <- function(name = NULL, ext = "R", error_call = caller_env()) {
@@ -172,3 +224,14 @@ check_file_name <- function(name, call = caller_env()) {
172224
valid_file_name <- function(x) {
173225
grepl("^[a-zA-Z0-9._-]+$", x)
174226
}
227+
228+
as_test_helper_file <- function(name = NULL) {
229+
file <- name %||% "helper.R"
230+
if (!grepl("^helper", file)) {
231+
file <- glue("helper-{file}")
232+
}
233+
if (path_ext(file) == "") {
234+
file <- path_ext_set(file, "R")
235+
}
236+
unclass(file)
237+
}

_pkgdown.yml

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ reference:
5858
- use_rmarkdown_template
5959
- use_spell_check
6060
- use_test
61+
- use_test_helper
6162
- use_vignette
6263
- use_addin
6364
- use_citation

man/use_r.Rd

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/use_test_helper.Rd

+35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/r.md

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
# use_test_helper() creates a helper file
2+
3+
Code
4+
use_test_helper(open = FALSE)
5+
Condition
6+
Error in `use_test_helper()`:
7+
x Your package must use testthat to use a helper file.
8+
Call `usethis::use_testthat()` to set up testthat.
9+
10+
---
11+
12+
Code
13+
use_test_helper("foo", open = FALSE)
14+
Message
15+
i Test helper files are executed at the start of all automated test runs.
16+
i `devtools::load_all()` also sources test helper files.
17+
[ ] Edit 'tests/testthat/helper-foo.R'.
18+
119
# compute_name() errors if no RStudio
220

321
Code

tests/testthat/test-r.R

+30-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,28 @@ test_that("use_test() creates a test file", {
1010
expect_proj_file("tests", "testthat", "test-foo.R")
1111
})
1212

13+
test_that("use_test_helper() creates a helper file", {
14+
create_local_package()
15+
16+
expect_snapshot(
17+
error = TRUE,
18+
use_test_helper(open = FALSE)
19+
)
20+
use_testthat()
21+
22+
use_test_helper(open = FALSE)
23+
withr::local_options(list(usethis.quiet = FALSE))
24+
expect_snapshot(
25+
use_test_helper("foo", open = FALSE)
26+
)
27+
28+
expect_proj_file("tests", "testthat", "helper.R")
29+
expect_proj_file("tests", "testthat", "helper-foo.R")
30+
})
31+
1332
test_that("can use use_test() in a project", {
1433
create_local_project()
15-
expect_error(use_test("foofy"), NA)
34+
expect_no_error(use_test("foofy"))
1635
})
1736

1837
# helpers -----------------------------------------------------------------
@@ -75,3 +94,13 @@ test_that("compute_active_name() standardises name", {
7594
test_that("compute_name() accepts the declared extension", {
7695
expect_equal(compute_name("foo.cpp", ext = "cpp"), "foo.cpp")
7796
})
97+
98+
test_that("as_test_helper_file() works", {
99+
expect_equal(as_test_helper_file(), "helper.R")
100+
expect_equal(as_test_helper_file("helper"), "helper.R")
101+
expect_equal(as_test_helper_file("helper.R"), "helper.R")
102+
expect_equal(as_test_helper_file("stuff"), "helper-stuff.R")
103+
expect_equal(as_test_helper_file("helper-stuff"), "helper-stuff.R")
104+
expect_equal(as_test_helper_file("stuff.R"), "helper-stuff.R")
105+
expect_equal(as_test_helper_file("helper-stuff.R"), "helper-stuff.R")
106+
})

0 commit comments

Comments
 (0)