Nothing
#' Skip a test for various reasons
#'
#' @description
#' `skip_if()` and `skip_if_not()` allow you to skip tests, immediately
#' concluding a [test_that()] block without executing any further expectations.
#' This allows you to skip a test without failure, if for some reason it
#' can't be run (e.g. it depends on the feature of a specific operating system,
#' or it requires a specific version of a package).
#'
#' See `vignette("skipping")` for more details.
#'
#' @section Helpers:
#'
#' * `skip_if_not_installed("pkg")` skips tests if package "pkg" is not
#' installed or cannot be loaded (using `requireNamespace()`). Generally,
#' you can assume that suggested packages are installed, and you do not
#' need to check for them specifically, unless they are particularly
#' difficult to install.
#'
#' * `skip_if_offline()` skips if an internet connection is not available
#' (using [curl::nslookup()]) or if the test is run on CRAN. Requires
#' \{curl\} to be installed and included in the dependencies of your package.
#'
#' * `skip_if_translated("msg")` skips tests if the "msg" is translated.
#'
#' * `skip_on_bioc()` skips on Bioconductor (using the `IS_BIOC_BUILD_MACHINE`
#' env var).
#'
#' * `skip_on_cran()` skips on CRAN (using the `NOT_CRAN` env var set by
#' devtools and friends). `local_on_cran()` gives you the ability to
#' easily simulate what will happen on CRAN.
#'
#' * `skip_on_covr()` skips when covr is running (using the `R_COVR` env var).
#'
#' * `skip_on_ci()` skips on continuous integration systems like GitHub Actions,
#' travis, and appveyor (using the `CI` env var).
#'
#' * `skip_on_os()` skips on the specified operating system(s) ("windows",
#' "mac", "linux", or "solaris").
#'
#' @param message A message describing why the test was skipped.
#' @param host A string with a hostname to lookup
#' @export
#' @examples
#' if (FALSE) skip("Some Important Requirement is not available")
#'
#' test_that("skip example", {
#' expect_equal(1, 1L) # this expectation runs
#' skip('skip')
#' expect_equal(1, 2) # this one skipped
#' expect_equal(1, 3) # this one is also skipped
#' })
skip <- function(message = "Skipping") {
message <- paste0(message, collapse = "\n")
cond <- structure(
list(message = paste0("Reason: ", message)),
class = c("skip", "condition")
)
stop(cond)
}
# Called automatically if the test contains no expectations
skip_empty <- function() {
cond <- structure(
list(message = "Reason: empty test"),
class = c("skip_empty", "skip", "condition")
)
stop(cond)
}
#' @export
#' @rdname skip
#' @param condition Boolean condition to check. `skip_if_not()` will skip if
#' `FALSE`, `skip_if()` will skip if `TRUE`.
skip_if_not <- function(condition, message = NULL) {
if (is.null(message)) {
message <- paste0(deparse1(substitute(condition)), " is not TRUE")
}
if (!isTRUE(condition)) {
skip(message)
} else {
invisible()
}
}
#' @export
#' @rdname skip
skip_if <- function(condition, message = NULL) {
if (is.null(message)) {
message <- paste0(deparse1(substitute(condition)), " is TRUE")
}
if (isTRUE(condition)) {
skip(message)
} else {
invisible()
}
}
#' @export
#' @param pkg Name of package to check for
#' @param minimum_version Minimum required version for the package
#' @rdname skip
skip_if_not_installed <- function(pkg, minimum_version = NULL) {
# most common case: it's not installed
tryCatch(
find.package(pkg),
error = function(e) skip(paste0("{", pkg, "} is not installed"))
)
# rarer: it's installed, but fails to load
if (!requireNamespace(pkg, quietly = TRUE)) {
skip(paste0("{", pkg, "} cannot be loaded"))
}
if (!is.null(minimum_version)) {
installed_version <- package_version(pkg)
if (installed_version < minimum_version) {
skip(paste0(
"Installed ",
pkg,
" is version ",
installed_version,
"; ",
"but ",
minimum_version,
" is required"
))
}
}
invisible()
}
package_version <- function(x) {
utils::packageVersion(x)
}
#' @export
#' @param spec A version specification like '>= 4.1.0' denoting that this test
#' should only be run on R versions 4.1.0 and later.
#' @rdname skip
skip_unless_r <- function(spec) {
check_string(spec)
parts <- unlist(strsplit(spec, " ", fixed = TRUE))
if (length(parts) != 2L) {
cli::cli_abort(
"{.arg spec} must be an valid version specification, like {.str >= 4.0.0}, not {.str {spec}}."
)
}
comparator <- match.fun(parts[1L])
required_version <- numeric_version(parts[2L])
current_version <- getRversion()
skip_if_not(
comparator(current_version, required_version),
sprintf(
"Current R version (%s) does not satisfy requirement (%s %s)",
current_version,
parts[1L],
required_version
)
)
}
# for mocking
getRversion <- NULL
#' @export
#' @rdname skip
skip_if_offline <- function(host = "captive.apple.com") {
skip_on_cran()
check_installed("curl")
skip_if_not(has_internet(host), "offline")
}
has_internet <- function(host) {
!is.null(curl::nslookup(host, error = FALSE))
}
#' @export
#' @rdname skip
skip_on_cran <- function() {
skip_if(on_cran(), "On CRAN")
}
#' @export
#' @rdname skip
#' @param on_cran Pretend we're on CRAN (`TRUE`) or not (`FALSE`).
#' @param frame Calling frame to tie change to; expect use only.
local_on_cran <- function(on_cran = TRUE, frame = caller_env()) {
check_bool(on_cran)
withr::local_envvar(NOT_CRAN = tolower(!on_cran), .local_envir = frame)
}
# Assert that we're not on CRAN, but don't override the user's setting
local_assume_not_on_cran <- function(frame = caller_env()) {
if (Sys.getenv("NOT_CRAN") != "") {
return()
}
withr::local_envvar("NOT_CRAN" = "true", .local_envir = frame)
}
#' @export
#' @param os Character vector of one or more operating systems to skip on.
#' Supported values are `"windows"`, `"mac"`, `"linux"`, `"solaris"`,
#' and `"emscripten"`.
#' @param arch Character vector of one or more architectures to skip on.
#' Common values include `"i386"` (32 bit), `"x86_64"` (64 bit), and
#' `"aarch64"` (M1 mac). Supplying `arch` makes the test stricter; i.e. both
#' `os` and `arch` must match in order for the test to be skipped.
#' @rdname skip
skip_on_os <- function(os, arch = NULL) {
os <- match.arg(
os,
choices = c("windows", "mac", "linux", "solaris", "emscripten"),
several.ok = TRUE
)
msg <- switch(
system_os(),
windows = if ("windows" %in% os) "On Windows",
darwin = if ("mac" %in% os) "On Mac",
linux = if ("linux" %in% os) "On Linux",
sunos = if ("solaris" %in% os) "On Solaris",
emscripten = if ("emscripten" %in% os) "On Emscripten"
)
if (!is.null(arch) && !is.null(msg)) {
if (!is.character(arch)) {
cli::cli_abort("{.arg arch} must be a character vector.")
}
if (system_arch() %in% arch) {
msg <- paste(msg, system_arch())
} else {
msg <- NULL
}
}
if (is.null(msg)) {
invisible(TRUE)
} else {
skip(msg)
}
}
system_os <- function() tolower(Sys.info()[["sysname"]])
system_arch <- function() R.version$arch
#' @export
#' @rdname skip
skip_on_ci <- function() {
skip_if(on_ci(), "On CI")
}
#' @export
#' @rdname skip
skip_on_covr <- function() {
skip_if(in_covr(), "On covr")
}
#' @export
#' @rdname skip
skip_on_bioc <- function() {
skip_if(on_bioc(), "On Bioconductor")
}
#' @export
#' @param msgid R message identifier used to check for translation: the default
#' uses a message included in most translation packs. See the complete list in
#' [`R-base.pot`](https://github.com/wch/r-source/blob/master/src/library/base/po/R-base.pot).
#' @rdname skip
skip_if_translated <- function(msgid = "'%s' not found") {
skip_if(
gettext(msgid) != msgid,
paste0("\"", msgid, "\" is translated")
)
}
gettext <- function(msgid, domain = "R") {
base::gettext(msgid, domain = domain)
}
#' Superseded skip functions
#'
#' @description
#' `r lifecycle::badge("superseded")`
#'
#' * `skip_on_travis()` and `skip_on_appveyor()` have been superseded by
#' [skip_on_ci()].
#'
#' @export
#' @keywords internal
skip_on_travis <- function() {
skip_if(env_var_is_true("TRAVIS"), "On Travis")
}
#' @export
#' @rdname skip_on_travis
skip_on_appveyor <- function() {
skip_if(env_var_is_true("APPVEYOR"), "On Appveyor")
}
# helpers -----------------------------------------------------------------
on_ci <- function() {
env_var_is_true("CI")
}
in_covr <- function() {
env_var_is_true("R_COVR")
}
on_bioc <- function() {
env_var_is_true("IS_BIOC_BUILD_MACHINE")
}
on_cran <- function() {
env <- Sys.getenv("NOT_CRAN")
if (identical(env, "")) {
!interactive()
} else {
!isTRUE(as.logical(env))
}
}
env_var_is_true <- function(x) {
isTRUE(as.logical(Sys.getenv(x, "false")))
}
env_var_is_false <- function(x) {
isFALSE(as.logical(Sys.getenv(x, "true")))
}
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.