How to test for a message and an error message simultaneously in R testthat?
Asked Answered
P

2

9

I'm looking to unit test a function that produces a connection. It outputs a message that contains the connection details during execution.

I want to test the following:

  1. The message appears as expected (expect_message(fn(),"blah"))
  2. There is no error (expect_error(fn(),NA))
  3. Object created is a specific class (expect_is(fn(),"PostgreSQLConnection"))

I could do res<-fn() and then do the expect_is() from it, but how can I perform tests on both the message and the (lack of an) error whilst calling the function.

Ideally, I'd like to evaluate all three simultaneously and in such a way I could then safely close the connection afterwards.

library(testthat)
fn<-function(){
  message("blah")
  obj<-"blah"
  class(obj)<-c("PostgreSQLConnection",class(obj))
  return(obj)
}

expect_message(fn(),"blah")
expect_error(fn(),NA)
expect_is(fn(),"PostgreSQLConnection")

PS The expect_message and expect_error functions use functions like throws_error which may or may not be deprecated- the docs are a little confusing on that point. ?throws_error

Plagioclase answered 31/3, 2016 at 11:58 Comment(0)
P
6

Using testthat::evaluate_promise you can get the various aspects of a function call, store the results, and then test for the items you need to test.

In this case the code becomes:

library(testthat)

fn<-function(){
  message("blah")
  obj<-"blah"
  class(obj)<-c("PostgreSQLConnection",class(obj))
  return(obj)
}

res<-evaluate_promise(fn())

expect_equal(res$messages,"blah")
expect_equal(res$warnings,character())
expect_s3_class(res$result,"PostgreSQLConnection")
Plagioclase answered 31/3, 2016 at 12:6 Comment(0)
F
3

You can also chain expect_message and expect_error:

fn1 <- function(){
  message("blah")
  obj<-"blah"
  stop("someError")
}
expect_error(expect_message(fn1()), "someError")
# or
expect_message(expect_error(fn1(), "someError"))
Font answered 15/6, 2020 at 9:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.