11

What's the best way to handle calls that generate a warning but then also return a value?

e.g.

> require(testthat)
> expect_warning(log(-1))
> expect_equal(log(-1), NaN)
Warning message:
In log(-1) : NaNs produced

I want to write the test such that the call to log(-1) should both (a) generate a warning and (b) return the value NaN. The way above works, but seeing the "Warning message:" at the bottom might confuse people. Should I suppress warnings temporarily?

Stephen Eglen
  • 591
  • 2
  • 15

2 Answers2

14
require(testthat)
expect_warning(val <- log(-1))
expect_true(is.nan(val))
BrodieG
  • 51,669
  • 9
  • 93
  • 146
  • 1
    I know the last line does work, but it feels slightly cleaner as `expect_true(is.nan(val))`. `expect_equal(val, NaN)` passing relies upon `all.equal(NaN, NaN)` being true, which is a dubious design decision. – Richie Cotton Jan 02 '14 at 15:46
  • 1
    @RichieCotton or maybe `expect_identical(val, NaN)` which seems a little safer – hadley Jan 02 '14 at 19:44
0

One great way to deal with value, message and warning is to use the adverb purrr::quietly like that:

## R/foo.r
foo <- function() {
  message("This is a message")
  warning("This is a warning")
  "This is a result"
}
test_that("foo works", {
  qfoo <- purrr::quietly(foo)
  qfoo_call <- qfoo()
  expect_equal(qfoo_call$result, "This is a result")
  expect_equal(qfoo_call$message, "This is a message")
  expect_equal(qfoo_call$warning, "This is a warning")
})

See this question to see all the benefits of this approach.

pietrodito
  • 1,783
  • 15
  • 24