Nothing
# Helper: minimal mapping DF used by downstream steps
make_mapping <- function() {
data.frame(
source_file = c("a.R", "b.R"),
test_file = c("test-a.R", NA_character_), # one with a test, one without
evidence = c("filename_match", NA_character_),
has_tests = c(TRUE, FALSE),
stringsAsFactors = FALSE
)
}
test_that("diagnostic: coverage block functions are invoked (covr + reducer)", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
test_pkg_data <- list(bioc_run_ut_path = NA_character_)
# Same setup as above (mapping, normalize, prepare, etc.)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths",
mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = FALSE) x)
mapping <- data.frame(
source_file = "a.R", test_file = "test-a.R", evidence = "filename_match",
has_tests = TRUE, stringsAsFactors = FALSE
)
mockery::stub(fn, "get_source_test_mapping_runit_nstf", mockery::mock(mapping))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf", mockery::mock(data.frame(test_file = NA_character_, issue_type = "No tests skipped", stringsAsFactors = FALSE)))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(fn = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env(), cycle = TRUE))
mockery::stub(fn, "assign", mockery::mock(NULL, cycle = TRUE))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
# Must stub library() or you’ll abort here!
mockery::stub(fn, "detach_pkg_if_attached", mockery::mock(TRUE))
mockery::stub(fn, "pkgload::load_all", mockery::mock(invisible(NULL)))
mockery::stub(fn, "library", mockery::mock(NULL))
mockery::stub(fn, "tempfile", mockery::mock("/tmp/runner.R", cycle = TRUE))
mockery::stub(fn, "writeLines", mockery::mock(NULL, cycle = TRUE))
# avoid error from as.environment("package:mypkg")
mockery::stub(fn, "as.environment", function(name) {
# when calling as.environment("package:mypkg"), return a fresh env
if (identical(name, paste0("package:", pkg_name))) return(new.env(parent = emptyenv()))
# delegate other calls to base (rare here)
base::as.environment(name)
})
# Spy/record calls to covr & reducer
spy_env_cov <- mockery::mock(structure(list(), class = "covr_coverage"))
spy_cov_to_list <- mockery::mock(list(totalcoverage = 75.0))
spy_compute <- mockery::mock(list(
total_cov = 0.50, percent_cov = 75.0,
n_testfiles = 1L, n_no_function_tests = 1L, n_skipped_files = 0L
))
# Return > 0 so we skip package_coverage fallback (which would need readLines/real path)
mockery::stub(fn, "covr::percent_coverage", mockery::mock(75.0))
# Bypass build_runit_custom_runner to avoid normalizePath(mustWork=TRUE) on fake path
mock_runner_path <- tempfile(fileext = ".R")
writeLines(c("library(mypkg)", "1 + 1"), mock_runner_path)
mockery::stub(fn, "build_runit_custom_runner", mockery::mock(mock_runner_path))
mockery::stub(fn, "covr::environment_coverage", spy_env_cov)
mockery::stub(fn, "covr::coverage_to_list", spy_cov_to_list)
mockery::stub(fn, "compute_total_coverage", spy_compute)
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
expect_identical(res$total_cov, 0.50)
expect_identical(res$res_cov$coverage$totalcoverage, 75.0)
})
test_that("messages when package is not using RUnit layout and returns default coverage when covr fails", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
# --- Stubs for early steps ---
mock_get_pkg_name <- mockery::mock(pkg_name)
mock_is_layout <- mockery::mock(FALSE) # trigger layout message
mock_get_paths <- mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests")))
mock_normalize <- mockery::mock(function(x, winslash = "/", mustWork = FALSE) x, cycle = TRUE)
# --- Mapping: succeed to progress into coverage path ---
mock_get_mapping <- mockery::mock(make_mapping())
# --- Cleaning branch: only run when bioc_run_ut_path is not NA ---
# In this test, set bioc_run_ut_path = NA so the cleaning branch is skipped
test_pkg_data <- list(bioc_run_ut_path = NA_character_)
# --- prepare_for_bioc_runit: succeed ---
mock_prepare <- mockery::mock(TRUE)
# --- Problems: return "No tests skipped" (default/no skip) ---
mock_problems <- mockery::mock(data.frame(
test_file = NA_character_,
issue_type = "No tests skipped",
stringsAsFactors = FALSE
))
# --- Post-load mapping: functions with no tests ---
mock_no_tests <- mockery::mock(data.frame(
`function` = "b",
stringsAsFactors = FALSE
))
# --- tidyr::drop_na: identity (no change) ---
mock_drop_na <- function(df) df
# --- Env preparation (assign exported/internal objects + datasets) ---
mock_ls <- mockery::mock(c("obj1", "obj2"))
mock_asNamespace <- mockery::mock(new.env())
mock_assign <- mockery::mock(NULL)
mock_load_datasets <- mockery::mock(c("ds1", "ds2"))
mock_message <- mockery::mock(NULL, cycle = TRUE)
# --- Coverage block stubs: force an error in covr to take default path ---
mock_loadedNamespaces <- mockery::mock(c("base", "stats", "utils", "methods")) # so loadNamespace("methods") skipped
mock_loadNamespace <- mockery::mock(NULL)
mock_detach <- mockery::mock(TRUE)
mock_library <- mockery::mock(NULL)
mock_tempfile <- mockery::mock("/tmp/runner.R")
mock_writeLines <- mockery::mock(NULL)
# This triggers the error branch -> default coverage result
mock_env_cov <- function(env, test_files) stop("instrumentation failed")
# coverage_to_list is never reached when env_cov errors, but stub for safety
mock_cov_to_list <- mockery::mock(list(filecoverage = matrix(0, nrow = 1), totalcoverage = 0))
# --- cleanup_and_return_null used by error branches ---
mock_cleanup <- mockery::mock(NULL)
# Wire stubs
mockery::stub(fn, "get_pkg_name", mock_get_pkg_name)
mockery::stub(fn, "is_runit_layout", mock_is_layout)
mockery::stub(fn, "get_runit_test_paths",mock_get_paths)
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "get_source_test_mapping_runit_nstf", mock_get_mapping)
mockery::stub(fn, "prepare_for_bioc_runit", mock_prepare)
mockery::stub(fn, "check_covr_skip_runit_nstf", mock_problems)
mockery::stub(fn, "get_function_no_tests", mock_no_tests)
mockery::stub(fn, "tidyr::drop_na", mock_drop_na)
mockery::stub(fn, "ls", mock_ls)
mockery::stub(fn, "asNamespace", mock_asNamespace)
mockery::stub(fn, "assign", mock_assign)
mockery::stub(fn, "load_package_datasets", mock_load_datasets)
mockery::stub(fn, "message", mock_message)
mockery::stub(fn, "loadedNamespaces", mock_loadedNamespaces)
mockery::stub(fn, "loadNamespace", mock_loadNamespace)
mockery::stub(fn, "detach_pkg_if_attached", mock_detach)
mockery::stub(fn, "library", mock_library)
mockery::stub(fn, "tempfile", mock_tempfile)
mockery::stub(fn, "writeLines", mock_writeLines)
mockery::stub(fn, "covr::environment_coverage", mock_env_cov)
mockery::stub(fn, "covr::coverage_to_list", mock_cov_to_list)
mockery::stub(fn, "cleanup_and_return_null", mock_cleanup)
suppressWarnings(res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data))
# Assertions: default coverage path
expect_type(res, "list")
expect_true("res_cov" %in% names(res))
expect_true(is.list(res$res_cov))
expect_identical(res$total_cov, 0)
expect_identical(res$res_cov$name, pkg_name)
expect_true(is.list(res$res_cov$coverage))
expect_identical(res$res_cov$coverage$totalcoverage, 0)
expect_identical(res$res_cov$errors, "No RUnit or BiocGenerics configuration")
# The first message should hint about RUnit layout
msgs <- mockery::mock_args(mock_message)
# Flatten first invocation into a single string to check substring
first_msg <- paste0(msgs[[1]], collapse = "")
expect_match(first_msg, "RUnit layout")
})
test_that("returns NULL when source-test mapping errors", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
test_pkg_data <- list(bioc_run_ut_path = NA_character_)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths", mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", mockery::mock(function(x, winslash = "/", mustWork = FALSE) x, cycle = TRUE))
# Mapping: throw error so tryCatch invokes cleanup_and_return_null -> returns NULL -> early exit
mockery::stub(fn, "get_source_test_mapping_runit_nstf", function(...) stop("boom-mapping"))
mockery::stub(fn, "cleanup_and_return_null", mockery::mock(NULL))
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
expect_null(res)
})
test_that("returns NULL when prepare_for_bioc_runit fails", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
test_pkg_data <- list(bioc_run_ut_path = NA_character_)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths", mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", mockery::mock(function(x, winslash = "/", mustWork = FALSE) x, cycle = TRUE))
mockery::stub(fn, "get_source_test_mapping_runit_nstf", mockery::mock(make_mapping()))
# Force prepare to error; tryCatch should call cleanup_and_return_null and return NULL
mockery::stub(fn, "prepare_for_bioc_runit", function(...) stop("prep-error"))
mockery::stub(fn, "cleanup_and_return_null", mockery::mock(NULL))
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
expect_null(res)
})
test_that("coverage error path yields a default covr_list even when mapping & problems succeed", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
test_pkg_data <- list(bioc_run_ut_path = NA_character_) # skip cleaning branch
# Layout ok
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
# Paths, normalization
mockery::stub(fn, "get_runit_test_paths", mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", mockery::mock(function(x, winslash = "/", mustWork = FALSE) x, cycle = TRUE))
# Mapping and later pipeline
mockery::stub(fn, "get_source_test_mapping_runit_nstf", mockery::mock(make_mapping()))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf", mockery::mock(data.frame(
test_file = NA_character_,
issue_type = "No tests skipped",
stringsAsFactors = FALSE
)))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(`function` = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
# Env prep for coverage
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env()))
mockery::stub(fn, "assign", mockery::mock(NULL))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "message", mockery::mock(NULL, cycle = TRUE))
# Coverage: trigger failure to default path
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
mockery::stub(fn, "detach_pkg_if_attached", mockery::mock(TRUE))
mockery::stub(fn, "library", mockery::mock(NULL))
mockery::stub(fn, "tempfile", mockery::mock("/tmp/runner.R"))
mockery::stub(fn, "writeLines", mockery::mock(NULL))
mockery::stub(fn, "covr::environment_coverage", function(...) stop("covr-failed"))
mockery::stub(fn, "covr::coverage_to_list", mockery::mock(list(filecoverage = matrix(0, nrow = 1), totalcoverage = 0)))
mockery::stub(fn, "cleanup_and_return_null", mockery::mock(NULL))
suppressWarnings(res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data))
expect_type(res, "list")
expect_identical(res$total_cov, 0)
expect_identical(res$res_cov$name, pkg_name)
expect_identical(res$res_cov$coverage$totalcoverage, 0)
expect_identical(res$res_cov$errors, "No RUnit or BiocGenerics configuration")
})
# Minimal helper mapping (one test file to pass mustWork normalization)
make_mapping <- function() {
data.frame(
source_file = c("a.R", "b.R"),
test_file = c("test-a.R", NA_character_),
evidence = c("filename_match", NA_character_),
has_tests = c(TRUE, FALSE),
stringsAsFactors = FALSE
)
}
test_that("error in coverage_to_list hits error branch but lines still produce messages and covr_list", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
test_pkg_data <- list(bioc_run_ut_path = NA_character_)
# Upstream stubs to reach the block
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths",
mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = FALSE) x)
# Mapping with one test to ensure test_files_clean is non-empty
make_mapping <- function() {
data.frame(
source_file = c("a.R", "b.R"),
test_file = c("test-a.R", NA_character_),
evidence = c("filename_match", NA_character_),
has_tests = c(TRUE, FALSE),
stringsAsFactors = FALSE
)
}
mockery::stub(fn, "get_source_test_mapping_runit_nstf", mockery::mock(make_mapping()))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf", mockery::mock(
data.frame(test_file = NA_character_, issue_type = "No tests skipped", stringsAsFactors = FALSE)
))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(fn = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
# Env prep / coverage stubs
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env(), cycle = TRUE))
mockery::stub(fn, "assign", mockery::mock(NULL, cycle = TRUE))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
mockery::stub(fn, "detach_pkg_if_attached", mockery::mock(TRUE))
mockery::stub(fn, "pkgload::load_all", function(...) invisible(NULL))
mockery::stub(fn, "library", mockery::mock(NULL))
mockery::stub(fn, "tempfile", mockery::mock("/tmp/runner.R", cycle = TRUE))
mockery::stub(fn, "writeLines", mockery::mock(NULL, cycle = TRUE))
# keep coverage block alive by returning a benign env for "package:mypkg"
mockery::stub(fn, "as.environment", function(name) {
if (identical(name, paste0("package:", pkg_name))) {
return(new.env(parent = emptyenv()))
}
base::as.environment(name)
})
# Bypass build to avoid normalizePath(mustWork=TRUE) on fake path
mock_runner_path <- tempfile(fileext = ".R")
writeLines(c("library(mypkg)", "1 + 1"), mock_runner_path)
mockery::stub(fn, "build_runit_custom_runner", mockery::mock(mock_runner_path))
# Return > 0 to skip package_coverage fallback
mockery::stub(fn, "covr::percent_coverage", mockery::mock(75.0))
# Force error in coverage_to_list -> error branch sets res_cov$errors and NA coverage fields
mockery::stub(fn, "covr::environment_coverage", mockery::mock(structure(list(), class = "covr_coverage")))
mockery::stub(fn, "covr::coverage_to_list", function(...) stop("explode"))
# Stub compute_total_coverage to still return values (so the lines proceed)
mockery::stub(fn, "compute_total_coverage", function(percent_cov, ...) {
# percent_cov will be NA_real_ due to error branch; ignore and return defaults
list(
total_cov = 0.00,
percent_cov = 0.00,
n_testfiles = 1L,
n_no_function_tests = 1L,
n_skipped_files = 0L
)
})
# Capture messages & cleanup calls
mock_msg <- mockery::mock(NULL, cycle = TRUE)
mock_clean <- mockery::mock(NULL)
mockery::stub(fn, "message", mock_msg)
mockery::stub(fn, "cleanup_and_return_null", mock_clean)
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
# Messages exist (Total Coverage 0.00%, Approx total coverage 0.00%)
msg_calls <- mockery::mock_args(mock_msg)
all_msgs <- vapply(msg_calls, function(x) paste0(x, collapse = ""), character(1))
total_line <- all_msgs[grepl("^Total Coverage for mypkg is:", all_msgs)]
approx_line <- all_msgs[grepl("^Approx total coverage:", all_msgs)]
expect_true(length(total_line) >= 1)
expect_true(length(approx_line) >= 1)
expect_match(total_line[1], "0%")
expect_match(approx_line[1], "\\(0\\.00%\\)")
# cleanup called once
mockery::expect_called(mock_clean, 1)
# covr_list assembled
expect_type(res, "list")
expect_true("res_cov" %in% names(res))
# In error branch, res_cov$coverage$'totalcoverage' == NA_integer_
expect_true(is.na(res$res_cov$coverage$totalcoverage))
expect_true(inherits(res$res_cov$errors, "error") || is.character(res$res_cov$errors))
})
test_that("returns TRUE when test_pkg_data$has_BioG_test is TRUE regardless of files", {
fn <- is_bioc_runit_layout
# Mock filesystem as FALSE to ensure the first clause is sufficient
mock_dir_exists <- mockery::mock(FALSE)
mock_file_exists <- mockery::mock(FALSE)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(pkg_source_path = "/fake/path", test_pkg_data = list(has_BioG_test = TRUE))
expect_true(res)
# Both stubs should still be called once due to evaluation sequence of ||
# (In R, || is short-circuiting, but since the first is TRUE, the others may not be called.
# To be robust across implementations, we don't assert call counts here.)
})
test_that("returns FALSE when no BioC-RUnit indicators are present", {
fn <- is_runit_layout
mock_dir_exists <- mockery::mock(FALSE)
mock_file_exists <- mockery::mock(FALSE)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
# test_pkg_data NULL or missing field -> isTRUE(NULL) => FALSE
res1 <- fn(pkg_source_path = "/fake/path", test_pkg_data = NULL)
expect_false(res1)
})
test_that("returns TRUE when inst/unitTests directory exists", {
fn <- is_runit_layout
# dir.exists should return TRUE; file.exists shouldn't need to be consulted,
# but we mock it to a known value anyway.
mock_dir_exists <- mockery::mock(TRUE)
mock_file_exists <- mockery::mock(FALSE)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(pkg_source_path = "/fake/path", test_pkg_data = list(has_BioG_test = FALSE))
expect_true(res)
# Verify dir.exists was called once with constructed path
mockery::expect_called(mock_dir_exists, 1)
# We can also check the argument passed to dir.exists (optional)
called_args <- mockery::mock_args(mock_dir_exists)
expect_match(called_args[[1]][[1]], "/fake/path/inst/unitTests$")
})
test_that("returns TRUE when tests/run_unitTests.R file exists", {
fn <- is_runit_layout
mock_dir_exists <- mockery::mock(FALSE)
mock_file_exists <- mockery::mock(TRUE)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(pkg_source_path = "/fake/path", test_pkg_data = list(has_BioG_test = FALSE))
expect_true(res)
# Verify file.exists was called once with constructed path
mockery::expect_called(mock_file_exists, 1)
called_args <- mockery::mock_args(mock_file_exists)
expect_match(called_args[[1]][[1]], "/fake/path/tests/run_unitTests\\.R$")
})
test_that("short-circuit behavior: when has_BioG_test is TRUE, other checks need not be TRUE", {
fn <- is_runit_layout
# We set dir.exists and file.exists to throw if called; if the function
# short-circuits correctly, these should not be invoked.
throwing_dir_exists <- function(...) stop("dir.exists should not be called")
throwing_file_exists <- function(...) stop("file.exists should not be called")
mockery::stub(fn, "dir.exists", throwing_dir_exists)
mockery::stub(fn, "file.exists", throwing_file_exists)
expect_true(fn(pkg_source_path = "/fake/path", test_pkg_data = list(has_BioG_test = TRUE)))
})
test_that("handles has_BioG_test = NULL or missing field as FALSE", {
fn <- is_runit_layout
mock_dir_exists <- mockery::mock(FALSE)
mock_file_exists <- mockery::mock(FALSE)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
# Explicit NULL value
res_null <- fn(pkg_source_path = "/fake/path", test_pkg_data = list(has_BioG_test = NULL))
expect_false(res_null)
})
test_that("supports atomic pkg_source_path; only path construction matters", {
fn <- is_runit_layout
mock_dir_exists <- mockery::mock(FALSE)
mock_file_exists <- mockery::mock(FALSE)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
# Try with a different path format; the stubs ensure no actual filesystem usage
res <- fn(pkg_source_path = "C:\\proj", test_pkg_data = NULL)
expect_false(res)
})
test_that("does nothing when package not attached and namespace not loaded", {
fn <- detach_pkg_if_attached
# search() contains no package:pkg
mock_search <- mockery::mock(c("package:stats", "package:utils"))
mock_detach <- mockery::mock(NULL) # should not be called
mock_is_ns <- mockery::mock(FALSE)
mock_unload <- mockery::mock(NULL) # should not be called
mock_message <- mockery::mock(NULL)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "isNamespaceLoaded", mock_is_ns)
mockery::stub(fn, "unloadNamespace", mock_unload)
mockery::stub(fn, "message", mock_message)
# Result is invisible TRUE
v <- withVisible(fn("mypkg", unload_namespace = TRUE, quiet = TRUE))
expect_true(v$value)
expect_false(v$visible)
# detach and unload should not be called
mockery::expect_called(mock_detach, 0)
mockery::expect_called(mock_unload, 0)
# no messages because quiet = TRUE
mockery::expect_called(mock_message, 0)
})
test_that("detaches when package attached; quiet=TRUE suppresses message", {
fn <- detach_pkg_if_attached
mock_search <- mockery::mock(c("package:mypkg", "package:stats"))
mock_detach <- mockery::mock(NULL)
mock_is_ns <- mockery::mock(FALSE) # namespace not loaded
mock_unload <- mockery::mock(NULL) # not called
mock_message <- mockery::mock(NULL)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "isNamespaceLoaded", mock_is_ns)
mockery::stub(fn, "unloadNamespace", mock_unload)
mockery::stub(fn, "message", mock_message)
res <- fn("mypkg", unload_namespace = TRUE, quiet = TRUE)
expect_true(res)
# detach should be called once with constructed search name and flags
mockery::expect_called(mock_detach, 1)
args <- mockery::mock_args(mock_detach)
expect_equal(args[[1]][[1]], "package:mypkg")
expect_true(isTRUE(args[[1]][["unload"]]))
expect_true(isTRUE(args[[1]][["character.only"]]))
# namespace unload should not be called (isNamespaceLoaded == FALSE)
mockery::expect_called(mock_unload, 0)
# quiet=TRUE means no message
mockery::expect_called(mock_message, 0)
})
test_that("unloads namespace when loaded; quiet=TRUE suppresses message", {
fn <- detach_pkg_if_attached
mock_search <- mockery::mock(c("package:stats")) # not attached
mock_detach <- mockery::mock(NULL) # not called
mock_is_ns <- mockery::mock(TRUE) # namespace loaded
mock_unload <- mockery::mock(NULL)
mock_message <- mockery::mock(NULL)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "isNamespaceLoaded", mock_is_ns)
mockery::stub(fn, "unloadNamespace", mock_unload)
mockery::stub(fn, "message", mock_message)
res <- fn("mypkg", unload_namespace = TRUE, quiet = TRUE)
expect_true(res)
mockery::expect_called(mock_detach, 0)
mockery::expect_called(mock_unload, 1)
unload_args <- mockery::mock_args(mock_unload)
expect_equal(unload_args[[1]][[1]], "mypkg")
mockery::expect_called(mock_message, 0)
})
test_that("both detach and unload occur when attached and namespace loaded", {
fn <- detach_pkg_if_attached
mock_search <- mockery::mock(c("package:mypkg", "package:stats"))
mock_detach <- mockery::mock(NULL)
mock_is_ns <- mockery::mock(TRUE)
mock_unload <- mockery::mock(NULL)
mock_message <- mockery::mock(NULL)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "isNamespaceLoaded", mock_is_ns)
mockery::stub(fn, "unloadNamespace", mock_unload)
mockery::stub(fn, "message", mock_message)
res <- fn("mypkg", unload_namespace = TRUE, quiet = TRUE)
expect_true(res)
mockery::expect_called(mock_detach, 1)
mockery::expect_called(mock_unload, 1)
mockery::expect_called(mock_message, 0)
})
test_that("unload_namespace = FALSE prevents namespace unloading", {
fn <- detach_pkg_if_attached
mock_search <- mockery::mock(c("package:mypkg"))
mock_detach <- mockery::mock(NULL)
mock_is_ns <- mockery::mock(TRUE) # would be loaded, but flag stops unload
mock_unload <- mockery::mock(NULL) # should not be called
mock_message <- mockery::mock(NULL)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "isNamespaceLoaded", mock_is_ns)
mockery::stub(fn, "unloadNamespace", mock_unload)
mockery::stub(fn, "message", mock_message)
res <- fn("mypkg", unload_namespace = FALSE, quiet = TRUE)
expect_true(res)
mockery::expect_called(mock_detach, 1)
mockery::expect_called(mock_unload, 0)
})
test_that("try() respects silent flag; errors in detach/unload are swallowed when quiet=TRUE", {
fn <- detach_pkg_if_attached
mock_search <- mockery::mock(c("package:mypkg"))
mock_detach <- function(...) stop("detach failed") # throws
mock_is_ns <- mockery::mock(TRUE)
mock_unload <- function(...) stop("unload failed") # throws
mock_message <- mockery::mock(NULL)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "isNamespaceLoaded", mock_is_ns)
mockery::stub(fn, "unloadNamespace", mock_unload)
mockery::stub(fn, "message", mock_message)
# quiet=TRUE => try(..., silent = TRUE): errors are swallowed, function still returns TRUE
expect_true(fn("mypkg", unload_namespace = TRUE, quiet = TRUE))
})
test_that("returns invisible(TRUE) in all paths", {
fn <- detach_pkg_if_attached
mock_search <- mockery::mock(c("package:mypkg"))
mock_detach <- mockery::mock(NULL)
mock_is_ns <- mockery::mock(TRUE)
mock_unload <- mockery::mock(NULL)
mock_message <- mockery::mock(NULL)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "isNamespaceLoaded", mock_is_ns)
mockery::stub(fn, "unloadNamespace", mock_unload)
mockery::stub(fn, "message", mock_message)
v <- withVisible(fn("mypkg", unload_namespace = TRUE, quiet = TRUE))
expect_true(v$value)
expect_false(v$visible)
})
test_that("detaches target package and BioC infra packages in order", {
fn <- prepare_for_bioc_runit
# Mock the detacher to record calls
mock_detach <- mockery::mock(NULL, NULL, NULL, NULL) # 4 calls total expected
# Mock load_all to prevent real load and to inspect args
mock_load_all <- mockery::mock(NULL)
# Stub symbols referenced inside the function
mockery::stub(fn, "detach_pkg_if_attached", mock_detach)
mockery::stub(fn, "pkgload::load_all", mock_load_all)
# Use a fake path/pkg
res <- fn(pkg_name = "mypkg", pkg_source_path = "/tmp/mypkg", detach_bioc_infra = TRUE)
expect_true(res)
# Expect 4 detach calls: mypkg, IRanges, S4Vectors, BiocGenerics
mockery::expect_called(mock_detach, 4)
calls <- mockery::mock_args(mock_detach)
expect_identical(calls[[1]][[1]], "mypkg")
expect_identical(calls[[2]][[1]], "IRanges")
expect_identical(calls[[3]][[1]], "S4Vectors")
expect_identical(calls[[4]][[1]], "BiocGenerics")
# Verify load_all called once, with path and quiet=TRUE
mockery::expect_called(mock_load_all, 1)
la_args <- mockery::mock_args(mock_load_all)
expect_identical(la_args[[1]][[1]], "/tmp/mypkg")
expect_true(isTRUE(la_args[[1]][["quiet"]]))
})
test_that("options(warn) is temporarily set to 1 and restored after function exits", {
fn <- prepare_for_bioc_runit
# Mocks to avoid real side effects
mock_detach <- mockery::mock(NULL, NULL, NULL, NULL)
mock_load_all <- mockery::mock(NULL)
mockery::stub(fn, "detach_pkg_if_attached", mock_detach)
mockery::stub(fn, "pkgload::load_all", mock_load_all)
# Preserve and auto-restore original options/env using withr
old_warn <- getOption("warn")
withr::local_options(list(warn = old_warn))
# Before call: whatever the test harness has
expect_identical(getOption("warn"), old_warn)
# Call the function (it will set warn=1 internally and restore on exit)
res <- fn(pkg_name = "mypkg", pkg_source_path = "/tmp/mypkg", detach_bioc_infra = TRUE)
expect_true(res)
# After return, warn should be restored to old_warn
expect_identical(getOption("warn"), old_warn)
})
test_that('R_TESTS is empty during test (local_envvar)', {
is_windows <- identical(.Platform$OS.type, "windows")
# Ensure clean slate first
Sys.unsetenv("R_TESTS")
# Temporarily set for the duration of the test; withr restores automatically
withr::local_envvar(if (is_windows) list("R_TESTS" = "") else list(R_TESTS = ""))
# ... run things that depend on R_TESTS="", or assertions ...
expect_identical(Sys.getenv("R_TESTS"), "")
})
test_that("POSIX branch: sets R_TESTS='' and restores to UNSET when originally unset", {
# Only run on Linux/macOS to exercise the POSIX branch
# Skip on Windows with explanation
skip_if(
condition = .Platform$OS.type == "windows",
message = paste(
"Skipped on Windows: this test exercises the POSIX-only behaviour of",
"prepare_for_bioc_runit where R_TESTS is set to '' and restored to UNSET.",
"Windows does not reliably distinguish empty vs UNSET environment variables."
)
)
fn <- prepare_for_bioc_runit
# Mock non-essential collaborators
mock_detach <- mockery::mock(NULL, NULL, NULL, NULL)
mock_load_all <- mockery::mock(NULL)
mockery::stub(fn, "detach_pkg_if_attached", mock_detach)
mockery::stub(fn, "pkgload::load_all", mock_load_all)
# Ensure R_TESTS is UNSET to begin with
Sys.unsetenv("R_TESTS")
# Belt & suspenders: ensure we leave R_TESTS unset after the test, even if assertions fail
withr::defer({
Sys.unsetenv("R_TESTS")
})
# Call the function under test (should set R_TESTS="" and register on.exit restoration)
res <- fn(pkg_name = "mypkg", pkg_source_path = "/tmp/mypkg", detach_bioc_infra = TRUE)
expect_true(res)
# After the function returns, on.exit should have restored to UNSET
# expect_true(is.na(Sys.getenv("R_TESTS", unset = NA_character_)))
})
test_that("POSIX branch: sets R_TESTS='' and restores to previous value when originally set (mocked)", {
skip_if(
condition = .Platform$OS.type == "windows",
message = paste("Skipped on Windows: this test exercises POSIX-specific behaviour where R_TESTS must be ",
"set to '' then restored. Windows environment handling (cmd.exe/PowerShell) treats empty ",
"environment variables differently and cannot reliably distinguish '' from prior values, ",
"making the restoration semantics untestable.")
)
fn <- prepare_for_bioc_runit
# Seed original value so old_R_TESTS inside fn is non-NA
original <- "previous-value"
Sys.setenv(R_TESTS = original)
# --- Mocks ---
mock_setenv <- mockery::mock(NULL, NULL) # first for "", then for restore to original
mock_unsetenv <- mockery::mock(NULL) # should NOT be called in this path
mock_detach <- mockery::mock(NULL, NULL, NULL, NULL)
mock_load_all <- mockery::mock(NULL)
mockery::stub(fn, "Sys.setenv", mock_setenv)
mockery::stub(fn, "Sys.unsetenv", mock_unsetenv)
mockery::stub(fn, "detach_pkg_if_attached", mock_detach)
mockery::stub(fn, "pkgload::load_all", mock_load_all)
# Execute
res <- fn(pkg_name = "mypkg", pkg_source_path = "/tmp/mypkg", detach_bioc_infra = TRUE)
expect_true(res)
# Assertions:
set_calls <- mockery::mock_args(mock_setenv)
# 1) It sets R_TESTS to empty string initially
expect_true(any(vapply(set_calls, function(x) identical(x, list(R_TESTS = "")), logical(1))),
info = "Sys.setenv(R_TESTS = \"\") should be called in POSIX branch")
})
test_that("run_covr_skip_runit_nstf: cleaning branch -> happy path updates mapping and proceeds", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
# --- test_pkg_data with cleaning branch active ---
test_pkg_data <- list(
bioc_run_ut_path = file.path(pkg_source_path, "inst", "unitTests", "run_unitTests.R"),
has_BioG_test = TRUE
)
cov_env <- new.env(parent = baseenv())
# --- Stubs for early steps -------------------------------------------------
mockery::stub(fn, "get_pkg_name", function(...) pkg_name)
mockery::stub(fn, "is_runit_layout", function(...) TRUE)
mockery::stub(fn, "get_runit_test_paths",
function(...) list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))
)
mockery::stub(fn, "normalizePath",
function(path, winslash = "/", mustWork = FALSE, ...) path
)
# mapping BEFORE cleaning (contains run_unitTests.R)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
function(...) data.frame(
source_file = c("a.R", "b.R"),
test_file = c("run_unitTests.R", "test-a.R"),
evidence = c("filename_match", "filename_match"),
has_tests = TRUE,
stringsAsFactors = FALSE
)
)
# mapping AFTER cleaning
mockery::stub(fn, "remove_run_unitTests_mapping",
function(mapping, ...) {
mapping[mapping$test_file != "run_unitTests.R", , drop = FALSE]
}
)
mockery::stub(fn, "prepare_for_bioc_runit", function(...) TRUE)
mockery::stub(fn, "check_covr_skip_runit_nstf",
function(...) data.frame(
test_file = NA_character_,
issue_type = "No tests skipped",
stringsAsFactors = FALSE
)
)
mockery::stub(fn, "get_function_no_tests",
function(...) data.frame(`function` = "b", stringsAsFactors = FALSE)
)
# drop_na identity
mockery::stub(fn, "tidyr::drop_na", function(df, ...) df)
# Coverage environment mocks
mockery::stub(fn, "ls", function(...) c("obj1", "obj2"))
mockery::stub(fn, "asNamespace", function(...) new.env())
mockery::stub(fn, "assign", function(...) NULL)
mockery::stub(fn, "load_package_datasets", function(...) c("ds1", "ds2"))
# coverage block -> fail -> fallback return
mockery::stub(fn, "loadedNamespaces", function(...) c("base"))
mockery::stub(fn, "loadNamespace", function(...) NULL)
mockery::stub(fn, "detach_pkg_if_attached", function(...) TRUE)
mockery::stub(fn, "library", function(...) NULL)
mockery::stub(fn, "tempfile", function(...) "/tmp/runner.R")
mockery::stub(fn, "writeLines", function(...) NULL)
mockery::stub(fn, "covr::environment_coverage", function(...) stop("instrumentation failed"))
mockery::stub(fn, "covr::coverage_to_list",
function(...) list(filecoverage = matrix(0,1), totalcoverage = 0)
)
# cleanup (should be called on coverage error)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
# --- Execute, capturing messages because message() was stubbed away earlier ---
output <- testthat::capture_messages(
suppressWarnings(res <- fn(pkg_source_path = pkg_source_path,
test_pkg_data = test_pkg_data,
cov_env = cov_env))
)
# --- Assertions -----------------------------------------------------------
# Ensure cleaning message was emitted
expect_true(any(grepl("performing source test map cleaning for mypkg", output)))
# Should not be NULL (because fn returns fallback structure)
expect_false(is.null(res))
})
test_that("run_covr_skip_runit_nstf builds correct run_test_line for prefix = 'runit'", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
test_pkg_data <- list(has_BioG_test = FALSE, bioc_run_ut_path = NA)
cov_env <- new.env()
# ---- ESSENTIAL STUBS ----
mockery::stub(fn, "get_pkg_name", function(...) "mypkg")
mockery::stub(fn, "is_runit_layout", function(...) TRUE)
mockery::stub(fn, "get_runit_test_paths",
function(...) list(bioc_unitTests = "/fake/pkg/inst/unitTests")
)
mockery::stub(fn, "normalizePath", function(path, ...) path)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
function(...) data.frame(
source_file="a.R",
test_file="test-a.R",
evidence="filename_match",
has_tests=TRUE
)
)
mockery::stub(fn, "remove_run_unitTests_mapping", identity)
mockery::stub(fn, "prepare_for_bioc_runit", function(...) TRUE)
mockery::stub(fn, "check_covr_skip_runit_nstf",
function(...) data.frame(test_file=NA_character_, issue_type="No tests skipped")
)
mockery::stub(fn, "get_function_no_tests", function(...) data.frame(fun="a"))
mockery::stub(fn, "tidyr::drop_na", function(df, ...) df)
mockery::stub(fn, "ls", function(...) character(0))
mockery::stub(fn, "asNamespace", function(...) new.env())
mockery::stub(fn, "assign", function(...) NULL)
mockery::stub(fn, "load_package_datasets", function(...) character(0))
mockery::stub(fn, "file.exists", function(...) TRUE)
mockery::stub(fn, "dir.exists", function(...) TRUE)
# force prefix = runit
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
# ---- Capture runner file created inside writeLines() ----
runner_path <- NULL
mockery::stub(fn, "writeLines", function(lines, path, ...) {
runner_path <<- path
base::writeLines(lines, path)
})
# fail coverage
mockery::stub(fn, "covr::environment_coverage", function(...) stop("fail"))
mockery::stub(fn, "covr::coverage_to_list",
function(...) list(filecoverage=matrix(0,1), totalcoverage=0)
)
mockery::stub(fn, "loadedNamespaces", function(...) "base")
mockery::stub(fn, "detach_pkg_if_attached", function(...) TRUE)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
# ---- RUN ----
out <- testthat::capture_messages(
suppressWarnings(fn(pkg_source_path = pkg_source_path,
test_pkg_data = test_pkg_data,
cov_env = cov_env))
)
# ---- ASSERTIONS ----
expect_true(is.character(out))
expect_false(is.null(out))
})
test_that("run_covr_skip_runit_nstf builds correct run_test_line for prefix = 'Test'", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
test_pkg_data <- list(has_BioG_test = FALSE, bioc_run_ut_path = NA)
cov_env <- new.env()
# ---- ESSENTIAL STUBS (same pattern as runit test) ----
mockery::stub(fn, "get_pkg_name", function(...) "mypkg")
mockery::stub(fn, "is_runit_layout", function(...) TRUE)
mockery::stub(fn, "get_runit_test_paths",
function(...) list(bioc_unitTests = "/fake/pkg/inst/unitTests"))
mockery::stub(fn, "normalizePath", function(path, ...) path)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
function(...) data.frame(
source_file="a.R",
test_file="Test-a.R",
evidence="filename_match",
has_tests=TRUE,
stringsAsFactors = FALSE
))
mockery::stub(fn, "remove_run_unitTests_mapping", identity)
mockery::stub(fn, "prepare_for_bioc_runit", function(...) TRUE)
mockery::stub(fn, "check_covr_skip_runit_nstf",
function(...) data.frame(test_file=NA_character_, issue_type="No tests skipped"))
mockery::stub(fn, "get_function_no_tests", function(...) data.frame(fun="a"))
mockery::stub(fn, "tidyr::drop_na", function(df, ...) df)
mockery::stub(fn, "ls", function(...) character(0))
mockery::stub(fn, "asNamespace", function(...) new.env())
mockery::stub(fn, "assign", function(...) NULL)
mockery::stub(fn, "load_package_datasets", function(...) character(0))
mockery::stub(fn, "file.exists", function(...) TRUE)
mockery::stub(fn, "dir.exists", function(...) TRUE)
# FORCE "Test" prefix
mockery::stub(fn, "detect_runit_test_prefix", function(...) "Test")
# Capture runner file
runner_path <- NULL
mockery::stub(fn, "writeLines", function(lines, path, ...) {
runner_path <<- path
base::writeLines(lines, path)
})
mockery::stub(fn, "covr::environment_coverage", function(...) stop("fail"))
mockery::stub(fn, "covr::coverage_to_list",
function(...) list(filecoverage=matrix(0,1), totalcoverage=0))
mockery::stub(fn, "loadedNamespaces", function(...) "base")
mockery::stub(fn, "detach_pkg_if_attached", function(...) TRUE)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
# ---- RUN ----
out <- testthat::capture_messages(
suppressWarnings(fn(pkg_source_path = pkg_source_path,
test_pkg_data = test_pkg_data,
cov_env = cov_env))
)
# ---- ASSERTIONS ----
expect_true(is.character(out))
expect_false(is.null(out))
})
test_that("run_covr_skip_runit_nstf builds correct run_test_line for default prefix 'test'", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
test_pkg_data <- list(has_BioG_test = FALSE, bioc_run_ut_path = NA)
cov_env <- new.env()
# ---- ESSENTIAL STUBS ----
mockery::stub(fn, "get_pkg_name", function(...) "mypkg")
mockery::stub(fn, "is_runit_layout", function(...) TRUE)
mockery::stub(fn, "get_runit_test_paths",
function(...) list(bioc_unitTests = "/fake/pkg/inst/unitTests"))
mockery::stub(fn, "normalizePath", function(path, ...) path)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
function(...) data.frame(
source_file="a.R",
test_file="test-a.R",
evidence="filename_match",
has_tests=TRUE,
stringsAsFactors = FALSE
))
mockery::stub(fn, "remove_run_unitTests_mapping", identity)
mockery::stub(fn, "prepare_for_bioc_runit", function(...) TRUE)
mockery::stub(fn, "check_covr_skip_runit_nstf",
function(...) data.frame(test_file=NA_character_, issue_type="No tests skipped"))
mockery::stub(fn, "get_function_no_tests", function(...) data.frame(fun="a"))
mockery::stub(fn, "tidyr::drop_na", function(df, ...) df)
mockery::stub(fn, "ls", function(...) character(0))
mockery::stub(fn, "asNamespace", function(...) new.env())
mockery::stub(fn, "assign", function(...) NULL)
mockery::stub(fn, "load_package_datasets", function(...) character(0))
mockery::stub(fn, "file.exists", function(...) TRUE)
mockery::stub(fn, "dir.exists", function(...) TRUE)
# FORCE any non-runit, non-Test → fall into default branch
mockery::stub(fn, "detect_runit_test_prefix", function(...) "xyz")
# Capture runner file
runner_path <- NULL
mockery::stub(fn, "writeLines", function(lines, path, ...) {
runner_path <<- path
base::writeLines(lines, path)
})
mockery::stub(fn, "covr::environment_coverage", function(...) stop("fail"))
mockery::stub(fn, "covr::coverage_to_list",
function(...) list(filecoverage=matrix(0,1), totalcoverage=0))
mockery::stub(fn, "loadedNamespaces", function(...) "base")
mockery::stub(fn, "detach_pkg_if_attached", function(...) TRUE)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
# ---- RUN ----
out <- testthat::capture_messages(
suppressWarnings(fn(pkg_source_path = pkg_source_path,
test_pkg_data = test_pkg_data,
cov_env = cov_env))
)
# ---- ASSERTIONS ----
expect_true(is.character(out))
expect_false(is.null(out))
})
test_that("run_covr_skip_runit_nstf: cleaning branch -> happy path updates mapping and proceeds", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
# Cleaning branch must activate (non-NA bioc_run_ut_path)
test_pkg_data <- list(
bioc_run_ut_path = "/fake/pkg/inst/unitTests/run_unitTests.R",
has_BioG_test = TRUE
)
cov_env <- new.env(parent = baseenv())
# ---------------------------------------------------------------------------
# ESSENTIAL STUBS ONLY
# ---------------------------------------------------------------------------
mockery::stub(fn, "get_pkg_name", function(...) pkg_name)
mockery::stub(fn, "is_runit_layout", function(...) TRUE)
mockery::stub(fn, "get_runit_test_paths",
function(...) list(bioc_unitTests = "/fake/pkg/inst/unitTests")
)
mockery::stub(fn, "normalizePath", function(path, ...) path)
# Mapping BEFORE cleaning (contains run_unitTests.R)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
function(...) data.frame(
source_file = c("a.R", "b.R"),
test_file = c("run_unitTests.R", "test-b.R"),
evidence = c("filename_match", "filename_match"),
has_tests = TRUE,
stringsAsFactors = FALSE
)
)
# Cleaning removes run_unitTests.R
mockery::stub(fn, "remove_run_unitTests_mapping",
function(mapping, ...) {
mapping[mapping$test_file != "run_unitTests.R", , drop = FALSE]
}
)
mockery::stub(fn, "prepare_for_bioc_runit", function(...) TRUE)
# No problematic tests → no skipping
mockery::stub(fn, "check_covr_skip_runit_nstf",
function(...) data.frame(
test_file = NA_character_,
issue_type = "No tests skipped",
stringsAsFactors = FALSE
)
)
mockery::stub(fn, "get_function_no_tests",
function(...) data.frame(fun = "b", stringsAsFactors = FALSE)
)
mockery::stub(fn, "tidyr::drop_na", function(df, ...) df)
# Minimal env population stubs
mockery::stub(fn, "ls", function(...) character(0))
mockery::stub(fn, "asNamespace", function(...) new.env())
mockery::stub(fn, "assign", function(...) NULL)
mockery::stub(fn, "load_package_datasets", function(...) character(0))
# Force coverage instrumentation to fail → fallback return
mockery::stub(fn, "loadedNamespaces", function(...) c("base"))
mockery::stub(fn, "detach_pkg_if_attached", function(...) TRUE)
mockery::stub(fn, "covr::environment_coverage", function(...) stop("instrumentation failed"))
mockery::stub(fn, "covr::coverage_to_list",
function(...) list(filecoverage = matrix(0, 1), totalcoverage = 0)
)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
# ---------------------------------------------------------------------------
# Run the function and CAPTURE MESSAGE() output (CRITICAL!)
# ---------------------------------------------------------------------------
output <- testthat::capture_messages(
res <- suppressWarnings(fn(pkg_source_path = pkg_source_path,
test_pkg_data = test_pkg_data,
cov_env = cov_env))
)
# ---------------------------------------------------------------------------
# Assertions
# ---------------------------------------------------------------------------
# Cleaning message MUST appear
expect_true(any(grepl(
"performing source test map cleaning for mypkg",
output
)))
expect_false(is.null(output))
# Function returns a non-null result (successful continuation)
expect_false(is.null(res))
})
test_that("run_covr_skip_runit_nstf: cleaning branch -> NULL mapping returns NULL early", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
# Cleaning branch must trigger -> bioc_run_ut_path is non-NA
test_pkg_data <- list(
bioc_run_ut_path = "/fake/pkg/inst/unitTests/run_unitTests.R",
has_BioG_test = TRUE
)
# --- ESSENTIAL STUBS ONLY --------------------------------------------------
mockery::stub(fn, "get_pkg_name", function(...) pkg_name)
mockery::stub(fn, "is_runit_layout", function(...) TRUE)
# valid test path list
mockery::stub(fn, "get_runit_test_paths",
function(...) list(bioc_unitTests = "/fake/pkg/inst/unitTests")
)
mockery::stub(fn, "normalizePath", function(path, ...) path)
# Mapping BEFORE cleaning (must be a data.frame)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
function(...) data.frame(
source_file = c("a.R","b.R"),
test_file = c("run_unitTests.R","test-b.R"),
evidence = "filename_match",
has_tests = TRUE,
stringsAsFactors = FALSE
)
)
# Cleaning returns NULL → EARLY RETURN expected
mockery::stub(fn, "remove_run_unitTests_mapping", function(...) NULL)
# These will not execute due to early return but must exist to avoid missing stubs
mockery::stub(fn, "prepare_for_bioc_runit", function(...) TRUE)
mockery::stub(fn, "check_covr_skip_runit_nstf",
function(...) data.frame(test_file=NA_character_, issue_type="No tests skipped"))
mockery::stub(fn, "get_function_no_tests",
function(...) data.frame(fun="b"))
mockery::stub(fn, "tidyr::drop_na", function(df, ...) df)
mockery::stub(fn, "ls", function(...) character(0))
mockery::stub(fn, "asNamespace", function(...) new.env())
mockery::stub(fn, "assign", function(...) NULL)
mockery::stub(fn, "load_package_datasets", function(...) character(0))
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
# ---------------------------------------------------------------------------
# Capture messages reliably
# ---------------------------------------------------------------------------
output <- testthat::capture_messages(
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
)
# ---- ASSERTIONS -----------------------------------------------------------
# Must exit early with NULL because cleaned mapping is NULL
expect_null(res)
# Cleaning message MUST appear
expect_true(any(grepl(
"performing source test map cleaning for mypkg",
output
)))
})
test_that("doRUnit branch: message 'Trying doRUnit.R' and build_doRUnit_wrapper called when doRUnit_path exists", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
doRUnit_path <- "/fake/pkg/tests/doRUnit.R"
test_pkg_data <- list(
bioc_run_ut_path = NA_character_,
doRUnit_path = doRUnit_path
)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths",
mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = FALSE, ...) x)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
mockery::mock(data.frame(source_file = "a.R", test_file = "test-a.R", evidence = "match", has_tests = TRUE, stringsAsFactors = FALSE)))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf",
mockery::mock(data.frame(test_file = NA_character_, issue_type = "No tests skipped", stringsAsFactors = FALSE)))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(fn = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env(), cycle = TRUE))
mockery::stub(fn, "assign", mockery::mock(NULL, cycle = TRUE))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
mockery::stub(fn, "detach_pkg_if_attached", mockery::mock(TRUE))
mockery::stub(fn, "pkgload::load_all", mockery::mock(invisible(NULL)))
mockery::stub(fn, "as.environment", function(name) {
if (identical(name, paste0("package:", pkg_name))) return(new.env(parent = emptyenv()))
base::as.environment(name)
})
mock_file_exists <- function(path) path == doRUnit_path
mockery::stub(fn, "file.exists", mock_file_exists)
mock_runner <- tempfile(fileext = ".R")
writeLines("1+1", mock_runner)
mock_build_doRUnit <- mockery::mock(mock_runner)
mockery::stub(fn, "build_doRUnit_wrapper", mock_build_doRUnit)
mock_env_cov <- mockery::mock(structure(list(), class = "covr_coverage"))
mockery::stub(fn, "covr::environment_coverage", mock_env_cov)
mockery::stub(fn, "covr::percent_coverage", mockery::mock(75.0))
mockery::stub(fn, "covr::coverage_to_list", mockery::mock(list(totalcoverage = 75.0)))
mockery::stub(fn, "compute_total_coverage", mockery::mock(list(total_cov = 0.75, percent_cov = 75.0, n_testfiles = 1L, n_no_function_tests = 1L, n_skipped_files = 0L)))
mockery::stub(fn, "build_runit_runTests_runner", mockery::mock(mock_runner))
mockery::stub(fn, "build_runit_custom_runner", mockery::mock(mock_runner))
mock_msg <- mockery::mock(NULL, cycle = TRUE)
mockery::stub(fn, "message", mock_msg)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
msg_calls <- mockery::mock_args(mock_msg)
all_msgs <- vapply(msg_calls, function(x) paste0(x, collapse = ""), character(1))
expect_true(any(grepl("Trying doRUnit.R for mypkg", all_msgs)))
mockery::expect_called(mock_build_doRUnit, 1)
args <- mockery::mock_args(mock_build_doRUnit)
expect_identical(args[[1]][[1]], doRUnit_path)
})
test_that("doRUnit branch: when env_coverage throws, message 'doRUnit.R failed' and fallback to runTests-style runner", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
doRUnit_path <- "/fake/pkg/tests/doRUnit.R"
test_pkg_data <- list(
bioc_run_ut_path = NA_character_,
doRUnit_path = doRUnit_path
)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths",
mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = FALSE, ...) x)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
mockery::mock(data.frame(source_file = "a.R", test_file = "test-a.R", evidence = "match", has_tests = TRUE, stringsAsFactors = FALSE)))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf",
mockery::mock(data.frame(test_file = NA_character_, issue_type = "No tests skipped", stringsAsFactors = FALSE)))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(fn = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env(), cycle = TRUE))
mockery::stub(fn, "assign", mockery::mock(NULL, cycle = TRUE))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
mockery::stub(fn, "detach_pkg_if_attached", mockery::mock(TRUE))
mockery::stub(fn, "pkgload::load_all", mockery::mock(invisible(NULL)))
mockery::stub(fn, "as.environment", function(name) {
if (identical(name, paste0("package:", pkg_name))) return(new.env(parent = emptyenv()))
base::as.environment(name)
})
mock_file_exists <- function(path) path == doRUnit_path
mockery::stub(fn, "file.exists", mock_file_exists)
mock_runner <- tempfile(fileext = ".R")
writeLines("1+1", mock_runner)
mockery::stub(fn, "build_doRUnit_wrapper", mockery::mock(mock_runner))
mockery::stub(fn, "covr::environment_coverage", function(...) stop("doRUnit instrumentation failed"))
mock_runTests_runner <- mockery::mock(mock_runner)
mockery::stub(fn, "build_runit_runTests_runner", mock_runTests_runner)
mockery::stub(fn, "covr::percent_coverage", mockery::mock(75.0))
mockery::stub(fn, "covr::coverage_to_list", mockery::mock(list(totalcoverage = 75.0)))
mockery::stub(fn, "compute_total_coverage", mockery::mock(list(total_cov = 0.75, percent_cov = 75.0, n_testfiles = 1L, n_no_function_tests = 1L, n_skipped_files = 0L)))
mock_msg <- mockery::mock(NULL, cycle = TRUE)
mockery::stub(fn, "message", mock_msg)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
msg_calls <- mockery::mock_args(mock_msg)
all_msgs <- vapply(msg_calls, function(x) paste0(x, collapse = ""), character(1))
expect_true(any(grepl("doRUnit.R failed:.*falling back to custom runner", all_msgs)))
mockery::expect_called(mock_runTests_runner, 1)
})
test_that("doRUnit branch: when percent_coverage returns 0, message and fallback to runTests-style runner", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
doRUnit_path <- "/fake/pkg/tests/doRUnit.R"
test_pkg_data <- list(
bioc_run_ut_path = NA_character_,
doRUnit_path = doRUnit_path
)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths",
mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = FALSE, ...) x)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
mockery::mock(data.frame(source_file = "a.R", test_file = "test-a.R", evidence = "match", has_tests = TRUE, stringsAsFactors = FALSE)))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf",
mockery::mock(data.frame(test_file = NA_character_, issue_type = "No tests skipped", stringsAsFactors = FALSE)))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(fn = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env(), cycle = TRUE))
mockery::stub(fn, "assign", mockery::mock(NULL, cycle = TRUE))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
mockery::stub(fn, "detach_pkg_if_attached", mockery::mock(TRUE))
mockery::stub(fn, "pkgload::load_all", mockery::mock(invisible(NULL)))
mockery::stub(fn, "as.environment", function(name) {
if (identical(name, paste0("package:", pkg_name))) return(new.env(parent = emptyenv()))
base::as.environment(name)
})
mock_file_exists <- function(path) path == doRUnit_path
mockery::stub(fn, "file.exists", mock_file_exists)
mock_runner <- tempfile(fileext = ".R")
writeLines("1+1", mock_runner)
mockery::stub(fn, "build_doRUnit_wrapper", mockery::mock(mock_runner))
mockery::stub(fn, "covr::environment_coverage", mockery::mock(structure(list(), class = "covr_coverage")))
mockery::stub(fn, "covr::percent_coverage", mockery::mock(0.0))
mock_runTests_runner <- mockery::mock(mock_runner)
mockery::stub(fn, "build_runit_runTests_runner", mock_runTests_runner)
mockery::stub(fn, "covr::coverage_to_list", mockery::mock(list(totalcoverage = 75.0)))
mockery::stub(fn, "compute_total_coverage", mockery::mock(list(total_cov = 0.75, percent_cov = 75.0, n_testfiles = 1L, n_no_function_tests = 1L, n_skipped_files = 0L)))
mock_msg <- mockery::mock(NULL, cycle = TRUE)
mockery::stub(fn, "message", mock_msg)
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
msg_calls <- mockery::mock_args(mock_msg)
all_msgs <- vapply(msg_calls, function(x) paste0(x, collapse = ""), character(1))
expect_true(any(grepl("doRUnit.R produced 0% coverage.*retrying with runTests-style runner", all_msgs)))
mockery::expect_called(mock_runTests_runner, 1)
})
test_that("package_coverage fallback: when env_coverage returns 0%, message and detach/readLines/package_coverage called", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
test_pkg_data <- list(bioc_run_ut_path = NA_character_)
mock_runner <- tempfile(fileext = ".R")
writeLines(c("library(mypkg)", "1 + 1"), mock_runner)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths",
mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = FALSE, ...) x)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
mockery::mock(data.frame(source_file = "a.R", test_file = "test-a.R", evidence = "match", has_tests = TRUE, stringsAsFactors = FALSE)))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf",
mockery::mock(data.frame(test_file = NA_character_, issue_type = "No tests skipped", stringsAsFactors = FALSE)))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(fn = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env(), cycle = TRUE))
mockery::stub(fn, "assign", mockery::mock(NULL, cycle = TRUE))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
mockery::stub(fn, "pkgload::load_all", mockery::mock(invisible(NULL)))
mockery::stub(fn, "as.environment", function(name) {
if (identical(name, paste0("package:", pkg_name))) return(new.env(parent = emptyenv()))
base::as.environment(name)
})
mock_detach <- mockery::mock(TRUE, TRUE)
mockery::stub(fn, "detach_pkg_if_attached", mock_detach)
mockery::stub(fn, "build_runit_custom_runner", mockery::mock(mock_runner))
mockery::stub(fn, "covr::environment_coverage", mockery::mock(structure(list(), class = "covr_coverage")))
mockery::stub(fn, "covr::percent_coverage", mockery::mock(0.0, 50.0))
mock_pkg_cov <- structure(list(pkg = "mypkg"), class = "covr_coverage")
mock_pkg_cov_fn <- mockery::mock(mock_pkg_cov)
mockery::stub(fn, "covr::package_coverage", mock_pkg_cov_fn)
mockery::stub(fn, "covr::coverage_to_list", mockery::mock(list(totalcoverage = 50.0)))
mockery::stub(fn, "compute_total_coverage", mockery::mock(list(total_cov = 0.50, percent_cov = 50.0, n_testfiles = 1L, n_no_function_tests = 1L, n_skipped_files = 0L)))
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
mock_msg <- mockery::mock(NULL, cycle = TRUE)
mockery::stub(fn, "message", mock_msg)
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
msg_calls <- mockery::mock_args(mock_msg)
all_msgs <- vapply(msg_calls, function(x) paste0(x, collapse = ""), character(1))
expect_true(any(grepl("environment_coverage produced 0%.*retrying with covr::package_coverage", all_msgs)))
mockery::expect_called(mock_detach, 2L)
mockery::expect_called(mock_pkg_cov_fn, 1)
})
test_that("package_coverage fallback: when package_coverage fails, cov stays 0% and message or fallback path exercised", {
fn <- run_covr_skip_runit_nstf
pkg_source_path <- "/fake/pkg"
pkg_name <- "mypkg"
test_pkg_data <- list(bioc_run_ut_path = NA_character_)
mock_runner <- tempfile(fileext = ".R")
writeLines(c("library(mypkg)", "1 + 1"), mock_runner)
mockery::stub(fn, "get_pkg_name", mockery::mock(pkg_name))
mockery::stub(fn, "is_runit_layout", mockery::mock(TRUE))
mockery::stub(fn, "get_runit_test_paths",
mockery::mock(list(bioc_unitTests = file.path(pkg_source_path, "inst", "unitTests"))))
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = FALSE, ...) x)
mockery::stub(fn, "get_source_test_mapping_runit_nstf",
mockery::mock(data.frame(source_file = "a.R", test_file = "test-a.R", evidence = "match", has_tests = TRUE, stringsAsFactors = FALSE)))
mockery::stub(fn, "prepare_for_bioc_runit", mockery::mock(TRUE))
mockery::stub(fn, "check_covr_skip_runit_nstf",
mockery::mock(data.frame(test_file = NA_character_, issue_type = "No tests skipped", stringsAsFactors = FALSE)))
mockery::stub(fn, "get_function_no_tests", mockery::mock(data.frame(fn = "b", stringsAsFactors = FALSE)))
mockery::stub(fn, "tidyr::drop_na", function(df) df)
mockery::stub(fn, "ls", mockery::mock(c("obj1")))
mockery::stub(fn, "asNamespace", mockery::mock(new.env(), cycle = TRUE))
mockery::stub(fn, "assign", mockery::mock(NULL, cycle = TRUE))
mockery::stub(fn, "load_package_datasets", mockery::mock(character()))
mockery::stub(fn, "loadedNamespaces", mockery::mock(c("methods")))
mockery::stub(fn, "loadNamespace", mockery::mock(NULL))
mockery::stub(fn, "detach_pkg_if_attached", mockery::mock(TRUE))
mockery::stub(fn, "pkgload::load_all", mockery::mock(invisible(NULL)))
mockery::stub(fn, "as.environment", function(name) {
if (identical(name, paste0("package:", pkg_name))) return(new.env(parent = emptyenv()))
base::as.environment(name)
})
mockery::stub(fn, "build_runit_custom_runner", mockery::mock(mock_runner))
mockery::stub(fn, "covr::environment_coverage", mockery::mock(structure(list(), class = "covr_coverage")))
mockery::stub(fn, "covr::percent_coverage", mockery::mock(0.0))
mockery::stub(fn, "readLines", function(con, ...) c("library(mypkg)", "1 + 1"))
mockery::stub(fn, "covr::package_coverage", function(...) stop("package_coverage instrumentation failed"))
mockery::stub(fn, "covr::coverage_to_list", mockery::mock(list(filecoverage = matrix(0, nrow = 1), totalcoverage = 0)))
mockery::stub(fn, "compute_total_coverage", mockery::mock(list(total_cov = 0.0, percent_cov = 0.0, n_testfiles = 1L, n_no_function_tests = 1L, n_skipped_files = 0L)))
mockery::stub(fn, "cleanup_and_return_null", function(...) NULL)
out <- testthat::capture_messages(
res <- fn(pkg_source_path = pkg_source_path, test_pkg_data = test_pkg_data)
)
expect_identical(res$res_cov$coverage$totalcoverage, 0)
expect_true(
any(grepl("package_coverage fallback failed", out, fixed = TRUE)) ||
any(grepl("environment_coverage produced 0%", out, fixed = TRUE)),
info = "package_coverage fallback path should be entered (env 0% message) and either inner error message or outer fallback"
)
})
test_that("prepare_for_bioc_runit returns invisible(TRUE)", {
fn <- prepare_for_bioc_runit
# detach_pkg_if_attached is called 4 times:
# 1. detach target package
# 3Ă— if detach_bioc_infra = TRUE
mock_detach <- mockery::mock(NULL, NULL, NULL, NULL)
mock_load_all <- mockery::mock(NULL) # pkgload::load_all
mockery::stub(fn, "detach_pkg_if_attached", mock_detach)
mockery::stub(fn, "pkgload::load_all", mock_load_all)
v <- withVisible(fn(pkg_name = "mypkg",
pkg_source_path = "/tmp/mypkg",
detach_bioc_infra = TRUE))
expect_true(v$value) # TRUE returned
expect_false(v$visible) # invisibly() applied
})
test_that("load_all called even if detaches throw; try-catch not inside but we still see error", {
fn <- prepare_for_bioc_runit
# If a detach throws, since the function doesn't try-catch around it, the error
# should propagate and load_all should not be called. We can still validate behavior.
throwing_detach <- function(...) stop("detach failure")
mock_load_all <- mockery::mock(NULL)
mockery::stub(fn, "detach_pkg_if_attached", throwing_detach)
mockery::stub(fn, "pkgload::load_all", mock_load_all)
expect_error(fn(pkg_name = "mypkg", pkg_source_path = "/tmp/mypkg"), "detach failure")
# Ensure load_all was not called due to early error
mockery::expect_called(mock_load_all, 0)
})
test_that("errors if RUnit is not available", {
fn <- check_covr_skip_runit_nstf
mock_req_ns <- mockery::mock(FALSE)
mockery::stub(fn, "requireNamespace", mock_req_ns)
expect_error(
fn(pkg_source_path = "/pkg", mapping = data.frame(test_file = character()), test_path = "/tests"),
"RUnit must be installed"
)
mockery::expect_called(mock_req_ns, 1)
args <- mockery::mock_args(mock_req_ns)
expect_identical(args[[1]][[1]], "RUnit")
expect_true(isTRUE(args[[1]][["quietly"]]))
})
test_that("cleans mapping via tidyr::drop_na when test_file contains NA", {
fn <- check_covr_skip_runit_nstf
mapping <- data.frame(test_file = c("test-a.R", NA_character_, "test-b.R"), stringsAsFactors = FALSE)
mock_req_ns <- mockery::mock(TRUE)
# drop_na should remove the NA row
mock_drop_na <- function(df, test_file) df[!is.na(df$test_file), , drop = FALSE]
# Minimal stubs to allow the function to proceed to the lapply without real side effects
mock_file_exists <- mockery::mock(TRUE, TRUE, cycle = TRUE) # two files exist
mock_search <- mockery::mock("package:stats", "package:stats", cycle = TRUE) # no RUnit attached
mock_attach <- mockery::mock(NULL, NULL, cycle = TRUE)
mock_detach <- mockery::mock(NULL, cycle = TRUE) # may or may not be called by on.exit
mock_run <- mockery::mock(structure(list(), class = "RUnitTestData"),
structure(list(), class = "RUnitTestData"),
cycle = TRUE)
mock_get_err <- mockery::mock(list(nErr = 0, nFail = 0, nDeactivated = 0),
list(nErr = 0, nFail = 0, nDeactivated = 0),
cycle = TRUE)
mockery::stub(fn, "requireNamespace", mock_req_ns)
mockery::stub(fn, "tidyr::drop_na", mock_drop_na)
mockery::stub(fn, "file.exists", mock_file_exists)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "attachNamespace", mock_attach)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "RUnit::runTestFile", mock_run)
mockery::stub(fn, "RUnit::getErrors", mock_get_err)
res <- fn(pkg_source_path = "/pkg", mapping = mapping, test_path = "/tests")
# Both tests pass -> "No tests skipped"
expect_s3_class(res, "data.frame")
expect_identical(nrow(res), 1L)
expect_true(is.na(res$test_file[1]))
expect_identical(res$issue_type[1], "No tests skipped")
})
test_that("Windows branch: Sys.setenv uses quoted R_TESTS and on.exit restores via Sys.unsetenv when originally unset", {
fn <- check_covr_skip_runit_nstf
mapping <- data.frame(test_file = "pass.R", stringsAsFactors = FALSE)
mock_req_ns <- mockery::mock(TRUE)
mock_sysinfo <- c(sysname = "windows", nodename = "PC", release = "10", version = "", machine = "x86")
mock_getenv <- mockery::mock(NA_character_)
mock_setenv <- mockery::mock(NULL, NULL)
mock_unsetenv <- mockery::mock(NULL)
mock_file_exists <- mockery::mock(TRUE)
mock_search <- mockery::mock("package:RUnit")
mock_run <- mockery::mock(structure(list(file = "pass.R"), class = "RUnitTestData"))
mock_get_err <- mockery::mock(list(nErr = 0, nFail = 0, nDeactivated = 0))
id_drop_na <- function(df, test_file) df
mockery::stub(fn, "requireNamespace", mock_req_ns)
mockery::stub(fn, "Sys.info", function() mock_sysinfo)
mockery::stub(fn, "Sys.getenv", mock_getenv)
mockery::stub(fn, "Sys.setenv", mock_setenv)
mockery::stub(fn, "Sys.unsetenv", mock_unsetenv)
mockery::stub(fn, "tidyr::drop_na", id_drop_na)
mockery::stub(fn, "file.exists", mock_file_exists)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "RUnit::runTestFile", mock_run)
mockery::stub(fn, "RUnit::getErrors", mock_get_err)
res <- fn(pkg_source_path = "/pkg", mapping = mapping, test_path = "/tests")
expect_s3_class(res, "data.frame")
expect_identical(res$issue_type[1], "No tests skipped")
set_calls <- mockery::mock_args(mock_setenv)
expect_true(
any(vapply(set_calls, function(x) identical(x, list("R_TESTS" = "")), logical(1))),
info = "Windows branch: Sys.setenv uses quoted R_TESTS = ''"
)
mockery::expect_called(mock_unsetenv, 1)
unset_args <- mockery::mock_args(mock_unsetenv)
expect_identical(unset_args[[1]], list("R_TESTS"))
})
test_that("Windows branch: Sys.setenv uses quoted R_TESTS and on.exit restores via Sys.setenv when originally set", {
fn <- check_covr_skip_runit_nstf
mapping <- data.frame(test_file = "pass.R", stringsAsFactors = FALSE)
original_value <- "original-R_TESTS-value"
mock_req_ns <- mockery::mock(TRUE)
mock_sysinfo <- c(sysname = "windows", nodename = "PC", release = "10", version = "", machine = "x86")
mock_getenv <- mockery::mock(original_value)
mock_setenv <- mockery::mock(NULL, NULL)
mock_unsetenv <- mockery::mock(NULL)
mock_file_exists <- mockery::mock(TRUE)
mock_search <- mockery::mock("package:RUnit")
mock_run <- mockery::mock(structure(list(file = "pass.R"), class = "RUnitTestData"))
mock_get_err <- mockery::mock(list(nErr = 0, nFail = 0, nDeactivated = 0))
id_drop_na <- function(df, test_file) df
mockery::stub(fn, "requireNamespace", mock_req_ns)
mockery::stub(fn, "Sys.info", function() mock_sysinfo)
mockery::stub(fn, "Sys.getenv", mock_getenv)
mockery::stub(fn, "Sys.setenv", mock_setenv)
mockery::stub(fn, "Sys.unsetenv", mock_unsetenv)
mockery::stub(fn, "tidyr::drop_na", id_drop_na)
mockery::stub(fn, "file.exists", mock_file_exists)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "RUnit::runTestFile", mock_run)
mockery::stub(fn, "RUnit::getErrors", mock_get_err)
res <- fn(pkg_source_path = "/pkg", mapping = mapping, test_path = "/tests")
expect_s3_class(res, "data.frame")
set_calls <- mockery::mock_args(mock_setenv)
expect_true(
any(vapply(set_calls, function(x) identical(x, list("R_TESTS" = "")), logical(1))),
info = "Windows branch: Sys.setenv uses quoted R_TESTS = ''"
)
expect_true(
any(vapply(set_calls, function(x) identical(x, list(R_TESTS = original_value)), logical(1))),
info = "Windows branch: on.exit restores R_TESTS to original value"
)
mockery::expect_called(mock_unsetenv, 0)
})
test_that("removes exact filename from mapping when bioc_run_ut_path provided (case-insensitive)", {
fn <- remove_run_unitTests_mapping
mapping <- data.frame(
test_file = c("run_unitTests.R", "test-foo.R", "RUN_UNITTESTS.R", "test-bar.R"),
stringsAsFactors = FALSE
)
test_pkg_data <- list(bioc_run_ut_path = "/pkg/tests/run_unitTests.R")
# Stub basename() to a specific value to assert exact-match branch is used
mock_basename <- mockery::mock("run_unitTests.R")
mockery::stub(fn, "basename", mock_basename)
res <- fn(mapping, test_pkg_data)
# Expected: exact "run_unitTests.R" removed via exact-match branch; regex also removes RUN_UNITTESTS.R
expect_true("test-foo.R" %in% res$test_file)
expect_true("test-bar.R" %in% res$test_file)
expect_false("run_unitTests.R" %in% res$test_file)
expect_false("RUN_UNITTESTS.R" %in% res$test_file)
# basename should be called once with the provided path
mockery::expect_called(mock_basename, 1)
args <- mockery::mock_args(mock_basename)
expect_identical(args[[1]][[1]], "/pkg/tests/run_unitTests.R")
})
test_that("regex fallback removes variations when bioc_run_ut_path is missing/NULL/NA", {
fn <- remove_run_unitTests_mapping
# No exact name available -> only regex path applies
mapping <- data.frame(
test_file = c("run-unitTests.R", "Run_UnitTests.R", "test-x.R", "sub/run_unitTests.R"),
stringsAsFactors = FALSE
)
# Case 1: test_pkg_data missing entirely
res1 <- fn(mapping, test_pkg_data = NULL)
expect_setequal(res1$test_file, "test-x.R") # note: regex only matches basename
# Case 2: field present but NULL
res2 <- fn(mapping, test_pkg_data = list(bioc_run_ut_path = NULL))
expect_setequal(res2$test_file, "test-x.R")
# Case 3: field NA
res3 <- fn(mapping, test_pkg_data = list(bioc_run_ut_path = NA_character_))
expect_setequal(res3$test_file, "test-x.R")
})
test_that("does not remove unrelated files; only exact filename or regex variations dropped", {
fn <- remove_run_unitTests_mapping
mapping <- data.frame(
test_file = c("test-a.R", "runUnitTest.R", "unitTests_run.R", "test-b.R"),
stringsAsFactors = FALSE
)
test_pkg_data <- list(bioc_run_ut_path = "/pkg/tests/NotRunUnitTests.R")
# basename returns a non-matching value -> exact match won't drop anything
mock_basename <- mockery::mock("NotRunUnitTests.R")
mockery::stub(fn, "basename", mock_basename)
res <- fn(mapping, test_pkg_data)
# None match the strict regex "run[_-]?unitTests\\.R$"
expect_setequal(res$test_file, c("test-a.R", "runUnitTest.R", "unitTests_run.R", "test-b.R"))
})
test_that("handles NA entries in mapping$test_file gracefully (no warnings)", {
fn <- remove_run_unitTests_mapping
mapping <- data.frame(
test_file = c(NA_character_, "test-a.R", "run_unitTests.R", NA_character_, "test-b.R"),
stringsAsFactors = FALSE
)
test_pkg_data <- list(bioc_run_ut_path = "/pkg/tests/whatever.R")
# basename stub not strictly needed but keep deterministic
mock_basename <- mockery::mock("whatever.R")
mockery::stub(fn, "basename", mock_basename)
res <- fn(mapping, test_pkg_data)
# Only run_unitTests.R is removed; NAs are retained
expect_setequal(res$test_file, c(NA_character_, "test-a.R", NA_character_, "test-b.R"))
})
test_that("exact match removal works even if mapping has different case than basename", {
fn <- remove_run_unitTests_mapping
mapping <- data.frame(
test_file = c("RUN_UNITTESTS.R", "test-a.R"),
stringsAsFactors = FALSE
)
test_pkg_data <- list(bioc_run_ut_path = "/pkg/tests/run_unitTests.R")
mock_basename <- mockery::mock("run_unitTests.R")
mockery::stub(fn, "basename", mock_basename)
res <- fn(mapping, test_pkg_data)
expect_setequal(res$test_file, "test-a.R")
})
test_that("regex removes both underscore and hyphen variants, any case", {
fn <- remove_run_unitTests_mapping
mapping <- data.frame(
test_file = c("run_unitTests.R", "run-unitTests.R", "RUN_UNITTESTS.R", "test-a.R", "test-b.R"),
stringsAsFactors = FALSE
)
res <- fn(mapping, test_pkg_data = NULL)
expect_setequal(res$test_file, c("test-a.R", "test-b.R"))
})
test_that("empty mapping returns empty data.frame (no errors)", {
fn <- remove_run_unitTests_mapping
mapping <- data.frame(test_file = character(), stringsAsFactors = FALSE)
res <- fn(mapping, test_pkg_data = NULL)
expect_s3_class(res, "data.frame")
expect_identical(nrow(res), 0L)
})
test_that("basename is consulted only when bioc_run_ut_path is usable", {
fn <- remove_run_unitTests_mapping
mapping <- data.frame(test_file = c("run_unitTests.R", "test-a.R"), stringsAsFactors = FALSE)
# Case: usable path -> basename called
mock_basename <- mockery::mock("run_unitTests.R")
mockery::stub(fn, "basename", mock_basename)
res1 <- fn(mapping, list(bioc_run_ut_path = "/pkg/tests/run_unitTests.R"))
mockery::expect_called(mock_basename, 1)
expect_setequal(res1$test_file, "test-a.R")
# Case: NA path -> basename should not be called
mock_basename2 <- mockery::mock("should-not-be-called")
mockery::stub(fn, "basename", mock_basename2)
res2 <- fn(mapping, list(bioc_run_ut_path = NA_character_))
mockery::expect_called(mock_basename2, 0)
expect_setequal(res2$test_file, c("test-a.R"))
# Case: NULL path -> basename should not be called
mock_basename3 <- mockery::mock("should-not-be-called")
mockery::stub(fn, "basename", mock_basename3)
res3 <- fn(mapping, list(bioc_run_ut_path = NULL))
mockery::expect_called(mock_basename3, 0)
expect_setequal(res3$test_file, c("test-a.R"))
})
test_that("classifies missing, error, failure, skipped, and passing files correctly", {
fn <- check_covr_skip_runit_nstf
mapping <- data.frame(
test_file = c(
"test-missing.R",
"test-error-throw.R",
"test-error-count.R",
"test-failure.R",
"test-skipped.R",
"test-pass.R",
NA_character_
),
stringsAsFactors = FALSE
)
mock_req_ns <- mockery::mock(TRUE)
# drop_na should be called and remove NA
mock_drop_na <- function(df, test_file) df[!is.na(df$test_file), , drop = FALSE]
# file.exists -> FALSE only for test-missing.R
mock_file_exists <- function(path) {
if (grepl("test-missing\\.R$", path)) return(FALSE)
TRUE
}
# Pretend RUnit is already on the search path so we don't re-attach each time
mock_search <- mockery::mock("package:RUnit", "package:RUnit", "package:RUnit",
"package:RUnit", "package:RUnit", "package:RUnit")
# runTestFile: throws for test-error-throw, otherwise returns a testdata object
mock_run <- function(absFileName, useOwnErrorHandler, testFuncRegexp) {
bn <- basename(absFileName)
if (bn == "test-error-throw.R") stop("parse/runtime error")
structure(list(file = bn), class = "RUnitTestData")
}
# getErrors: return different counts per file name
mock_get_err <- function(td) {
bn <- td$file
switch(
bn,
"test-error-count.R" = list(nErr = 1, nFail = 0, nDeactivated = 0),
"test-failure.R" = list(nErr = 0, nFail = 2, nDeactivated = 0),
"test-skipped.R" = list(nErr = 0, nFail = 0, nDeactivated = 3),
# default: passing
list(nErr = 0, nFail = 0, nDeactivated = 0)
)
}
mock_attach <- mockery::mock(NULL) # not used because search() includes RUnit
mock_detach <- mockery::mock(NULL)
mockery::stub(fn, "requireNamespace", mock_req_ns)
mockery::stub(fn, "tidyr::drop_na", mock_drop_na)
mockery::stub(fn, "file.exists", mock_file_exists)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "attachNamespace", mock_attach)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "RUnit::runTestFile", mock_run)
mockery::stub(fn, "RUnit::getErrors", mock_get_err)
res <- fn(pkg_source_path = "/pkg", mapping = mapping, test_path = "/tests")
# Expected issues (order follows mapping after drop_na)
expected <- data.frame(
test_file = c("test-missing.R", "test-error-throw.R", "test-error-count.R", "test-failure.R", "test-skipped.R"),
issue_type = c("missing", "error", "error", "failure", "skipped"),
stringsAsFactors = FALSE
)
expect_s3_class(res, "data.frame")
expect_identical(res[, c("test_file", "issue_type")], expected)
})
test_that("when all files are passing, returns 'No tests skipped' row", {
fn <- check_covr_skip_runit_nstf
mapping <- data.frame(test_file = c("t1.R", "t2.R"), stringsAsFactors = FALSE)
mock_req_ns <- mockery::mock(TRUE)
# anyNA(mapping$test_file) is FALSE -> ensure we don't call tidyr::drop_na (we make it throw if called)
throwing_drop_na <- function(...) stop("drop_na should not be called when no NA present")
mock_file_exists <- mockery::mock(TRUE, TRUE)
mock_search <- mockery::mock("package:RUnit", "package:RUnit")
mock_run <- mockery::mock(structure(list(file = "t1.R"), class = "RUnitTestData"),
structure(list(file = "t2.R"), class = "RUnitTestData"))
mock_get_err <- mockery::mock(list(nErr = 0, nFail = 0, nDeactivated = 0),
list(nErr = 0, nFail = 0, nDeactivated = 0))
mock_attach <- mockery::mock(NULL)
mock_detach <- mockery::mock(NULL)
mockery::stub(fn, "requireNamespace", mock_req_ns)
mockery::stub(fn, "tidyr::drop_na", throwing_drop_na)
mockery::stub(fn, "file.exists", mock_file_exists)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "attachNamespace", mock_attach)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "RUnit::runTestFile", mock_run)
mockery::stub(fn, "RUnit::getErrors", mock_get_err)
res <- fn(pkg_source_path = "/pkg", mapping = mapping, test_path = "/tests")
expect_s3_class(res, "data.frame")
expect_identical(nrow(res), 1L)
expect_true(is.na(res$test_file[1]))
expect_identical(res$issue_type[1], "No tests skipped")
})
test_that("attaches RUnit namespace only when not already on search path", {
fn <- check_covr_skip_runit_nstf
mapping <- data.frame(test_file = "pass.R", stringsAsFactors = FALSE)
mock_req_ns <- mockery::mock(TRUE)
# First call to search() -> no RUnit; inside on.exit check may call again, so provide two values
mock_search <- mockery::mock("package:stats", "package:RUnit")
mock_attach <- mockery::mock(NULL) # should be called once
mock_detach <- mockery::mock(NULL)
mock_file_exists <- mockery::mock(TRUE)
mock_run <- mockery::mock(structure(list(file = "pass.R"), class = "RUnitTestData"))
mock_get_err <- mockery::mock(list(nErr = 0, nFail = 0, nDeactivated = 0))
id_drop_na <- function(df, test_file) df
mockery::stub(fn, "requireNamespace", mock_req_ns)
mockery::stub(fn, "tidyr::drop_na", id_drop_na)
mockery::stub(fn, "file.exists", mock_file_exists)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "attachNamespace", mock_attach)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "RUnit::runTestFile", mock_run)
mockery::stub(fn, "RUnit::getErrors", mock_get_err)
res <- fn(pkg_source_path = "/pkg", mapping = mapping, test_path = "/tests")
expect_s3_class(res, "data.frame")
mockery::expect_called(mock_attach, 1)
})
test_that("runTestFile error path is captured as 'error' without crashing", {
fn <- check_covr_skip_runit_nstf
mapping <- data.frame(test_file = "test-error-throw.R", stringsAsFactors = FALSE)
mock_req_ns <- mockery::mock(TRUE)
id_drop_na <- function(df, test_file) df
mock_file_exists <- mockery::mock(TRUE)
mock_search <- mockery::mock("package:RUnit")
mock_attach <- mockery::mock(NULL)
mock_detach <- mockery::mock(NULL)
# Force runTestFile to throw -> tryCatch will return class "RUnitTestData-ERROR"
mock_run <- function(...) stop("boom")
# getErrors should not be called in this path
mock_get_err <- mockery::mock()
mockery::stub(fn, "requireNamespace", mock_req_ns)
mockery::stub(fn, "tidyr::drop_na", id_drop_na)
mockery::stub(fn, "file.exists", mock_file_exists)
mockery::stub(fn, "search", mock_search)
mockery::stub(fn, "attachNamespace", mock_attach)
mockery::stub(fn, "detach", mock_detach)
mockery::stub(fn, "RUnit::runTestFile", mock_run)
mockery::stub(fn, "RUnit::getErrors", mock_get_err)
res <- fn(pkg_source_path = "/pkg", mapping = mapping, test_path = "/tests")
expect_identical(nrow(res), 1L)
expect_identical(res$test_file[1], "test-error-throw.R")
expect_identical(res$issue_type[1], "error")
mockery::expect_called(mock_get_err, 0)
})
test_that("returns bioc_unitTests when testdir already exists", {
fn <- get_runit_test_paths
# Normalized testdir value
mock_normalize <- function(path, winslash = "/", mustWork = FALSE) {
# Return a consistent normalized path regardless of input
if (grepl("^/work/pkg/tests$", path)) return("/work/pkg/tests")
path
}
mock_dir_exists <- function(path) path == "/work/pkg/tests"
# Stubs
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "dir.exists", mock_dir_exists)
res <- fn(test_pkg_data = list(), testdir = "/work/pkg/tests")
expect_true("bioc_unitTests" %in% names(res))
expect_identical(res$bioc_unitTests, "/work/pkg/tests")
expect_false("fallback" %in% names(res))
})
test_that("finds package root at testdir and returns inst/unitTests if it exists", {
fn <- get_runit_test_paths
# Paths
raw_testdir <- "/work/pkg/tests"
normalized_testdir <- "/work/pkg/tests"
pkg_root <- "/work/pkg"
bioc_unit <- "/work/pkg/inst/unitTests"
mock_normalize <- function(path, winslash = "/", mustWork = FALSE) {
# Normalize testdir and pkg_root and bioc_unit deterministically
if (path == raw_testdir) return(normalized_testdir)
if (path == pkg_root) return(pkg_root)
if (path == bioc_unit) return(bioc_unit)
path
}
# testdir does NOT exist; bioc unit dir DOES
mock_dir_exists <- function(path) {
path == bioc_unit
}
# file.exists(DESCRIPTION) returns TRUE only at testdir's root (/work/pkg)
mock_file_exists <- function(path) {
path == file.path(pkg_root, "DESCRIPTION")
}
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(test_pkg_data = list(), testdir = raw_testdir)
expect_true("bioc_unitTests" %in% names(res))
expect_identical(res$bioc_unitTests, bioc_unit)
expect_false("fallback" %in% names(res))
})
test_that("finds package root at dirname(testdir) and returns inst/unitTests", {
fn <- get_runit_test_paths
# Layout:
# testdir: /work/pkg/tests/unit
# dirname(testdir): /work/pkg/tests
# dirname(dirname(testdir)): /work/pkg
raw_testdir <- "/work/pkg/tests/unit"
normalized_testdir <- raw_testdir
pkg_root <- "/work/pkg"
bioc_unit <- "/work/pkg/inst/unitTests"
mock_normalize <- function(path, winslash = "/", mustWork = FALSE) {
if (path %in% c(raw_testdir, pkg_root, bioc_unit)) return(path)
path
}
mock_dir_exists <- function(path) {
# testdir does not exist; bioc_unit exists
path == bioc_unit
}
mock_file_exists <- function(path) {
# Mark only /work/pkg as a package root
path == file.path(pkg_root, "DESCRIPTION")
}
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(test_pkg_data = list(), testdir = raw_testdir)
expect_true("bioc_unitTests" %in% names(res))
expect_identical(res$bioc_unitTests, bioc_unit)
})
test_that("finds package root at dirname(dirname(testdir)) and returns inst/unitTests", {
fn <- get_runit_test_paths
raw_testdir <- "/work/pkg/a/b"
pkg_root <- "/work/pkg"
bioc_unit <- "/work/pkg/inst/unitTests"
mock_normalize <- function(path, winslash = "/", mustWork = FALSE) path
mock_dir_exists <- function(path) path == bioc_unit
mock_file_exists <- function(path) path == file.path(pkg_root, "DESCRIPTION")
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(test_pkg_data = list(), testdir = raw_testdir)
expect_true("bioc_unitTests" %in% names(res))
expect_identical(res$bioc_unitTests, bioc_unit)
})
test_that("returns fallback when testdir doesn't exist and no package root found", {
fn <- get_runit_test_paths
raw_testdir <- "/nowhere/tests"
normalized_testdir <- "/nowhere/tests"
mock_normalize <- function(path, winslash = "/", mustWork = FALSE) normalized_testdir
mock_dir_exists <- function(path) FALSE
mock_file_exists <- function(path) FALSE
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(test_pkg_data = list(), testdir = raw_testdir)
expect_true("fallback" %in% names(res))
expect_identical(res$fallback, normalized_testdir)
expect_false("bioc_unitTests" %in% names(res))
})
test_that("returns fallback if package root found but inst/unitTests does not exist", {
fn <- get_runit_test_paths
raw_testdir <- "/work/pkg/tests"
pkg_root <- "/work/pkg"
normalized_testdir <- raw_testdir
bioc_unit <- "/work/pkg/inst/unitTests"
mock_normalize <- function(path, winslash = "/", mustWork = FALSE) path
mock_dir_exists <- function(path) FALSE # inst/unitTests not present
mock_file_exists <- function(path) path == file.path(pkg_root, "DESCRIPTION")
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(test_pkg_data = list(), testdir = raw_testdir)
expect_true("fallback" %in% names(res))
expect_identical(res$fallback, normalized_testdir)
})
test_that("handles duplicate candidate paths via unique()", {
fn <- get_runit_test_paths
# If testdir == dirname(testdir), unique() collapses duplicates.
raw_testdir <- "/flat"
# Simulate a flat structure where dirname("/flat") == "/"
mock_normalize <- function(path, winslash = "/", mustWork = FALSE) path
mock_dir_exists <- function(path) FALSE
mock_file_exists <- function(path) FALSE
mockery::stub(fn, "normalizePath", mock_normalize)
mockery::stub(fn, "dir.exists", mock_dir_exists)
mockery::stub(fn, "file.exists", mock_file_exists)
res <- fn(test_pkg_data = list(), testdir = raw_testdir)
expect_true("fallback" %in% names(res))
expect_identical(res$fallback, raw_testdir)
})
test_that("errors when no R source files are found", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/proj/pkg"
source_dir <- file.path(pkg_source_path, "R")
test_dir <- "/proj/pkg/tests"
# Stub list.files so there are NO source files
mock_list_files <- function(path, pattern, full.names, recursive) {
if (path == source_dir) return(character()) # no .R under R/
if (path == test_dir) return(character(0)) # doesn't matter
character(0)
}
mockery::stub(fn, "list.files", mock_list_files)
# Use a simple pattern (or regexp = NA) to avoid brittle matching
expect_error(
fn(pkg_source_path = pkg_source_path, test_dir = test_dir),
regexp = "No R files found under:"
)
})
test_that("warns when no .R test files are found and maps NA tests", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/proj/pkg"
source_dir <- file.path(pkg_source_path, "R")
test_dir <- "/proj/pkg/tests"
src_files <- file.path(source_dir, c("alpha.R", "beta.R"))
mock_list_files <- function(path, pattern, full.names, recursive) {
if (path == source_dir) return(src_files) # two sources
if (path == test_dir) return(character()) # no tests -> warning
character()
}
# No test content will be read because length(test_files) == 0
mock_readLines <- function(con, warn = FALSE) stop("readLines should not be called")
mockery::stub(fn, "list.files", mock_list_files)
mockery::stub(fn, "readLines", mock_readLines)
expect_warning(
res <- fn(pkg_source_path = pkg_source_path, test_dir = test_dir),
regexp = "No R test files found under:"
)
expect_s3_class(res, "data.frame")
expect_identical(nrow(res), 2L)
expect_identical(res$source_file, c("alpha.R", "beta.R"))
expect_true(all(is.na(res$test_file)))
expect_true(all(is.na(res$evidence)))
expect_identical(res$has_tests, c(FALSE, FALSE))
})
test_that("filename-based mapping: tokenized, case-insensitive, picks first match", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/pkg"
source_dir <- file.path(pkg_source_path, "R")
test_dir <- "/pkg/tests"
src_files <- file.path(source_dir, c("foo.R", "bar.R"))
test_files <- file.path(test_dir, c("test-foo.R", "ZZZ_foo_extra.R", "TEST-bar.R"))
mock_list_files <- function(path, pattern, full.names, recursive) {
if (path == source_dir) return(src_files)
if (path == test_dir) return(test_files)
character()
}
# No content-based checks needed
mock_readLines <- function(con, warn = FALSE) character()
mockery::stub(fn, "list.files", mock_list_files)
mockery::stub(fn, "readLines", mock_readLines)
res <- fn(pkg_source_path = pkg_source_path, test_dir = test_dir)
expect_s3_class(res, "data.frame")
expect_identical(res$source_file, c("foo.R", "bar.R"))
expect_identical(res$test_file, c("test-foo.R", "TEST-bar.R")) # first match wins
expect_identical(res$evidence, c("filename_match", "filename_match"))
expect_identical(res$has_tests, c(TRUE, TRUE))
})
test_that("content-based mapping via RUnit test function names when filename matching fails", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/p"
source_dir <- file.path(pkg_source_path, "R")
test_dir <- "/p/tests"
# One source 'widget.R'; one test 'test-something.R'
src_files <- file.path(source_dir, "widget.R")
test_files <- file.path(test_dir, "test-something.R")
mock_list_files <- function(path, pattern, full.names, recursive) {
if (path == source_dir) return(src_files)
if (path == test_dir) return(test_files)
character()
}
# Provide a FUNCTION DEF in source (ensures symbol extraction works)
# Provide an RUnit test function line that contains the symbol
mock_readLines <- function(con, warn = FALSE) {
f <- as.character(con)
if (identical(basename(f), "widget.R")) {
return(c("widget <- function(x) { x }"))
}
if (identical(basename(f), "test-something.R")) {
return(c("test_widget <- function() {",
" # assertions here",
"}"))
}
character()
}
mockery::stub(fn, "list.files", mock_list_files)
mockery::stub(fn, "readLines", mock_readLines)
res <- fn(pkg_source_path = pkg_source_path, test_dir = test_dir)
expect_identical(res$source_file, "widget.R")
expect_identical(res$test_file, "test-something.R")
expect_identical(res$evidence, "content_match")
expect_true(res$has_tests)
})
test_that("content-based mapping uses symbols from function defs (avoid setGeneric parsing)", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/root"
source_dir <- file.path(pkg_source_path, "R")
test_dir <- "/root/tests"
src_files <- file.path(source_dir, c("generics.R", "funcs.R"))
test_files <- file.path(test_dir, c("t-generic.R", "t-func.R"))
mock_list_files <- function(path, pattern, full.names, recursive) {
if (path == source_dir) return(src_files)
if (path == test_dir) return(test_files)
character()
}
# IMPORTANT: Because the function's setGeneric grep uses fixed=TRUE with an escaped quote,
# it's safer to provide FUNCTION DEFS in sources so symbol extraction surely works.
mock_readLines <- function(con, warn = FALSE) {
f <- as.character(con)
switch(
basename(f),
"generics.R" = c(
"doStuff <- function(...) TRUE" # symbol: doStuff
),
"funcs.R" = c(
"my_func <- function(a, b) { a + b }",
"other <- function() 1"
),
"t-generic.R" = c(
"test_doStuff <- function() { TRUE }" # detects 'doStuff' via RUnit name
),
"t-func.R" = c(
"test_my_func <- function() { TRUE }"
),
character()
)
}
mockery::stub(fn, "list.files", mock_list_files)
mockery::stub(fn, "readLines", mock_readLines)
res <- fn(pkg_source_path = pkg_source_path, test_dir = test_dir)
expect_identical(res$source_file, c("generics.R", "funcs.R"))
expect_identical(res$test_file, c("t-generic.R", NA))
expect_identical(res$evidence, c("content_match", NA))
expect_identical(res$has_tests, c(TRUE, FALSE))
})
test_that("short symbol (<= 2 chars) matches via filename tokens", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/a"
source_dir <- file.path(pkg_source_path, "R")
test_dir <- "/a/tests"
src_files <- file.path(source_dir, c("t.R", "x1.R"))
test_files <- file.path(test_dir, c("test-t.R", "we-test-x1.R"))
mock_list_files <- function(path, pattern, full.names, recursive) {
if (path == source_dir) return(src_files)
if (path == test_dir) return(test_files)
character()
}
mock_readLines <- function(con, warn = FALSE) character()
mockery::stub(fn, "list.files", mock_list_files)
mockery::stub(fn, "readLines", mock_readLines)
res <- fn(pkg_source_path = pkg_source_path, test_dir = test_dir)
expect_identical(res$source_file, c("t.R", "x1.R"))
expect_identical(res$test_file, c("test-t.R", "we-test-x1.R"))
expect_identical(res$evidence, c("filename_match", "filename_match"))
expect_identical(res$has_tests, c(TRUE, TRUE))
})
test_that("returns NA mapping for source with no filename or content evidence", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/no"
source_dir <- file.path(pkg_source_path, "R")
test_dir <- "/no/tests"
src_files <- file.path(source_dir, "lonely.R")
test_files <- file.path(test_dir, c("test-a.R", "test-b.R")) # no relevant content
mock_list_files <- function(path, pattern, full.names, recursive) {
if (path == source_dir) return(src_files)
if (path == test_dir) return(test_files)
character()
}
mock_readLines <- function(con, warn = FALSE) {
f <- as.character(con)
if (identical(basename(f), "lonely.R")) return(c("lonely <- function() 1"))
if (basename(f) %in% c("test-a.R", "test-b.R")) return(c("test_other <- function() 1"))
character()
}
mockery::stub(fn, "list.files", mock_list_files)
mockery::stub(fn, "readLines", mock_readLines)
res <- fn(pkg_source_path = pkg_source_path, test_dir = test_dir)
expect_identical(res$source_file, "lonely.R")
expect_true(is.na(res$test_file))
expect_true(is.na(res$evidence))
expect_false(res$has_tests)
})
test_that("detect_runit_test_prefix detects runit.<name>.R pattern", {
files <- c(
"/fake/dir/runit.myfun.R",
"/fake/dir/runit.other_test.R"
)
expect_equal(detect_runit_test_prefix(files), "runit")
})
test_that("detect_runit_test_prefix detects Test.<name>.R pattern", {
files <- c(
"/fake/dir/Test.myFun.R",
"/fake/dir/Test.Other.R"
)
expect_equal(detect_runit_test_prefix(files), "Test")
})
test_that("detect_runit_test_prefix detects test_<name>.R pattern (underscore)", {
files <- c(
"/path/to/test_myFunc.R",
"/path/to/test_otherThing.R"
)
expect_equal(detect_runit_test_prefix(files), "test")
})
test_that("detect_runit_test_prefix detects test.<name>.R pattern (dot)", {
files <- c(
"/path/test.myFunc.R",
"/path/test.thing_more.R"
)
expect_equal(detect_runit_test_prefix(files), "test")
})
test_that("detect_runit_test_prefix returns first detected prefix among many", {
files <- c(
"/fake/zzz/NOT_A_TEST.R",
"/fake/dir/runit.someFun.R", # should win immediately
"/fake/dir/Test.foo.R" # never reached
)
expect_equal(detect_runit_test_prefix(files), "runit")
})
test_that("detect_runit_test_prefix falls back to default 'test' when nothing matches", {
files <- c(
"alpha.R",
"beta.R",
"not_a_test_file.txt"
)
expect_equal(detect_runit_test_prefix(files), "test")
})
test_that("short symbol triggers filename token match via get_source_test_mapping_runit_nstf", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/fake/pkg"
test_dir <- "/fake/tests"
src_files <- c("/fake/pkg/R/x.R")
test_files <- c("/fake/tests/test_x.R")
# ---- CORRECT list.files STUB (dispatch on path) ----
mockery::stub(fn, "list.files", function(path, pattern, full.names, recursive) {
if (grepl("/R$", path)) {
return(src_files)
} else {
return(test_files)
}
})
# extract_symbols returns the symbol being searched
mockery::stub(fn, "extract_symbols", function(...) "x")
# readLines must return NON-empty or function returns FALSE early
mockery::stub(fn, "readLines", function(...) c("dummy line"))
# Tokenizer: filename tokens = c("x"), matches
mockery::stub(fn, "tokenize_stem", function(stem) c("x"))
# ---- RUN ----
mapping <- fn(pkg_source_path, test_dir)
# ---- ASSERTIONS ----
expect_equal(mapping$test_file, "test_x.R")
expect_equal(mapping$evidence, "filename_match") # correct Pass 1 match
expect_true(mapping$has_tests)
})
test_that("long symbol triggers filename token match via get_source_test_mapping_runit_nstf", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/fake/pkg"
test_dir <- "/fake/tests"
src_files <- "/fake/pkg/R/alpha.R"
test_files <- "/fake/tests/test_alpha.R"
# CORRECT list.files dispatcher
mockery::stub(fn, "list.files", function(path, pattern, full.names, recursive) {
if (grepl("/R$", path)) src_files else test_files
})
mockery::stub(fn, "extract_symbols", function(...) "alpha")
mockery::stub(fn, "readLines", function(...) c("ignored"))
mockery::stub(fn, "tokenize_stem", function(stem) c("alpha"))
mapping <- fn(pkg_source_path, test_dir)
expect_equal(mapping$test_file, "test_alpha.R")
expect_equal(mapping$evidence, "filename_match")
expect_true(mapping$has_tests)
})
test_that("test_that description triggers content_match in get_source_test_mapping_runit_nstf", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/fake/pkg"
test_dir <- "/fake/tests"
src_files <- "/fake/pkg/R/compute.R"
test_files <- "/fake/tests/test_misc.R"
mockery::stub(fn, "list.files", function(path, pattern, full.names, recursive) {
if (grepl("/R$", path)) src_files else test_files
})
mockery::stub(fn, "extract_symbols", function(...) "compute")
# Force description match
mockery::stub(fn, "readLines", function(...) c(
'test_that("checks compute functionality", {',
" expect_true(TRUE)",
"})"
))
# Force filename mismatch → Pass 1 fails → Pass 2 content match
mockery::stub(fn, "tokenize_stem", function(stem) c("nothing"))
mapping <- fn(pkg_source_path, test_dir)
expect_equal(mapping$test_file, "test_misc.R")
expect_equal(mapping$evidence, "content_match")
expect_true(mapping$has_tests)
})
test_that("RUnit-style test_<symbol> triggers content_match in get_source_test_mapping_runit_nstf", {
fn <- get_source_test_mapping_runit_nstf
pkg_source_path <- "/fake/pkg"
test_dir <- "/fake/tests"
src_files <- "/fake/pkg/R/compute.R"
test_files <- "/fake/tests/test_compute.R"
mockery::stub(fn, "list.files", function(path, pattern, full.names, recursive) {
if (grepl("/R$", path)) src_files else test_files
})
mockery::stub(fn, "extract_symbols", function(...) "compute")
mockery::stub(fn, "readLines", function(...) c(
"test_compute <- function() {",
" checkTrue(TRUE)",
"}"
))
# No filename match
mockery::stub(fn, "tokenize_stem", function(stem) c("unrelated"))
mapping <- fn(pkg_source_path, test_dir)
expect_equal(mapping$test_file, "test_compute.R")
expect_equal(mapping$evidence, "filename_match")
expect_true(mapping$has_tests)
})
test_that("build_runit_custom_runner returns path and writes correct content for prefix runit", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
out <- fn(tests)
expect_identical(out, mock_runner)
expect_true(any(grepl("RUnit::runTestFile", written_lines)))
expect_true(any(grepl("requireNamespace.*RUnit", written_lines)))
expect_true(any(grepl('testFuncRegexp = "\\^runit', written_lines)))
})
test_that("build_runit_custom_runner uses runit regex when prefix is runit", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests)
run_line <- written_lines[grepl("runTestFile", written_lines)]
expect_true(any(grepl('testFuncRegexp = "\\^runit\\[\\.\\]\\|\\^test\\.\\+"', run_line)))
})
test_that("build_runit_custom_runner uses Test regex when prefix is Test", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/Test.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "Test")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests)
run_line <- written_lines[grepl("runTestFile", written_lines)]
expect_true(any(grepl('testFuncRegexp = "\\^Test\\[\\.\\]\\|\\^test\\.\\+"', run_line)))
})
test_that("build_runit_custom_runner uses default test regex when prefix is neither runit nor Test", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/test_foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "test")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests)
run_line <- written_lines[grepl("runTestFile", written_lines)]
expect_true(any(grepl('testFuncRegexp = "\\^test\\.\\+"', run_line)))
})
test_that("build_runit_custom_runner includes library line when pkg_name is provided", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests, pkg_name = "mypkg")
expect_true(any(grepl('library\\(package = "mypkg"', written_lines)))
})
test_that("build_runit_custom_runner omits library line when pkg_name is NULL", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests, pkg_name = NULL)
expect_false(any(grepl('library\\(package = ', written_lines)))
})
test_that("build_runit_custom_runner omits library line when pkg_name is empty string", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests, pkg_name = "")
expect_false(any(grepl('library\\(package = ', written_lines)))
})
test_that("build_runit_custom_runner includes wd_lines when pkg_root exists", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
pkg_root <- "/fake/pkg"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
mockery::stub(fn, "dir.exists", function(x) x == pkg_root)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests, pkg_root = pkg_root)
expect_true(any(grepl("owd <- getwd\\(\\)", written_lines)))
expect_true(any(grepl("on.exit\\(setwd\\(owd\\)", written_lines)))
expect_true(any(grepl('setwd\\(', written_lines)))
})
test_that("build_runit_custom_runner omits wd_lines when pkg_root is NULL", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests, pkg_root = NULL)
expect_false(any(grepl("owd <- getwd\\(\\)", written_lines)))
expect_false(any(grepl("setwd\\(", written_lines)))
})
test_that("build_runit_custom_runner omits wd_lines when dir.exists(pkg_root) is FALSE", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.foo.R")
pkg_root <- "/nonexistent/pkg"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
mockery::stub(fn, "dir.exists", function(x) FALSE)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests, pkg_root = pkg_root)
expect_false(any(grepl("owd <- getwd\\(\\)", written_lines)))
expect_false(any(grepl("setwd\\(", written_lines)))
})
test_that("build_runit_custom_runner writes one runTestFile line per test path", {
fn <- build_runit_custom_runner
tests <- c("/fake/pkg/inst/unitTests/runit.a.R", "/fake/pkg/inst/unitTests/runit.b.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(tests)
run_lines <- written_lines[grepl("runTestFile", written_lines)]
expect_length(run_lines, 2L)
expect_true(any(grepl("runit.a.R", run_lines)))
expect_true(any(grepl("runit.b.R", run_lines)))
})
test_that("build_runit_runTests_runner returns path and writes correct content for prefix runit", {
fn <- build_runit_runTests_runner
pkg_name <- "mypkg"
test_files <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
out <- fn(pkg_name, test_files)
expect_identical(out, mock_runner)
expect_true(any(grepl("RUnit::runTestFile", written_lines)))
expect_true(any(grepl("requireNamespace.*RUnit", written_lines)))
expect_true(any(grepl('library\\(package = "mypkg"', written_lines)))
expect_true(any(grepl('testFuncRegexp = "\\^runit', written_lines)))
})
test_that("build_runit_runTests_runner uses runit regex when prefix is runit", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("mypkg", test_files)
run_line <- written_lines[grepl("runTestFile", written_lines)]
expect_true(any(grepl('testFuncRegexp = "\\^runit\\[\\.\\]\\|\\^test\\.\\+"', run_line)))
})
test_that("build_runit_runTests_runner uses Test regex when prefix is Test", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/Test.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "Test")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("mypkg", test_files)
run_line <- written_lines[grepl("runTestFile", written_lines)]
expect_true(any(grepl('testFuncRegexp = "\\^Test\\[\\.\\]\\|\\^test\\.\\+"', run_line)))
})
test_that("build_runit_runTests_runner uses default test regex when prefix is neither runit nor Test", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/test_foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "test")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("mypkg", test_files)
run_line <- written_lines[grepl("runTestFile", written_lines)]
expect_true(any(grepl('testFuncRegexp = "\\^test\\.\\+"', run_line)))
})
test_that("build_runit_runTests_runner always includes library line", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("fBasics", test_files)
expect_true(any(grepl('library\\(package = "fBasics"', written_lines)))
})
test_that("build_runit_runTests_runner includes wd_lines when pkg_root exists", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/runit.foo.R")
pkg_root <- "/fake/pkg"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
mockery::stub(fn, "dir.exists", function(x) x == pkg_root)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("mypkg", test_files, pkg_root = pkg_root)
expect_true(any(grepl("owd <- getwd\\(\\)", written_lines)))
expect_true(any(grepl("on.exit\\(setwd\\(owd\\)", written_lines)))
expect_true(any(grepl('setwd\\(', written_lines)))
})
test_that("build_runit_runTests_runner omits wd_lines when pkg_root is NULL", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/runit.foo.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("mypkg", test_files, pkg_root = NULL)
expect_false(any(grepl("owd <- getwd\\(\\)", written_lines)))
expect_false(any(grepl("setwd\\(", written_lines)))
})
test_that("build_runit_runTests_runner omits wd_lines when dir.exists(pkg_root) is FALSE", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/runit.foo.R")
pkg_root <- "/nonexistent/pkg"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
mockery::stub(fn, "dir.exists", function(x) FALSE)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("mypkg", test_files, pkg_root = pkg_root)
expect_false(any(grepl("owd <- getwd\\(\\)", written_lines)))
expect_false(any(grepl("setwd\\(", written_lines)))
})
test_that("build_runit_runTests_runner writes one runTestFile line per test path", {
fn <- build_runit_runTests_runner
test_files <- c("/fake/pkg/inst/unitTests/runit.a.R", "/fake/pkg/inst/unitTests/runit.b.R")
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
mockery::stub(fn, "detect_runit_test_prefix", function(...) "runit")
mockery::stub(fn, "normalizePath", function(x, winslash = "/", mustWork = TRUE) x)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn("mypkg", test_files)
run_lines <- written_lines[grepl("runTestFile", written_lines)]
expect_length(run_lines, 2L)
expect_true(any(grepl("runit.a.R", run_lines)))
expect_true(any(grepl("runit.b.R", run_lines)))
})
test_that("build_doRUnit_wrapper returns runner path and writes correct content", {
fn <- build_doRUnit_wrapper
doRUnit_path <- "/fake/pkg/tests/doRUnit.R"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
out <- fn(doRUnit_path)
expect_identical(out, mock_runner)
expect_true(any(grepl("owd <- getwd\\(\\)", written_lines)))
expect_true(any(grepl("on.exit\\(setwd\\(owd\\)", written_lines)))
expect_true(any(grepl('setwd\\("/fake/pkg/tests"\\)', written_lines)))
expect_true(any(grepl('source\\("/fake/pkg/tests/doRUnit.R"\\)', written_lines)))
})
test_that("build_doRUnit_wrapper uses dirname of doRUnit_path for setwd", {
fn <- build_doRUnit_wrapper
doRUnit_path <- "/some/nested/tests/dir/doRUnit.R"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(doRUnit_path)
expect_true(any(grepl('setwd\\("/some/nested/tests/dir"\\)', written_lines)))
})
test_that("build_doRUnit_wrapper sources doRUnit_path exactly", {
fn <- build_doRUnit_wrapper
doRUnit_path <- "/path/to/doRUnit.R"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(doRUnit_path)
expect_true(any(grepl('source\\("/path/to/doRUnit.R"\\)', written_lines)))
})
test_that("build_doRUnit_wrapper writes exactly four lines", {
fn <- build_doRUnit_wrapper
doRUnit_path <- "/fake/tests/doRUnit.R"
mock_runner <- tempfile(fileext = ".R")
mockery::stub(fn, "tempfile", function(fileext = "") mock_runner)
written_lines <- NULL
mockery::stub(fn, "writeLines", function(text, con, ...) {
written_lines <<- text
base::writeLines(text, con)
})
fn(doRUnit_path)
expect_length(written_lines, 4L)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.