From a29b60bd7711bda330e111b1f653acb2200c7286 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Thu, 7 Nov 2024 12:03:25 -0600 Subject: [PATCH 1/3] Make `package_coverage(quiet = TRUE)` truely quiet --- R/covr.R | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/R/covr.R b/R/covr.R index 7510db65..0755d7db 100644 --- a/R/covr.R +++ b/R/covr.R @@ -458,7 +458,12 @@ package_coverage <- function(path = ".", name <- if (.Platform$OS.type == "windows") "R.exe" else "R" path <- file.path(R.home("bin"), name) - system2(path, args) + system2( + path, + args, + stdout = if (quiet) NULL else "", + stderr = if (quiet) NULL else "" + ) }) ) From e7c7e8903dd2c6fb98adf8c81930abe67c4ec09d Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Thu, 7 Nov 2024 12:09:19 -0600 Subject: [PATCH 2/3] use_testthat(3) --- DESCRIPTION | 3 ++- tests/testthat.R | 20 +++++++++---------- .../tests/testthat/test-TestCompiled.R | 1 - .../tests/testthat/test-TestCompiled.R | 1 - tests/testthat/test-Compiled.R | 1 - tests/testthat/test-R6.R | 2 -- tests/testthat/test-RC.R | 1 - tests/testthat/test-S4.R | 1 - tests/testthat/test-box-R6.R | 2 -- tests/testthat/test-box.R | 2 -- .../test-box_attached_modules_functions-R6.R | 2 -- .../test-box_attached_modules_functions.R | 2 -- tests/testthat/test-braceless.R | 2 -- tests/testthat/test-cobertura.R | 2 -- tests/testthat/test-codecov.R | 1 - tests/testthat/test-corner-cases.R | 2 -- tests/testthat/test-coveralls.R | 2 -- tests/testthat/test-covr.R | 3 --- tests/testthat/test-exclusions.R | 4 ---- tests/testthat/test-file_coverage.R | 1 - tests/testthat/test-functions.R | 1 - tests/testthat/test-gcov.R | 1 - tests/testthat/test-gitlab.R | 2 -- tests/testthat/test-memoised.R | 1 - tests/testthat/test-null.R | 2 -- tests/testthat/test-package_coverage.R | 1 - tests/testthat/test-parallel.R | 3 --- tests/testthat/test-print.R | 1 - tests/testthat/test-record_tests.R | 2 -- tests/testthat/test-report.R | 2 -- tests/testthat/test-sonarqube.R | 2 -- tests/testthat/test-summary.R | 2 -- tests/testthat/test-trace_calls.R | 1 - tests/testthat/test-utils.R | 4 ---- tests/testthat/test-vectorized.R | 1 - 35 files changed, 12 insertions(+), 69 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 35845bed..f87349df 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -61,7 +61,7 @@ Suggests: rmarkdown, htmltools, DT (>= 0.2), - testthat, + testthat (>= 3.0.0), rlang, rstudioapi (>= 0.2), xml2 (>= 1.0.0), @@ -74,3 +74,4 @@ License: MIT + file LICENSE VignetteBuilder: knitr RoxygenNote: 7.2.3 Roxygen: list(markdown = TRUE) +Config/testthat/edition: 3 diff --git a/tests/testthat.R b/tests/testthat.R index 82a14ead..d6da5a81 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,12 +1,12 @@ -ops <- options("crayon.enabled" = FALSE, warn = 1) -library(testthat) -library("covr") +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html -# Skip tests on Solaris as gcc is not in the PATH and I do not have an easy way -# to mimic the CRAN build environment -if (!tolower(Sys.info()[["sysname"]]) == "sunos") { - Sys.setenv("R_TESTS" = "") - test_check("covr") -} +library(testthat) +library(covr) -options(ops) +test_check("covr") diff --git a/tests/testthat/Test+Char/TestCompiled/tests/testthat/test-TestCompiled.R b/tests/testthat/Test+Char/TestCompiled/tests/testthat/test-TestCompiled.R index 02c5aa7a..97af0b62 100644 --- a/tests/testthat/Test+Char/TestCompiled/tests/testthat/test-TestCompiled.R +++ b/tests/testthat/Test+Char/TestCompiled/tests/testthat/test-TestCompiled.R @@ -1,4 +1,3 @@ -context("Test") test_that("compiled function simple works", { expect_equal(simple(1), 1) expect_equal(simple(2), 1) diff --git a/tests/testthat/TestCompiled/tests/testthat/test-TestCompiled.R b/tests/testthat/TestCompiled/tests/testthat/test-TestCompiled.R index 52d468e1..22a098fc 100644 --- a/tests/testthat/TestCompiled/tests/testthat/test-TestCompiled.R +++ b/tests/testthat/TestCompiled/tests/testthat/test-TestCompiled.R @@ -1,4 +1,3 @@ -context("Test") test_that("compiled function simple works", { expect_equal(simple(1), 1) expect_equal(simple(2), 1) diff --git a/tests/testthat/test-Compiled.R b/tests/testthat/test-Compiled.R index a9c3defc..51689de3 100644 --- a/tests/testthat/test-Compiled.R +++ b/tests/testthat/test-Compiled.R @@ -1,4 +1,3 @@ -context("Compiled") test_that("Compiled code coverage is reported including code in headers", { skip_on_cran() skip_if(is_win_r41()) diff --git a/tests/testthat/test-R6.R b/tests/testthat/test-R6.R index 7cce3df8..fee5192d 100644 --- a/tests/testthat/test-R6.R +++ b/tests/testthat/test-R6.R @@ -1,5 +1,3 @@ -context("R6") - test_that("R6 methods coverage is reported", { # There is some sort of bug that causes this test to fail during R CMD check # in R-devel, not sure why, and can't reproduce it interactively diff --git a/tests/testthat/test-RC.R b/tests/testthat/test-RC.R index abfe7194..9e66c99d 100644 --- a/tests/testthat/test-RC.R +++ b/tests/testthat/test-RC.R @@ -1,4 +1,3 @@ -context("RC") test_that("RC methods coverage is reported", { cov <- as.data.frame(package_coverage("TestRC")) diff --git a/tests/testthat/test-S4.R b/tests/testthat/test-S4.R index e019ab7f..44a35f28 100644 --- a/tests/testthat/test-S4.R +++ b/tests/testthat/test-S4.R @@ -1,4 +1,3 @@ -context("S4") test_that("S4 methods coverage is reported", { cov <- as.data.frame(package_coverage("TestS4")) diff --git a/tests/testthat/test-box-R6.R b/tests/testthat/test-box-R6.R index b50b8408..7eebc1c2 100644 --- a/tests/testthat/test-box-R6.R +++ b/tests/testthat/test-box-R6.R @@ -1,5 +1,3 @@ -context("box-R6") - loaded_mods <- loadNamespace("box")$loaded_mods rm(list = ls(loaded_mods), envir = loaded_mods) diff --git a/tests/testthat/test-box.R b/tests/testthat/test-box.R index 9ee174a0..6f3c7a84 100644 --- a/tests/testthat/test-box.R +++ b/tests/testthat/test-box.R @@ -1,5 +1,3 @@ -context("box") - loaded_mods <- loadNamespace("box")$loaded_mods rm(list = ls(loaded_mods), envir = loaded_mods) diff --git a/tests/testthat/test-box_attached_modules_functions-R6.R b/tests/testthat/test-box_attached_modules_functions-R6.R index ba491dc8..96087cfa 100644 --- a/tests/testthat/test-box_attached_modules_functions-R6.R +++ b/tests/testthat/test-box_attached_modules_functions-R6.R @@ -1,5 +1,3 @@ -context("box-attached-modules-functions-R6") - loaded_mods <- loadNamespace("box")$loaded_mods rm(list = ls(loaded_mods), envir = loaded_mods) diff --git a/tests/testthat/test-box_attached_modules_functions.R b/tests/testthat/test-box_attached_modules_functions.R index 06064083..a9970e79 100644 --- a/tests/testthat/test-box_attached_modules_functions.R +++ b/tests/testthat/test-box_attached_modules_functions.R @@ -1,5 +1,3 @@ -context("box-attached-modules-functions") - loaded_mods <- loadNamespace("box")$loaded_mods rm(list = ls(loaded_mods), envir = loaded_mods) diff --git a/tests/testthat/test-braceless.R b/tests/testthat/test-braceless.R index a696c24f..da4edfbe 100644 --- a/tests/testthat/test-braceless.R +++ b/tests/testthat/test-braceless.R @@ -1,5 +1,3 @@ -context("braceless") - test_that("if", { f <- 'f <- function(x) { diff --git a/tests/testthat/test-cobertura.R b/tests/testthat/test-cobertura.R index 0a214656..603c8722 100644 --- a/tests/testthat/test-cobertura.R +++ b/tests/testthat/test-cobertura.R @@ -1,5 +1,3 @@ -context("cobertura_export") - test_that("it works with coverage objects", { tmp <- tempfile() cov <- package_coverage(test_path("TestSummary")) diff --git a/tests/testthat/test-codecov.R b/tests/testthat/test-codecov.R index 9b7493cc..45317142 100644 --- a/tests/testthat/test-codecov.R +++ b/tests/testthat/test-codecov.R @@ -1,4 +1,3 @@ -context("codecov") ci_vars <- c( "APPVEYOR" = NA, "APPVEYOR_ACCOUNT_NAME" = NA, diff --git a/tests/testthat/test-corner-cases.R b/tests/testthat/test-corner-cases.R index 612ae003..b3a4f1af 100644 --- a/tests/testthat/test-corner-cases.R +++ b/tests/testthat/test-corner-cases.R @@ -1,5 +1,3 @@ -context("corner-cases") - test_that("corner-cases are handled as expected", { expect_warning(withr::with_output_sink(tempfile(), { cov <- file_coverage("corner-cases.R", "corner-cases-test.R") diff --git a/tests/testthat/test-coveralls.R b/tests/testthat/test-coveralls.R index cafae047..fd6dd0a1 100644 --- a/tests/testthat/test-coveralls.R +++ b/tests/testthat/test-coveralls.R @@ -1,5 +1,3 @@ -context("coveralls") - ci_vars <- c( "APPVEYOR" = NA, "APPVEYOR_BUILD_NUMBER" = NA, diff --git a/tests/testthat/test-covr.R b/tests/testthat/test-covr.R index 413a9358..cdef7781 100644 --- a/tests/testthat/test-covr.R +++ b/tests/testthat/test-covr.R @@ -1,4 +1,3 @@ -context("function_coverage") test_that("function_coverage", { withr::with_options(c(keep.source = TRUE), { @@ -59,7 +58,6 @@ test_that("duplicated first_line", { }) }) -context("trace_calls") test_that("trace calls handles all possibilities", { expr <- expression(y <- x * 10) @@ -68,7 +66,6 @@ test_that("trace calls handles all possibilities", { expect_equal(trace_calls(list(expr)), list(expr)) }) -context("show_failures") test_that("show_failures shows as much text as it can from the end", { withr::with_options(c(warning.length = 300), { td <- tempfile() diff --git a/tests/testthat/test-exclusions.R b/tests/testthat/test-exclusions.R index 54a93381..b8a1daae 100644 --- a/tests/testthat/test-exclusions.R +++ b/tests/testthat/test-exclusions.R @@ -2,7 +2,6 @@ exclude_ops <- list(exclude_pattern = "#TeSt_NoLiNt", exclude_start = "#TeSt_NoLiNt_StArT", exclude_end = "#TeSt_NoLiNt_EnD") -context("parse_exclusions") test_that("it returns an empty vector if there are no exclusions", { t1 <- c("this", "is", @@ -64,7 +63,6 @@ test_that("it throws an error if start and end are unpaired", { expect_error(do.call(parse_exclusions, c(list(t1), exclude_ops)), "but only") }) -context("normalize_exclusions") expect_equal_vals <- function(x, y) { testthat::expect_equal(unname(x), unname(y)) } @@ -124,7 +122,6 @@ test_that("it handles redundant files", { cov <- package_coverage("TestSummary") -context("exclude") test_that("it excludes lines", { expect_equal(length(cov), 4) expect_equal(length(exclude(cov, list("R/TestSummary.R" = 5), path = "TestSummary")), 3) @@ -149,7 +146,6 @@ test_that("it excludes properly", { expect_equal(length(t1), 0) }) -context("file_exclusions") test_that("it returns NULL if empty or no file exclusions", { expect_equal(file_exclusions(NULL, ""), NULL) diff --git a/tests/testthat/test-file_coverage.R b/tests/testthat/test-file_coverage.R index bfaac667..121ab26c 100644 --- a/tests/testthat/test-file_coverage.R +++ b/tests/testthat/test-file_coverage.R @@ -1,4 +1,3 @@ -context("file_coverage") s1 <- tempfile() t1 <- tempfile() writeLines(con = s1, diff --git a/tests/testthat/test-functions.R b/tests/testthat/test-functions.R index 511e37e8..c537498f 100644 --- a/tests/testthat/test-functions.R +++ b/tests/testthat/test-functions.R @@ -1,4 +1,3 @@ -context("evaluated functions") test_that("function_coverage generates output", { env <- new.env() withr::with_options(c("keep.source" = TRUE), { diff --git a/tests/testthat/test-gcov.R b/tests/testthat/test-gcov.R index a83cfdbd..c3b7dc56 100644 --- a/tests/testthat/test-gcov.R +++ b/tests/testthat/test-gcov.R @@ -1,4 +1,3 @@ -context("gcov") test_that("parse_gcov parses files properly", { mockery::stub(parse_gcov, "file.exists", TRUE) mockery::stub(normalize_path, "normalizePath", "simple.c") diff --git a/tests/testthat/test-gitlab.R b/tests/testthat/test-gitlab.R index 95d0fd64..6bb83921 100644 --- a/tests/testthat/test-gitlab.R +++ b/tests/testthat/test-gitlab.R @@ -1,5 +1,3 @@ -context("gitlab") - test_that("gitlab", { cov <- package_coverage("TestS4") diff --git a/tests/testthat/test-memoised.R b/tests/testthat/test-memoised.R index 2c75d8f5..37b04734 100644 --- a/tests/testthat/test-memoised.R +++ b/tests/testthat/test-memoised.R @@ -1,4 +1,3 @@ -context("memoised") s1 <- tempfile() t1 <- tempfile() writeLines(con = s1, diff --git a/tests/testthat/test-null.R b/tests/testthat/test-null.R index 721a0680..41e3b664 100644 --- a/tests/testthat/test-null.R +++ b/tests/testthat/test-null.R @@ -1,5 +1,3 @@ -context("NULL") - test_that("coverage of functions with NULL constructs", { f1 <- function() NULL f2 <- function() { diff --git a/tests/testthat/test-package_coverage.R b/tests/testthat/test-package_coverage.R index 15836046..6fade55a 100644 --- a/tests/testthat/test-package_coverage.R +++ b/tests/testthat/test-package_coverage.R @@ -1,4 +1,3 @@ -context("package_coverage") test_that("package_coverage returns an error if the path does not exist", { expect_error(package_coverage("blah")) }) diff --git a/tests/testthat/test-parallel.R b/tests/testthat/test-parallel.R index 971a6bb9..64ce2897 100644 --- a/tests/testthat/test-parallel.R +++ b/tests/testthat/test-parallel.R @@ -1,6 +1,3 @@ -context("coverage of parallel code") - - test_that("mcparallel without the fix", { skip_on_os("windows") diff --git a/tests/testthat/test-print.R b/tests/testthat/test-print.R index 5050119f..aeb8c807 100644 --- a/tests/testthat/test-print.R +++ b/tests/testthat/test-print.R @@ -1,4 +1,3 @@ -context("print function") test_that("format_percentage works as expected", { expect_equal(format_percentage(0), crayon::red("0.00%")) diff --git a/tests/testthat/test-record_tests.R b/tests/testthat/test-record_tests.R index 712f4e70..8e0ad1ff 100644 --- a/tests/testthat/test-record_tests.R +++ b/tests/testthat/test-record_tests.R @@ -1,5 +1,3 @@ -context("record_tests") - cov_func <- withr::with_options( list(covr.record_tests = TRUE), package_coverage(test_path("TestFunctional"))) diff --git a/tests/testthat/test-report.R b/tests/testthat/test-report.R index a33ad2fb..05799f19 100644 --- a/tests/testthat/test-report.R +++ b/tests/testthat/test-report.R @@ -1,5 +1,3 @@ -context("report") - skip_on_ci <- function() { if (!identical(Sys.getenv("CI"), "true")) { return(invisible(TRUE)) diff --git a/tests/testthat/test-sonarqube.R b/tests/testthat/test-sonarqube.R index 3204ea07..2bcee65d 100644 --- a/tests/testthat/test-sonarqube.R +++ b/tests/testthat/test-sonarqube.R @@ -1,5 +1,3 @@ -context("sonarqube_export") - test_that("it works with coverage objects", { tmp <- tempfile() cov <- package_coverage(test_path("TestSummary")) diff --git a/tests/testthat/test-summary.R b/tests/testthat/test-summary.R index 9e541bbc..a4aea7c4 100644 --- a/tests/testthat/test-summary.R +++ b/tests/testthat/test-summary.R @@ -1,5 +1,3 @@ -context("summary_functions") - test_that("Summary gives 50% coverage and two lines with zero coverage", { cv <- package_coverage("TestSummary") expect_equal(percent_coverage(cv), 50) diff --git a/tests/testthat/test-trace_calls.R b/tests/testthat/test-trace_calls.R index a31b96d0..e15fd880 100644 --- a/tests/testthat/test-trace_calls.R +++ b/tests/testthat/test-trace_calls.R @@ -1,4 +1,3 @@ -context("trace_calls") test_that("one-line functions are traced correctly", { old <- getOption("keep.source") options(keep.source = TRUE) diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R index f2dc3df5..408cd859 100644 --- a/tests/testthat/test-utils.R +++ b/tests/testthat/test-utils.R @@ -1,4 +1,3 @@ -context("as_package") test_that("it throws error if no package", { expect_error(as_package("arst11234"), "`path` is invalid:.*arst11234") }) @@ -15,21 +14,18 @@ test_that("it returns the package if given the root or child directory", { expect_equal(as_package("TestS4/tests/testthat")$package, "TestS4") }) -context("local_branch") test_that("it works as expected", { with_mock(`covr:::system_output` = function(...) { "test_branch " }, { expect_equal(local_branch("TestSummary"), "test_branch") }) }) -context("current_commit") test_that("it works as expected", { with_mock(`covr:::system_output` = function(...) { " test_hash" }, { expect_equal(current_commit("TestSummary"), "test_hash") }) }) -context("get_source_filename") test_that("it works", { # R 4.0.0 changes this behavior so `getSrcFilename()` will actually return # "test-utils.R" diff --git a/tests/testthat/test-vectorized.R b/tests/testthat/test-vectorized.R index 294720e6..774e0ed0 100644 --- a/tests/testthat/test-vectorized.R +++ b/tests/testthat/test-vectorized.R @@ -1,4 +1,3 @@ -context("Vectorize") s1 = tempfile() t1 = tempfile() writeLines(con = s1, From ad71c360c8ec0a21a1bf54045a0e87bc683becf4 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Thu, 7 Nov 2024 12:19:22 -0600 Subject: [PATCH 3/3] Run tests in parallel --- DESCRIPTION | 1 + tests/testthat/_snaps/Compiled.md | 16 +++++++++++++++ tests/testthat/test-Compiled.R | 29 +++++++++++++++++++++------- tests/testthat/test-tally_coverage.R | 13 ------------- 4 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 tests/testthat/_snaps/Compiled.md delete mode 100644 tests/testthat/test-tally_coverage.R diff --git a/DESCRIPTION b/DESCRIPTION index f87349df..4018a860 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -75,3 +75,4 @@ VignetteBuilder: knitr RoxygenNote: 7.2.3 Roxygen: list(markdown = TRUE) Config/testthat/edition: 3 +Config/testthat/parallel: TRUE diff --git a/tests/testthat/_snaps/Compiled.md b/tests/testthat/_snaps/Compiled.md new file mode 100644 index 00000000..ca5fb739 --- /dev/null +++ b/tests/testthat/_snaps/Compiled.md @@ -0,0 +1,16 @@ +# Error thrown for missing gcov + + Code + package_coverage("TestCompiled", relative_path = TRUE) + Condition + Error in `run_gcov()`: + ! gcov not found + +# Warning thrown for empty gcov output + + Code + . <- package_coverage("TestCompiled", relative_path = TRUE) + Condition + Warning in `run_gcov()`: + parsed gcov output was empty + diff --git a/tests/testthat/test-Compiled.R b/tests/testthat/test-Compiled.R index 51689de3..f93e7b85 100644 --- a/tests/testthat/test-Compiled.R +++ b/tests/testthat/test-Compiled.R @@ -78,16 +78,31 @@ test_that("Compiled code coverage is reported under non-standard char's", { test_that("Error thrown for missing gcov", { skip_on_cran() - withr::with_options(c(covr.gcov=''), - expect_error(package_coverage("TestCompiled", relative_path=TRUE), - "gcov not found") - ) + + withr::local_options(covr.gcov='') + expect_snapshot(package_coverage("TestCompiled", relative_path=TRUE), error = TRUE) }) test_that("Warning thrown for empty gcov output", { skip_on_cran() - withr::with_options(c(covr.gcov_args='-n'), - expect_warning(package_coverage("TestCompiled", relative_path=TRUE), - "parsed gcov output was empty") + + withr::local_options(covr.gcov_args='-n') + expect_snapshot( + . <- package_coverage("TestCompiled", relative_path=TRUE), + transform = function(x) gsub(getwd(), "", x) ) }) + +test_that("tally_coverage includes compiled code", { + skip_on_cran() + skip_if(is_win_r41()) + + cov <- package_coverage(test_path("TestCompiled")) + tall <- tally_coverage(cov) + + expect_named(tall, c("filename", "functions", "line", "value")) + + expect_equal( + unique(tall$filename), + c("R/TestCompiled.R", "src/simple-header.h", "src/simple.cc", "src/simple4.cc")) +}) diff --git a/tests/testthat/test-tally_coverage.R b/tests/testthat/test-tally_coverage.R deleted file mode 100644 index 93173766..00000000 --- a/tests/testthat/test-tally_coverage.R +++ /dev/null @@ -1,13 +0,0 @@ -test_that("tally_coverage includes compiled code", { - skip_on_cran() - skip_if(is_win_r41()) - - cov <- package_coverage(test_path("TestCompiled")) - tall <- tally_coverage(cov) - - expect_named(tall, c("filename", "functions", "line", "value")) - - expect_equal( - unique(tall$filename), - c("R/TestCompiled.R", "src/simple-header.h", "src/simple.cc", "src/simple4.cc")) -})