I'm working on an R package and I need some help writing R test functions that are meant to check whether the correct warning is being thrown on C-side code and then caught on the R side. Let me give you some background on what I'm working on exactly:
So far I've written something similar to this:
counter <- 0
tryCatch({
function_im_testing()
}, warning = function(war) {
# Check if warning is as expected and if so increment counter
if(toString(war)=="The warning I'm expecting/testing for"){
print(toString(war))
counter <- counter + 1
}
}, error = function(err) {
print(toString(err))
}, finally = {
print("Leaving tryCatch")
})
# Stop if the 3 warnings we expected aren't present
stopifnot(counter == 3)
This is the method I'm using and, so far, I haven't even been able to get the if statement to execute by trying to get toString(war) and "Warning I'm expecting/testing for" to be the same thing. This, in addition with the fact that this method is pretty sloppy and unreliable, leads me to believe that there's a better way. So, is there a better approach to doing this?
Usually with warnings you'd like to allow evaluation to continue; tryCatch
is used to stop evaluation. So instead use withCallingHandlers
with a handler for warnings that does what you want, and then invokes the 'muffleWarning' restart. The message of an error / warning can be extracted with conditionMessage
counter <- 0L
withCallingHandlers({
function_im_testing()
}, warning = function(w) {
if (conditionMessage(w) == "The warning I'm expecting/testing for")
counter <<- counter + 1L
invokeRestart("muffleWarning")
})
Since you're writing your own package, it makes sense to create warnings that can be identified in a more robust way, e.g., the following returns a condition that can be used in warning
, but that has a class 'bad_input' that can be used in withCallingHandlers
.
bad_input <- function(...) {
w <- simpleWarning(...)
class(w) <- c("bad_input", class(w))
w
}
To be used like warning(bad_input("your input is bad"))
and producing output with
fun <- function() {
warning("oops")
warning(bad_input("your input is bad"))
"DONE"
}
like
> fun()
[1] "DONE"
Warning messages:
1: In fun() : oops
2: your input is bad
> counter <- 0L
> withCallingHandlers(fun(), bad_input = function(w) {
+ counter <<- counter + 1L
+ invokeRestart("muffleWarning")
+ })
[1] "DONE"
Warning message:
In fun() : oops
> counter
[1] 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With