testthat
testthat copied to clipboard
Assignment in `expect_no_warning()` does not work if a warning was thrown
expect_no_warning() seems to behave somewhat inconsistent to the rest of the family (e.g. compared to expect_warning()): Assignment inside the body fails if a warning was thrown.
There was a similar discussion in #998 where this was deemed a bug.
Note the second try, variable b: it's the only case where assignment does not work, in all other cases it works.
library(testthat)
foo_warning <- function() {
warning("a warning")
5
}
foo <- function() {
5
}
expect_warning(a <- foo_warning())
a
#> [1] 5
expect_no_warning(b <- foo_warning())
#> Error: Expected `b <- foo_warning()` to run without any warnings.
#> ℹ Actually got a <simpleWarning> with text:
#> a warning
b
#> Error: Objekt 'b' nicht gefunden
expect_warning(c <- foo())
#> Error: `c <- foo()` did not produce any warnings.
c
#> [1] 5
expect_no_warning(d <- foo())
d
#> [1] 5
Created on 2024-10-04 with reprex v2.1.1
When rendering the reprex with the expect_condition() and expect_no_condition(), I get similar results:
library(testthat)
foo_warning <- function() {
warning("a warning")
5
}
foo <- function() {
5
}
expect_condition(a <- foo_warning())
a
#> Error: Objekt 'a' nicht gefunden
expect_no_condition(b <- foo_warning())
#> Error: Expected `b <- foo_warning()` to run without any conditions.
#> ℹ Actually got a <simpleWarning> with text:
#> a warning
b
#> Error: Objekt 'b' nicht gefunden
expect_condition(c <- foo())
#> Error: `c <- foo()` did not throw an condition.
c
#> [1] 5
expect_no_condition(d <- foo())
d
#> [1] 5
Created on 2024-10-04 with reprex v2.1.1
Slightly simpler reprex:
library(testthat)
expect_warning(a <- 1)
#> Error: `a <- 1` did not produce any warnings.
a
#> [1] 1
expect_no_warning({warning("x"); b <- 1})
#> Error: Expected `{ ... }` to run without any warnings.
#> ℹ Actually got a <simpleWarning> with text:
#> x
b
#> Error: object 'b' not found
Created on 2024-11-05 with reprex v2.1.0
But:
library(testthat)
expect_no_warning({b <- 1; warning("x")})
#> Error: Expected `{ ... }` to run without any warnings.
#> ℹ Actually got a <simpleWarning> with text:
#> x
b
#> [1] 1
i.e. the expectation fails as soon as the warning is detected, and no further code is run.
Looks like we need to apply the same logic in cnd_matcher() to the capture() function inside expect_no_. i.e. use act <- quasi_capture(enquo(object), NULL, matcher) and then inspect act$cap.