Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ Suggests:
VignetteBuilder:
knitr
Config/Needs/website: ThinkR-open/thinkrtemplate
Config/testthat/edition: 3
Config/testthat/parallel: true
Config/testthat/start-first: checkhelper, fix-globals*, audit-globals,
check_as_cran, check_clean_userspace*, check_n_covr, audit-userspace
Encoding: UTF-8
Language: en-US
LazyData: true
Expand Down
2 changes: 1 addition & 1 deletion R/globals.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
globalVariables(
utils::globalVariables(
unique(
c(
"is_importfrom", "importfrom_function", "is_global_variable",
Expand Down
37 changes: 19 additions & 18 deletions tests/testthat/helpers.R
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
test_that("Package version required", {

# Check the version of the package roxygen2 to take into account the breaking change.
expect_true(packageVersion("roxygen2") > "7.1.2")
# Silence expected lifecycle deprecations for the current test.
local_quiet_deprecation <- function(envir = parent.frame()) {
withr::local_options(lifecycle_verbosity = "quiet", .local_envir = envir)
}

})
# Discard output and messages for the current test.
# For file-scope fixtures, use `quiet_create_example_pkg()` instead.
local_quiet <- function(envir = parent.frame()) {
if (sink.number(type = "message") == 2L) {
withr::local_message_sink(nullfile(), .local_envir = envir)
}
withr::local_output_sink(nullfile(), .local_envir = envir)
invisible()
}

# Silence lifecycle deprecation warnings globally; tests that explicitly
# exercise the deprecation layer override this with `withr::local_options()`.
options(lifecycle_verbosity = "quiet")
# Create the example package without toolchain output or expected warnings.
quiet_create_example_pkg <- function(...) {
local_quiet(environment())
suppressWarnings(create_example_pkg(...))
}

# Snapshot tempdir() at test entry and unlink anything new at teardown.
# Use this in tests that call rcmdcheck (audit_globals/fix_globals path)
# so they don't leak artefacts that downstream tests
# (test-check_clean_userspace) detect as pre-existing files.
#
# `envir` defaults to the caller's frame, which is the right thing inside
# a `test_that()` block. When called at FILE scope (e.g. before any
# `test_that` runs), pass `envir = testthat::teardown_env()` so the
# deferred cleanup ties to the file's documented teardown environment
# rather than to the source frame's lifetime.
# Remove files added to `tempdir()` when the test or file completes.
local_tempdir_clean <- function(envir = parent.frame()) {
before <- list.files(tempdir(), all.files = TRUE, no.. = TRUE)
withr::defer(
Expand Down
13 changes: 13 additions & 0 deletions tests/testthat/test-asciify-edge-cases.R
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ test_that("asciify_file is byte-equivalent on a no-op pure-ASCII input", {
# ---- return shape: n_tokens populated --------------------------------------

test_that("find_nonascii_files reports a real n_tokens for parseable R files", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(
Expand All @@ -113,6 +114,7 @@ test_that("find_nonascii_files reports a real n_tokens for parseable R files", {
})

test_that("find_nonascii_files sorts its output by file then line", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
# Three files, intentionally created in non-alphabetical order
Expand All @@ -137,6 +139,7 @@ test_that("find_nonascii_files sorts its output by file then line", {
})

test_that("find_nonascii_files survives a NA file.size (e.g. broken symlink)", {
local_quiet_deprecation()
skip_on_os("windows") # symlinks need elevated perms on Windows
withr::with_tempdir({
dir.create("R")
Expand Down Expand Up @@ -213,6 +216,7 @@ test_that("asciify_file on a .Rnw reports a real n_tokens (Sweave routed read-on
# ---- return shape: asciify_pkg returns invisibly ---------------------------

test_that("asciify_pkg() returns its summary invisibly", {
local_quiet_deprecation()
pkg_path <- tempfile(pattern = "asciify-pkg-")
dir.create(pkg_path)
on.exit(unlink(pkg_path, recursive = TRUE), add = TRUE)
Expand All @@ -232,6 +236,7 @@ test_that("asciify_pkg() returns its summary invisibly", {
# ---- interactive feedback: summary message ---------------------------------

test_that("asciify_pkg() emits a 'would change' message in dry_run", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(paste0("x <- \"caf", e, "\""), "R/f.R", useBytes = FALSE)
Expand All @@ -243,6 +248,7 @@ test_that("asciify_pkg() emits a 'would change' message in dry_run", {
})

test_that("asciify_pkg() emits a 'rewrote' message in apply mode", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(paste0("x <- \"caf", e, "\""), "R/f.R", useBytes = FALSE)
Expand All @@ -254,6 +260,7 @@ test_that("asciify_pkg() emits a 'rewrote' message in apply mode", {
})

test_that("asciify_pkg() summary message reports correct counts", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(paste0("x <- \"caf", e, "\""), "R/f1.R", useBytes = FALSE)
Expand All @@ -266,6 +273,7 @@ test_that("asciify_pkg() summary message reports correct counts", {
})

test_that("asciify_pkg() summary counts every non-ASCII character, not parser tokens", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
a <- "\u00e0"; e2 <- "\u00e9"; c2 <- "\u00e7"; e3 <- "\u00e8"
Expand All @@ -281,6 +289,7 @@ test_that("asciify_pkg() summary counts every non-ASCII character, not parser to
})

test_that("asciify_pkg() message is silenceable", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(paste0("x <- \"caf", e, "\""), "R/f.R", useBytes = FALSE)
Expand All @@ -291,6 +300,7 @@ test_that("asciify_pkg() message is silenceable", {
})

test_that("asciify_pkg() hints to re-run with dry_run = FALSE in dry-run with changes", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(paste0("x <- \"caf", e, "\""), "R/f.R", useBytes = FALSE)
Expand All @@ -302,6 +312,7 @@ test_that("asciify_pkg() hints to re-run with dry_run = FALSE in dry-run with ch
})

test_that("asciify_pkg() hints how to inspect the invisible result when there are changes", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(paste0("x <- \"caf", e, "\""), "R/f.R", useBytes = FALSE)
Expand All @@ -313,6 +324,7 @@ test_that("asciify_pkg() hints how to inspect the invisible result when there ar
})

test_that("asciify_pkg() does not show the apply hint when in apply mode", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines(paste0("x <- \"caf", e, "\""), "R/f.R", useBytes = FALSE)
Expand All @@ -322,6 +334,7 @@ test_that("asciify_pkg() does not show the apply hint when in apply mode", {
})

test_that("asciify_pkg() does not show hints when nothing would change", {
local_quiet_deprecation()
withr::with_tempdir({
dir.create("R")
writeLines("x <- 1", "R/f.R", useBytes = FALSE) # ASCII-clean
Expand Down
10 changes: 9 additions & 1 deletion tests/testthat/test-asciify.R
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ test_that("asciify_r_source(identifiers='skip') stays silent and unchanged", {

test_that("asciify_r_source rewrites strings even in a file with a non-ASCII id (warn)", {
src <- "fa\u00e7on <- \"caf\u00e9\""
out <- expect_warning(asciify_r_source(src, identifiers = "warn"))
expect_warning(out <- asciify_r_source(src, identifiers = "warn"))
# the string was escaped
expect_match(out, "\\\\u00e9", fixed = FALSE)
# the identifier stays
Expand Down Expand Up @@ -240,6 +240,8 @@ test_that("asciify_file rewrites only the R chunks of an Rmd, leaving prose alon
# ---- asciify_pkg ------------------------------------------------------------

test_that("asciify_pkg(dry_run = TRUE) reports without writing", {
local_quiet_deprecation()
local_quiet()
pkg_path <- tempfile(pattern = "asciify-pkg-")
dir.create(pkg_path)
on.exit(unlink(pkg_path, recursive = TRUE), add = TRUE)
Expand All @@ -257,6 +259,8 @@ test_that("asciify_pkg(dry_run = TRUE) reports without writing", {
})

test_that("asciify_pkg(dry_run = FALSE) actually rewrites every R file in scope", {
local_quiet_deprecation()
local_quiet()
pkg_path <- tempfile(pattern = "asciify-pkg-")
dir.create(pkg_path)
on.exit(unlink(pkg_path, recursive = TRUE), add = TRUE)
Expand Down Expand Up @@ -288,6 +292,8 @@ test_that("asciify_pkg(dry_run = FALSE) actually rewrites every R file in scope"
})

test_that("asciify_pkg leaves a pure-ASCII file alone", {
local_quiet_deprecation()
local_quiet()
pkg_path <- tempfile(pattern = "asciify-pkg-")
dir.create(pkg_path)
on.exit(unlink(pkg_path, recursive = TRUE), add = TRUE)
Expand All @@ -300,6 +306,7 @@ test_that("asciify_pkg leaves a pure-ASCII file alone", {
# ---- find_nonascii_files ----------------------------------------------------

test_that("find_nonascii_files returns one row per offending line", {
local_quiet_deprecation()
pkg_path <- tempfile(pattern = "asciify-pkg-")
dir.create(pkg_path)
on.exit(unlink(pkg_path, recursive = TRUE), add = TRUE)
Expand All @@ -314,6 +321,7 @@ test_that("find_nonascii_files returns one row per offending line", {
})

test_that("find_nonascii_files returns an empty frame when there is nothing to flag", {
local_quiet_deprecation()
pkg_path <- tempfile(pattern = "asciify-pkg-")
dir.create(pkg_path)
on.exit(unlink(pkg_path, recursive = TRUE), add = TRUE)
Expand Down
15 changes: 9 additions & 6 deletions tests/testthat/test-audit-ascii.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ test_that("audit_ascii() exists with the expected signature", {
})

test_that("audit_ascii() on an ASCII-clean fixture returns an empty data frame", {
path <- suppressWarnings(create_example_pkg())
on.exit(unlink(path, recursive = TRUE))
local_quiet()
path <- quiet_create_example_pkg()
on.exit(unlink(path, recursive = TRUE), add = TRUE)
out <- suppressMessages(audit_ascii(path))
expect_s3_class(out, "data.frame")
expect_equal(nrow(out), 0L)
})

test_that("audit_ascii() flags non-ASCII bytes when present", {
path <- suppressWarnings(create_example_pkg())
on.exit(unlink(path, recursive = TRUE))
local_quiet()
path <- quiet_create_example_pkg()
on.exit(unlink(path, recursive = TRUE), add = TRUE)
writeLines(
"x <- \"café\"",
file.path(path, "R", "nonascii.R")
Expand All @@ -27,7 +29,8 @@ test_that("audit_ascii() flags non-ASCII bytes when present", {
})

test_that("audit_ascii() emits a cli message", {
path <- suppressWarnings(create_example_pkg())
on.exit(unlink(path, recursive = TRUE))
local_quiet()
path <- quiet_create_example_pkg()
on.exit(unlink(path, recursive = TRUE), add = TRUE)
expect_message(audit_ascii(path), regexp = "ASCII|ascii")
})
8 changes: 4 additions & 4 deletions tests/testthat/test-audit-check.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ test_that("audit_check() summarises ERROR/WARNING/NOTE counts and returns the rc
)
testthat::local_mocked_bindings(.check_as_cran = function(...) fake)

out <- expect_message(
audit_check("."),
expect_message(
out <- audit_check("."),
regexp = "1 ERROR.*2 WARNING.*3 NOTE"
)
expect_identical(out, fake)
Expand All @@ -26,8 +26,8 @@ test_that("audit_check() handles the all-clean case (0/0/0) without choking on p
fake <- list(errors = character(), warnings = character(), notes = character())
testthat::local_mocked_bindings(.check_as_cran = function(...) fake)

out <- expect_message(
audit_check("."),
expect_message(
out <- audit_check("."),
regexp = "0 ERRORs.*0 WARNINGs.*0 NOTEs"
)
expect_identical(out, fake)
Expand Down
8 changes: 8 additions & 0 deletions tests/testthat/test-audit-citation.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ local_pkg_with_citation <- function(content, envir = parent.frame()) {
}

test_that("audit_citation() flags personList(), as.personList() and citEntry()", {
local_quiet()
pkg <- local_pkg_with_citation(c(
'citEntry(',
' entry = "Manual",',
Expand Down Expand Up @@ -47,6 +48,7 @@ test_that("audit_citation() flags personList(), as.personList() and citEntry()",
})

test_that("audit_citation() flags as.personList() too", {
local_quiet()
pkg <- local_pkg_with_citation(c(
'bibentry(',
' bibtype = "Manual",',
Expand All @@ -62,6 +64,7 @@ test_that("audit_citation() flags as.personList() too", {
})

test_that("audit_citation() returns an empty tibble when CITATION is modern", {
local_quiet()
pkg <- local_pkg_with_citation(c(
'bibentry(',
' bibtype = "Manual",',
Expand All @@ -80,6 +83,7 @@ test_that("audit_citation() returns an empty tibble when CITATION is modern", {
})

test_that("audit_citation() handles a missing inst/CITATION gracefully", {
local_quiet()
pkg <- tempfile("pkg-no-cit-")
dir.create(pkg)
on.exit(unlink(pkg, recursive = TRUE), add = TRUE)
Expand All @@ -90,11 +94,13 @@ test_that("audit_citation() handles a missing inst/CITATION gracefully", {
})

test_that("audit_citation() emits a cli summary message", {
local_quiet()
pkg <- local_pkg_with_citation('citEntry(entry = "Manual")')
expect_message(audit_citation(pkg), regexp = "audit_citation")
})

test_that("audit_citation() reports correct line numbers for nested calls", {
local_quiet()
pkg <- local_pkg_with_citation(c(
'# header comment',
'citHeader("My pkg")',
Expand Down Expand Up @@ -127,6 +133,7 @@ local_pkg_with_citation <- function(citation, envir = parent.frame()) {
}

test_that("audit_citation() warns and returns empty on a syntactically broken CITATION", {
local_quiet()
pkg <- local_pkg_with_citation(c(
'citEntry(entry = "Manual",',
' title = "no closing paren ever'
Expand All @@ -140,6 +147,7 @@ test_that("audit_citation() warns and returns empty on a syntactically broken CI
})

test_that("audit_citation() returns empty on an empty CITATION", {
local_quiet()
pkg <- local_pkg_with_citation(character(0))

out <- audit_citation(pkg)
Expand Down
6 changes: 3 additions & 3 deletions tests/testthat/test-audit-dataset-doc.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ test_that("audit_dataset_doc() returns an empty tibble when data/ does not exist
dir.create(path)
dir.create(file.path(path, "R"))
writeLines("Package: foo", file.path(path, "DESCRIPTION"))
on.exit(unlink(path, recursive = TRUE))
on.exit(unlink(path, recursive = TRUE), add = TRUE)
out <- suppressMessages(audit_dataset_doc(path))
expect_s3_class(out, "data.frame")
expect_equal(nrow(out), 0L)
Expand All @@ -23,7 +23,7 @@ test_that("audit_dataset_doc() reports datasets present in data/", {
writeLines("Package: foo", file.path(path, "DESCRIPTION"))
iris_path <- file.path(path, "data", "iris.rda")
save(iris, file = iris_path)
on.exit(unlink(path, recursive = TRUE))
on.exit(unlink(path, recursive = TRUE), add = TRUE)
out <- suppressMessages(audit_dataset_doc(path))
expect_equal(nrow(out), 1L)
expect_equal(out$name, "iris")
Expand All @@ -35,7 +35,7 @@ test_that("audit_dataset_doc() emits a cli message", {
dir.create(path)
dir.create(file.path(path, "R"))
writeLines("Package: foo", file.path(path, "DESCRIPTION"))
on.exit(unlink(path, recursive = TRUE))
on.exit(unlink(path, recursive = TRUE), add = TRUE)
expect_message(audit_dataset_doc(path), regexp = "dataset")
})

Expand Down
Loading