From 42c7ed057d30f4b0dcf42f91950aca98ab1a44ff Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 5 Aug 2025 11:16:47 -0500 Subject: [PATCH 1/3] Automatically skip missing packages on CRAN Practically, this should mean that you never need to add `skip_if_not_installed()` for suggested packages. It's already the tidyverse style to not do this, but now this works everywhere. Fixes #1585 --- NEWS.md | 1 + R/test-that.R | 5 +++++ tests/testthat/test-test-that.R | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/NEWS.md b/NEWS.md index c7e7e85d9..052a8180e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # testthat (development version) +* On CRAN, `test_that()` will now automatically skip if a package is not installed (#1585). Practically, this means that you no longer need to check that suggested packages are installed. (We don't do this in the tidyverse because we think it has limited payoff, but other styles advise differently.) * Parallel testthat now does not ignore test files with syntax errors (#1360). * `expect_lt()`, `expect_gt()`, and friends have a refined display that is more likely to display the correct number of digits and shows you the actual values compared. * `describe()`, `it()`, and `test_that()` now have a shared stack of descriptions so that if you nest any inside of each other, any resulting failures will show you the full path. diff --git a/R/test-that.R b/R/test-that.R index e51059602..38f751e5f 100644 --- a/R/test-that.R +++ b/R/test-that.R @@ -167,6 +167,11 @@ test_code <- function(code, env, reporter = NULL, skip_on_empty = TRUE) { } }, expectation = handle_expectation, + packageNotFoundError = function(e) { + if (on_cran()) { + skip(paste0(e$package, " is not installed.")) + } + }, skip = handle_skip, warning = handle_warning, message = handle_message, diff --git a/tests/testthat/test-test-that.R b/tests/testthat/test-test-that.R index 8cb482d2c..486d51e72 100644 --- a/tests/testthat/test-test-that.R +++ b/tests/testthat/test-test-that.R @@ -147,3 +147,20 @@ test_that("no braces required in testthat 2e", { NA ) }) + +test_that("missing packages cause a skip on CRAN", { + local_on_cran(TRUE) + + expectations <- capture_expectations(test_that("", { + library(notinstalled) + })) + expect_length(expectations, 1) + expect_s3_class(expectations[[1]], "expectation_skip") + + local_on_cran(FALSE) + expectations <- capture_expectations(test_that("", { + library(notinstalled) + })) + expect_length(expectations, 1) + expect_s3_class(expectations[[1]], "expectation_error") +}) From 9d0bce9b8df23e6ad461342017ad20ccbdb855ab Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 6 Aug 2025 06:44:31 -0500 Subject: [PATCH 2/3] Tweak message --- R/test-that.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/test-that.R b/R/test-that.R index 38f751e5f..d74c30c73 100644 --- a/R/test-that.R +++ b/R/test-that.R @@ -169,7 +169,7 @@ test_code <- function(code, env, reporter = NULL, skip_on_empty = TRUE) { expectation = handle_expectation, packageNotFoundError = function(e) { if (on_cran()) { - skip(paste0(e$package, " is not installed.")) + skip(paste0("{", e$package, "} is not installed.")) } }, skip = handle_skip, From 85642883a2ce087aef5c8c7d3cbdc25af108c0cb Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 6 Aug 2025 06:45:10 -0500 Subject: [PATCH 3/3] Proofread --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4c6e5f7bc..d1bbe46fb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,6 @@ # testthat (development version) -* On CRAN, `test_that()` will now automatically skip if a package is not installed (#1585). Practically, this means that you no longer need to check that suggested packages are installed. (We don't do this in the tidyverse because we think it has limited payoff, but other styles advise differently.) +* On CRAN, `test_that()` now automatically skips if a package is not installed (#1585). Practically, this means that you no longer need to check that suggested packages are installed. (We don't do this in the tidyverse because we think it has limited payoff, but other styles advise differently.) * `expect_snapshot()` no longer skips on CRAN, as that skips the rest of the test. Instead it just returns, neither succeeding nor failing (#1585). * Interrupting a test now prints the test name. This makes it easier to tell where a very slow test might be hanging (#1464) * Parallel testthat now does not ignore test files with syntax errors (#1360).