test_that("variants save different values", { expect_snapshot(r_version(), variant = r_version()) }) test_that("can snapshot output", { foo <- function() cat("y") expect_snapshot_output(foo()) expect_snapshot_output(foo()) expect_snapshot_output(foo()) expect_snapshot_output(foo()) }) test_that("can snapshot everything", { f <- function() { print("1") message("2") warning("3") stop("4") } expect_snapshot(f(), error = TRUE) }) test_that("empty lines are preserved", { f <- function() { cat("1\n\n") message("2\n") warning("3\n") stop("4\n\n") } expect_snapshot(f(), error = TRUE) }) test_that("line-endings fixed before comparison", { x <- "a\n\rb" expect_snapshot(cat(x)) }) test_that("multiple outputs of same type are collapsed", { expect_snapshot({ x <- 1 y <- 1 { message("a") message("b") } { warning("a") warning("b") } }) }) test_that("can scrub output/messages/warnings/errors", { secret <- function() { print("secret") message("secret") warning("secret") stop("secret") } redact <- function(x) gsub("secret", "", x) expect_snapshot(secret(), transform = redact, error = TRUE) # Or with an inline fun expect_snapshot(print("secret"), transform = \(x) gsub("secret", "****", x)) }) test_that("always checks error status", { expect_error(expect_snapshot(stop("!"), error = FALSE)) expect_snapshot_failure(expect_snapshot(print("!"), error = TRUE)) }) test_that("snapshots of failures fail", { expect_snapshot_failure(expect_snapshot(fail())) }) test_that("can capture error/warning messages", { expect_snapshot_error(stop("This is an error")) expect_snapshot_warning(warning("This is a warning")) }) test_that("snapshot captures deprecations", { foo <- function() { lifecycle::deprecate_warn("1.0.0", "foo()") } expect_snapshot(foo()) expect_snapshot_warning(foo()) expect_snapshot_warning(foo(), class = "lifecycle_warning_deprecated") }) test_that("can check error/warning classes", { expect_snapshot(expect_snapshot_error(1), error = TRUE) expect_snapshot(expect_snapshot_error(1, class = "myerror"), error = TRUE) expect_snapshot(expect_snapshot_warning(1), error = TRUE) expect_snapshot(expect_snapshot_warning(1, class = "mywarning"), error = TRUE) }) test_that("snapshot handles multi-line input", { expect_snapshot({ 1 + 2 3 + 4 "this is a comment" }) }) test_that("snapshot captures output if visible", { f_visible <- function() "x" f_invisible <- function() invisible("x") expect_snapshot(f_visible()) expect_snapshot(f_invisible()) }) test_that("captures custom classes", { f <- function() { inform("Hello", class = "testthat_greeting") warn("Goodbye", class = "testthat_farewell") abort("Eeek!", class = "testthat_scream") } expect_snapshot(f(), error = TRUE) }) test_that("even with multiple lines", { expect_snapshot_output(cat("a\nb\nc")) expect_snapshot_output(cat("a\nb\nc\n")) }) test_that("`expect_snapshot()` does not inject", { expect_snapshot({ x <- quote(!!foo) expect_equal(x, call("!", call("!", quote(foo)))) }) }) test_that("full condition message is printed with rlang", { expect_snapshot(error = TRUE, { foo <- error_cnd("foo", message = "Title parent.") abort("Title.", parent = foo) }) }) test_that("can print with and without condition classes", { f <- function() { message("foo") warning("bar") stop("baz") } expect_snapshot(error = TRUE, cnd_class = TRUE, f()) expect_snapshot(error = TRUE, cnd_class = FALSE, f()) }) test_that("errors and warnings are folded", { f <- function() { warning("foo") stop("bar") } expect_snapshot(error = TRUE, f()) }) # I don't know how to test this automatically; wrapping it in another # snapshot doesn't capture the behaviour I expected, presumably due to the # way that errors bubble up # test_that("errors in snapshots behave like regular errors", { # f <- function() g() # g <- function() h() # h <- function() abort("!") # # expect_snapshot(f()) # expect_snapshot(1 + 1) # }) test_that("hint is informative", { local_mocked_bindings(in_check_reporter = function() FALSE) withr::local_envvar(GITHUB_ACTIONS = "false", TESTTHAT_WD = NA) expect_snapshot(snapshot_hint("bar.R", reset_output = FALSE)) }) test_that("hint includes path when WD is different", { local_mocked_bindings(in_check_reporter = function() FALSE) withr::local_envvar(TESTTHAT_WD = "..") hint <- snapshot_hint("bar.R", reset_output = FALSE) # Can't use snapshot here because its hint will get the wrong path expect_match( hint, 'snapshot_accept("bar.R", "testthat")', fixed = TRUE, all = FALSE ) }) test_that("expect_snapshot requires a non-empty test label", { local_description_set() local_on_cran(FALSE) test_that("", { expect_error(expect_snapshot(1 + 1)) }) pass() # quiet message about this test being empty }) test_that("expect_snapshot validates its inputs", { expect_snapshot(error = TRUE, { expect_snapshot(1 + 1, cran = "yes") expect_snapshot(1 + 1, error = "yes") expect_snapshot(1 + 1, cnd_class = "yes") }) }) test_that("expect_snapshot_output validates its inputs", { expect_snapshot(error = TRUE, { expect_snapshot_output(cat("test"), cran = "yes") }) }) test_that("expect_snapshot_error validates its inputs", { expect_snapshot(error = TRUE, { expect_snapshot_error(stop("!"), class = 123) expect_snapshot_error(stop("!"), cran = "yes") }) }) test_that("expect_snapshot_warning validates its inputs", { expect_snapshot(error = TRUE, { expect_snapshot_warning(warning("!"), class = 123) expect_snapshot_warning(warning("!"), cran = "yes") }) }) test_that("on CRAN, snapshots generate skip at end of test", { local_on_cran(TRUE) expectations <- capture_expectations(test_that("", { expect_snapshot(1 + 1) expect_true(TRUE) })) expect_length(expectations, 2) expect_s3_class(expectations[[1]], "expectation_success") expect_s3_class(expectations[[2]], "expectation_skip") })