Skip to content

Commit

Permalink
Add use_test_helper() (#1978)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
olivroy and jennybc authored Jul 26, 2024
1 parent 1128379 commit decf39d
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 3 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export(use_spell_check)
export(use_standalone)
export(use_template)
export(use_test)
export(use_test_helper)
export(use_testthat)
export(use_tibble)
export(use_tidy_coc)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# usethis (development version)

* `use_test_helper()` is a new function to create a test helper file (@olivroy, #1822).

* `use_cpp11()` makes it easier to update `NAMESPACE` (@pachadotdev, #1921).

* `pr_merge_main()` now offers the choice to not open the files with merge conflicts (@olivroy, #1720).
Expand Down
65 changes: 64 additions & 1 deletion R/r.R
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@
#' @param name Either a string giving a file name (without directory) or
#' `NULL` to take the name from the currently open file in RStudio.
#' @inheritParams edit_file
#' @seealso The [testing](https://r-pkgs.org/testing-basics.html) and
#' @seealso
#' * The [testing](https://r-pkgs.org/testing-basics.html) and
#' [R code](https://r-pkgs.org/code.html) chapters of
#' [R Packages](https://r-pkgs.org).
#' * [use_test_helper()] to create a testthat helper file.
#'
#' @export
#'
#' @examples
Expand Down Expand Up @@ -85,6 +88,55 @@ use_test <- function(name = NULL, open = rlang::is_interactive()) {
invisible(TRUE)
}

#' Create or edit a test helper file
#'
#' This function creates (or opens) a test helper file, typically
#' `tests/testthat/helper.R`. Test helper files are executed at the
#' beginning of every automated test run and are also executed by
#' [`load_all()`][pkgload::load_all]. A helper file is a great place to
#' define test helper functions for use throughout your test suite, such as
#' a custom expectation.
#'
#' @param name Can be used to specify the optional "SLUG" in
#' `tests/testthat/helper-SLUG.R`.
#' @inheritParams edit_file
#' @seealso
#' * [use_test()] to create a test file.
#' * The testthat vignette on special files
#' `vignette("special-files", package = "testthat")`.
#' @export
#'
#' @examples
#' \dontrun{
#' use_test_helper()
#' use_test_helper("mocks")
#' }
use_test_helper <- function(name = NULL, open = rlang::is_interactive()) {
maybe_name(name)

if (!uses_testthat()) {
ui_abort(c(
"x" = "Your package must use {.pkg testthat} to use a helper file.",
"_" = "Call {.run usethis::use_testthat()} to set up {.pkg testthat}."
))
}

target_path <- proj_path(
path("tests", "testthat", as_test_helper_file(name))
)

if (!file_exists(target_path)) {
ui_bullets(c(
"i" = "Test helper files are executed at the start of all automated
test runs.",
"i" = "{.run devtools::load_all()} also sources test helper files."
))
}
edit_file(target_path, open = open)

invisible(TRUE)
}

# helpers -----------------------------------------------------------------

compute_name <- function(name = NULL, ext = "R", error_call = caller_env()) {
Expand Down Expand Up @@ -172,3 +224,14 @@ check_file_name <- function(name, call = caller_env()) {
valid_file_name <- function(x) {
grepl("^[a-zA-Z0-9._-]+$", x)
}

as_test_helper_file <- function(name = NULL) {
file <- name %||% "helper.R"
if (!grepl("^helper", file)) {
file <- glue("helper-{file}")
}
if (path_ext(file) == "") {
file <- path_ext_set(file, "R")
}
unclass(file)
}
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ reference:
- use_rmarkdown_template
- use_spell_check
- use_test
- use_test_helper
- use_vignette
- use_addin
- use_citation
Expand Down
5 changes: 4 additions & 1 deletion man/use_r.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions man/use_test_helper.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions tests/testthat/_snaps/r.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# use_test_helper() creates a helper file

Code
use_test_helper(open = FALSE)
Condition
Error in `use_test_helper()`:
x Your package must use testthat to use a helper file.
Call `usethis::use_testthat()` to set up testthat.

---

Code
use_test_helper("foo", open = FALSE)
Message
i Test helper files are executed at the start of all automated test runs.
i `devtools::load_all()` also sources test helper files.
[ ] Edit 'tests/testthat/helper-foo.R'.

# compute_name() errors if no RStudio

Code
Expand Down
31 changes: 30 additions & 1 deletion tests/testthat/test-r.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,28 @@ test_that("use_test() creates a test file", {
expect_proj_file("tests", "testthat", "test-foo.R")
})

test_that("use_test_helper() creates a helper file", {
create_local_package()

expect_snapshot(
error = TRUE,
use_test_helper(open = FALSE)
)
use_testthat()

use_test_helper(open = FALSE)
withr::local_options(list(usethis.quiet = FALSE))
expect_snapshot(
use_test_helper("foo", open = FALSE)
)

expect_proj_file("tests", "testthat", "helper.R")
expect_proj_file("tests", "testthat", "helper-foo.R")
})

test_that("can use use_test() in a project", {
create_local_project()
expect_error(use_test("foofy"), NA)
expect_no_error(use_test("foofy"))
})

# helpers -----------------------------------------------------------------
Expand Down Expand Up @@ -75,3 +94,13 @@ test_that("compute_active_name() standardises name", {
test_that("compute_name() accepts the declared extension", {
expect_equal(compute_name("foo.cpp", ext = "cpp"), "foo.cpp")
})

test_that("as_test_helper_file() works", {
expect_equal(as_test_helper_file(), "helper.R")
expect_equal(as_test_helper_file("helper"), "helper.R")
expect_equal(as_test_helper_file("helper.R"), "helper.R")
expect_equal(as_test_helper_file("stuff"), "helper-stuff.R")
expect_equal(as_test_helper_file("helper-stuff"), "helper-stuff.R")
expect_equal(as_test_helper_file("stuff.R"), "helper-stuff.R")
expect_equal(as_test_helper_file("helper-stuff.R"), "helper-stuff.R")
})

0 comments on commit decf39d

Please sign in to comment.