Test for exact string in testthat

2019-07-17 04:03发布

I'd like to test that one of my functions gives a particular message (or warning, or error).

good <- function() message("Hello")
bad <- function() message("Hello!!!!!")

I'd like the first expectation to succeed and the second to fail.

library(testthat)
expect_message(good(), "Hello", fixed=TRUE)
expect_message(bad(), "Hello", fixed=TRUE)

Unfortunately, both of them pass at the moment.

For clarification: this is meant to be a minimal example, rather than the exact messages I'm testing against. If possible I'd like to avoid adding complexity (and probably errors) to my test scripts by needing to come up with an appropriate regex for every new message I want to test.

标签: r testthat
2条回答
祖国的老花朵
2楼-- · 2019-07-17 04:41

Your rexeg matches "Hello" in both cases, thus it doesn't return an error. You''ll need to set up word boundaries \\b from both sides. It would suffice if you wouldn't use punctuations/spaces in here. In order to ditch them too, you'll need to add [^\\s ^\\w]

library(testthat)
expect_message(good(), "\\b^Hello[^\\s ^\\w]\\b")
expect_message(bad(), "\\b^Hello[^\\s ^\\w]\\b")    
## Error: bad() does not match '\b^Hello[^\s ^\w]\b'. Actual value: "Hello!!!!!\n"
查看更多
仙女界的扛把子
3楼-- · 2019-07-17 04:53

You can use ^ and $ anchors to indicate that that the string must begin and end with your pattern.

expect_message(good(), "^Hello\\n$")
expect_message(bad(), "^Hello\\n$")
#Error: bad() does not match '^Hello\n$'. Actual value: "Hello!!!!!\n"

The \\n is needed to match the new line that message adds.

For warnings it's a little simpler, since there's no newline:

expect_warning(warning("Hello"), "^Hello$")

For errors it's a little harder:

good_stop <- function() stop("Hello")
expect_error(good_stop(), "^Error in good_stop\\(\\) : Hello\n$")

Note that any regex metacharacters, i.e. . \ | ( ) [ { ^ $ * + ?, will need to be escaped.


Alternatively, borrowing from Mr. Flick's answer here, you could convert the message into a string and then use expect_true, expect_identical, etc.

messageToText <- function(expr) {
  con <- textConnection("messages", "w")
  sink(con, type="message")
  eval(expr)
  sink(NULL, type="message")
  close(con)
  messages
}

expect_identical(messageToText(good()), "Hello")
expect_identical(messageToText(bad()), "Hello") 
#Error: messageToText(bad()) is not identical to "Hello". Differences: 1 string mismatch
查看更多
登录 后发表回答