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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ This release mostly focusses on an overhaul of how testthat works with condition

* New `exp_signal()` function is a condition signaller that
implements the testthat protocol (signal with `stop()` if the
expectation is broken, with a `continue_test` restart).
expectation is broken, with a `muffle_expectation` restart).

* Existence of restarts is first checked before invocation. This makes
it possible to signal warnings or messages with a different
Expand Down
6 changes: 2 additions & 4 deletions R/expect-self-test.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ capture_success_failure <- function(expr) {
expectation_failure = function(cnd) {
last_failure <<- cnd
n_failure <<- n_failure + 1
# Don't bubble up to any other handlers
invokeRestart("continue_test")
invokeRestart("muffle_expectation")
},
expectation_success = function(cnd) {
n_success <<- n_success + 1
# Don't bubble up to any other handlers
invokeRestart("continue_test")
invokeRestart("muffle_expectation")
}
)

Expand Down
4 changes: 2 additions & 2 deletions R/expectation.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#' optionally subsequence) elements should describe what was actually seen.
#' @inheritParams fail
#' @return An expectation object from either `succeed()` or `fail()`.
#' with a `continue_test` restart.
#' with a `muffle_expectation` restart.
#' @seealso [exp_signal()]
#' @keywords internal
#' @export
Expand Down Expand Up @@ -104,7 +104,7 @@ exp_signal <- function(exp) {
} else {
signalCondition(exp)
},
continue_test = function(e) NULL
muffle_expectation = function(e) NULL
)

invisible(exp)
Expand Down
7 changes: 6 additions & 1 deletion R/snapshot.R
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,12 @@ expect_snapshot_ <- function(
if (error) {
fail(msg, trace = state$error[["trace"]])
} else {
cnd_signal(state$error)
# This might be a failed expectation, so we need to make sure
# that we can muffle it
withRestarts(
cnd_signal(state$error),
muffle_expectation = function() NULL
)
}
Comment on lines -134 to 140
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know very little about testthat internals, but is this supposed to be exp_signal(state$error)?

It feels like there should only be 1 place in testthat where you set up withRestarts(muffle_expectation =), and then other places should reuse that helper. Otherwise you end up with weird ad hoc calls like this one.

I'm not totally sure what state$error is though, and if calling exp_signal() on it is appropriate

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

state$error could be any error, not just an expectation.

I agree that there shouldn't be multiple places where we have to add this restart, but the condition handling in snapshots is complicated and I know I've got it wrong before, so I don't really want to touch that code. (I just looked back at the blame and it seems like literally every line of that if statement required a different PR to get right 😭). (But I'll take one more look)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I tried again, and it got me into an even weirder state. So I don't think it's worth 100% reasoning through again, and this should be the only place where we need it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds fine

return()
}
Expand Down
3 changes: 1 addition & 2 deletions R/test-that.R
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ test_code <- function(code, env, reporter = NULL, skip_on_empty = TRUE) {
handle_expectation <- function(e) {
the$test_expectations <- the$test_expectations + 1L
register_expectation(e, 7)
# Don't bubble up to any other handlers
invokeRestart("continue_test")
invokeRestart("muffle_expectation")
}
handle_warning <- function(e) {
# When options(warn) < 0, warnings are expected to be ignored.
Expand Down
2 changes: 1 addition & 1 deletion man/expect.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tests/testthat/_snaps/snapshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@
Error:
! Expected `print("!")` to throw a error.

# snapshots of failures fail

Code
expect_snapshot(fail())
Condition
Error:
! Failure has been forced

# can capture error/warning messages

This is an error
Expand Down
4 changes: 4 additions & 0 deletions tests/testthat/test-snapshot.R
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ test_that("always checks error status", {
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"))
Expand Down