diff --git a/NEWS.md b/NEWS.md index 30ed7293f..983e3356f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # testthat (development version) +* `set_state_inspector()` gains `tolerance` argument and ignores minor FP differences by default (@mcol, #2237). * `expect_vector()` fails, instead of erroring, if `object` is not a vector (@plietar, #2224). * New `vignette("mocking")` explains mocking in detail (#1265). * New `vignette("challenging-functions")` provides an index to other documentation organised by testing challenges (#1265). diff --git a/R/test-state.R b/R/test-state.R index ff1320314..6fb878515 100644 --- a/R/test-state.R +++ b/R/test-state.R @@ -42,7 +42,8 @@ #' @export #' @param callback Either a zero-argument function that returns an object #' capturing global state that you're interested in, or `NULL`. -set_state_inspector <- function(callback) { +#' @inheritParams waldo::compare +set_state_inspector <- function(callback, tolerance = testthat_tolerance()) { if ( !is.null(callback) && !(is.function(callback) && length(formals(callback)) == 0) @@ -51,11 +52,18 @@ set_state_inspector <- function(callback) { } the$state_inspector <- callback + the$state_inspector_tolerance <- tolerance invisible() } testthat_state_condition <- function(before, after, call) { - diffs <- waldo_compare(before, after, x_arg = "before", y_arg = "after") + diffs <- waldo_compare( + before, + after, + x_arg = "before", + y_arg = "after", + tolerance = the$state_inspector_tolerance + ) if (length(diffs) == 0) { return(NULL) diff --git a/man/set_state_inspector.Rd b/man/set_state_inspector.Rd index 08ae0740b..61e52f1b1 100644 --- a/man/set_state_inspector.Rd +++ b/man/set_state_inspector.Rd @@ -4,11 +4,24 @@ \alias{set_state_inspector} \title{Check for global state changes} \usage{ -set_state_inspector(callback) +set_state_inspector(callback, tolerance = testthat_tolerance()) } \arguments{ \item{callback}{Either a zero-argument function that returns an object capturing global state that you're interested in, or \code{NULL}.} + +\item{tolerance}{If non-\code{NULL}, used as threshold for ignoring small +floating point difference when comparing numeric vectors. Using any +non-\code{NULL} value will cause integer and double vectors to be compared +based on their values, not their types, and will ignore the difference +between \code{NaN} and \code{NA_real_}. + +It uses the same algorithm as \code{\link[=all.equal]{all.equal()}}, i.e., first we generate +\code{x_diff} and \code{y_diff} by subsetting \code{x} and \code{y} to look only locations +with differences. Then we check that +\code{mean(abs(x_diff - y_diff)) / mean(abs(y_diff))} (or just +\code{mean(abs(x_diff - y_diff))} if \code{y_diff} is small) is less than +\code{tolerance}.} } \description{ One of the most pernicious challenges to debug is when a test runs fine