diff --git a/DESCRIPTION b/DESCRIPTION index 4e82bae86..88e69180b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: testthat Title: Unit Testing for R -Version: 3.1.6.9000 +Version: 3.1.6.9001 Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")), diff --git a/R/test-files.R b/R/test-files.R index 83834c980..fb133fc52 100644 --- a/R/test-files.R +++ b/R/test-files.R @@ -49,6 +49,7 @@ #' @param stop_on_failure If `TRUE`, throw an error if any tests fail. #' @param stop_on_warning If `TRUE`, throw an error if any tests generate #' warnings. +#' @param recursive If `TRUE` Test that will search for test files in the nested directories. #' @param load_package Strategy to use for load package code: #' * "none", the default, doesn't load the package. #' * "installed", uses [library()] to load an installed package. @@ -75,6 +76,7 @@ test_dir <- function(path, stop_on_warning = FALSE, wrap = lifecycle::deprecated(), package = NULL, + recursive = FALSE, load_package = c("none", "installed", "source") ) { @@ -86,7 +88,8 @@ test_dir <- function(path, filter = filter, ..., full.names = FALSE, - start_first = start_first + start_first = start_first, + recursive = recursive ) if (length(test_paths) == 0) { abort("No test files found") @@ -370,8 +373,8 @@ local_teardown_env <- function(env = parent.frame()) { #' @return A character vector of paths #' @keywords internal #' @export -find_test_scripts <- function(path, filter = NULL, invert = FALSE, ..., full.names = TRUE, start_first = NULL) { - files <- dir(path, "^test.*\\.[rR]$", full.names = full.names) +find_test_scripts <- function(path, filter = NULL, invert = FALSE, ..., full.names = TRUE, start_first = NULL, recursive = FALSE) { + files <- dir(path, "^test.*\\.[rR]$", full.names = full.names, recursive = recursive) files <- filter_test_scripts(files, filter, invert, ...) order_test_scripts(files, start_first) } diff --git a/man/find_test_scripts.Rd b/man/find_test_scripts.Rd index 0e5dfc618..007999518 100644 --- a/man/find_test_scripts.Rd +++ b/man/find_test_scripts.Rd @@ -10,7 +10,8 @@ find_test_scripts( invert = FALSE, ..., full.names = TRUE, - start_first = NULL + start_first = NULL, + recursive = FALSE ) } \arguments{ @@ -31,6 +32,8 @@ first pattern first, then the ones matching the second, etc. and then the rest of the files, alphabetically. Parallel tests tend to finish quicker if you start the slowest files first. \code{NULL} means alphabetical order.} + +\item{recursive}{If \code{TRUE} Test that will search for test files in the nested directories.} } \value{ A character vector of paths diff --git a/man/test_dir.Rd b/man/test_dir.Rd index 5e76f2c7b..4c817d7d0 100644 --- a/man/test_dir.Rd +++ b/man/test_dir.Rd @@ -15,6 +15,7 @@ test_dir( stop_on_warning = FALSE, wrap = lifecycle::deprecated(), package = NULL, + recursive = FALSE, load_package = c("none", "installed", "source") ) } @@ -47,6 +48,8 @@ warnings.} \item{package}{If these tests belong to a package, the name of the package.} +\item{recursive}{If \code{TRUE} Test that will search for test files in the nested directories.} + \item{load_package}{Strategy to use for load package code: \itemize{ \item "none", the default, doesn't load the package. diff --git a/tests/testthat/_snaps/test-files.md b/tests/testthat/_snaps/test-files.md index 13e011d73..9958864d6 100644 --- a/tests/testthat/_snaps/test-files.md +++ b/tests/testthat/_snaps/test-files.md @@ -19,3 +19,24 @@ 16 test-helper.R helper test 1 0 FALSE FALSE 0 1 17 test-skip.R Skips skip 1 0 TRUE FALSE 0 0 +# runs all tests in nested directories and records output + + file context test nb failed skipped error warning passed + 1 nested_folder/test-errors.R simple 0 0 FALSE TRUE 0 0 + 2 nested_folder/test-errors.R after one success 1 0 FALSE TRUE 0 1 + 3 nested_folder/test-errors.R after one failure 1 1 FALSE TRUE 0 0 + 4 nested_folder/test-errors.R in the test 0 0 FALSE TRUE 0 0 + 5 nested_folder/test-errors.R in expect_error 1 0 FALSE FALSE 0 1 + 6 nested_folder/test-failures.R just one failure 1 1 FALSE FALSE 0 0 + 7 nested_folder/test-failures.R one failure on two 2 1 FALSE FALSE 0 1 + 8 nested_folder/test-failures.R no failure 2 0 FALSE FALSE 0 2 + 9 nested_folder/test-skip.R Skips skip 1 0 TRUE FALSE 0 0 + 10 test-basic.R logical tests act as expected 2 0 FALSE FALSE 0 2 + 11 test-basic.R logical tests ignore attributes 2 0 FALSE FALSE 0 2 + 12 test-basic.R equality holds 2 0 FALSE FALSE 0 2 + 13 test-basic.R can't access variables from other tests 2 1 0 TRUE FALSE 0 0 + 14 test-basic.R can't access variables from other tests 1 1 0 FALSE FALSE 0 1 + 15 test-empty.R empty test 1 0 TRUE FALSE 0 0 + 16 test-empty.R empty test with error 0 0 FALSE TRUE 0 0 + 17 test-helper.R helper test 1 0 FALSE FALSE 0 1 + diff --git a/tests/testthat/test-test-files.R b/tests/testthat/test-test-files.R index a86e4061a..4ee3dcca7 100644 --- a/tests/testthat/test-test-files.R +++ b/tests/testthat/test-test-files.R @@ -46,6 +46,17 @@ test_that("can control if warnings errors", { expect_error(test_warning(stop_on_warning = FALSE), NA) }) +test_that("runs all tests in nested directories and records output", { + withr::local_envvar(TESTTHAT_PARALLEL = "FALSE") + res <- test_dir(test_path("test_dir_recursive"), reporter = "silent", stop_on_failure = FALSE, recursive = TRUE) + df <- as.data.frame(res) + df$user <- df$system <- df$real <- df$result <- NULL + + local_reproducible_output(width = 200) + local_edition(3) + expect_snapshot_output(print(df)) +}) + # test_file --------------------------------------------------------------- test_that("can test single file", { diff --git a/tests/testthat/test_dir_recursive/helper_hello.R b/tests/testthat/test_dir_recursive/helper_hello.R new file mode 100644 index 000000000..dd96afc4c --- /dev/null +++ b/tests/testthat/test_dir_recursive/helper_hello.R @@ -0,0 +1 @@ +hello <- function() "Hello World" diff --git a/tests/testthat/test_dir_recursive/nested_folder/test-errors.R b/tests/testthat/test_dir_recursive/nested_folder/test-errors.R new file mode 100644 index 000000000..fdeb9d564 --- /dev/null +++ b/tests/testthat/test_dir_recursive/nested_folder/test-errors.R @@ -0,0 +1,22 @@ +test_that("simple", { + stop("argh") +}) + +test_that("after one success", { + expect_true(TRUE) + stop("argh") + expect_true(TRUE) +}) + +test_that("after one failure", { + expect_true(FALSE) + stop("argh") +}) + +test_that("in the test", { + expect_true(stop("Argh")) +}) + +test_that("in expect_error", { + expect_error(stop("Argh")) +}) diff --git a/tests/testthat/test_dir_recursive/nested_folder/test-failures.R b/tests/testthat/test_dir_recursive/nested_folder/test-failures.R new file mode 100644 index 000000000..21204f22f --- /dev/null +++ b/tests/testthat/test_dir_recursive/nested_folder/test-failures.R @@ -0,0 +1,13 @@ +test_that("just one failure", { + expect_true(FALSE) +}) + +test_that("one failure on two", { + expect_false(FALSE) + expect_true(FALSE) +}) + +test_that("no failure", { + expect_false(FALSE) + expect_true(TRUE) +}) diff --git a/tests/testthat/test_dir_recursive/nested_folder/test-skip.R b/tests/testthat/test_dir_recursive/nested_folder/test-skip.R new file mode 100644 index 000000000..5796fa6f1 --- /dev/null +++ b/tests/testthat/test_dir_recursive/nested_folder/test-skip.R @@ -0,0 +1,4 @@ +test_that("Skips skip", { + skip("Skipping to avoid certain failure") + expect_true(FALSE) +}) diff --git a/tests/testthat/test_dir_recursive/test-bare-expectations.R b/tests/testthat/test_dir_recursive/test-bare-expectations.R new file mode 100644 index 000000000..cd99df26e --- /dev/null +++ b/tests/testthat/test_dir_recursive/test-bare-expectations.R @@ -0,0 +1 @@ +expect_equal(2, 2) diff --git a/tests/testthat/test_dir_recursive/test-basic.R b/tests/testthat/test_dir_recursive/test-basic.R new file mode 100644 index 000000000..9baa743e6 --- /dev/null +++ b/tests/testthat/test_dir_recursive/test-basic.R @@ -0,0 +1,22 @@ +test_that("logical tests act as expected", { + expect_true(TRUE) + expect_false(FALSE) +}) + +test_that("logical tests ignore attributes", { + expect_true(c(a = TRUE)) + expect_false(c(a = FALSE)) +}) + +test_that("equality holds", { + expect_equal(5, 5) + expect_identical(10, 10) +}) + +test_that("can't access variables from other tests 2", { + a <- 10 +}) + +test_that("can't access variables from other tests 1", { + expect_false(exists("a")) +}) diff --git a/tests/testthat/test_dir_recursive/test-empty.R b/tests/testthat/test_dir_recursive/test-empty.R new file mode 100644 index 000000000..f31a703e4 --- /dev/null +++ b/tests/testthat/test_dir_recursive/test-empty.R @@ -0,0 +1,3 @@ +test_that("empty test", NULL) + +test_that("empty test with error", stop("Argh")) diff --git a/tests/testthat/test_dir_recursive/test-helper.R b/tests/testthat/test_dir_recursive/test-helper.R new file mode 100644 index 000000000..26da9303f --- /dev/null +++ b/tests/testthat/test_dir_recursive/test-helper.R @@ -0,0 +1,4 @@ +# test that the companion helper script is sourced by test_dir +test_that("helper test", { + expect_equal(hello(), "Hello World") +})