Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to continue function when error is thrown in withCallingHandlers in R

I'm writing a test case for an R function that tests whether an error is being thrown and caught correctly at a certain point in the function and I'm having some trouble getting the test to continue when an error is thrown during execution in withCallingHandlers(...). I'm using this approach:

counter <- 0
withCallingHandlers({
testingFunction(df0, df1)
testingFunction(df2, df3)
testingFunction(df4, df5)

}, warning=function(war){
    print(paste(war$message))
}, error=function(err){
    print(paste(err$message))
    if(err$message == paste("The function should throw this error message",
                              "at the right time.")){
        counter <<- counter + 1
    }

})

stopifnot(counter == 2)

The problem I'm running into is that the script is exiting after the first error is (successfully) caught and I'm not sure how to handle the error so that after it's caught, withCallingHandlers simply continues onto the next part of its execution. I understand that it has something to do with a restart object but I'm not sure how to use them correctly. Does anyone know how I could manipulate the above code so that execution of withCallingHandlers(...) continues even when an error is caught?

like image 446
Decave Avatar asked May 21 '13 22:05

Decave


2 Answers

For a test function

fun1 = function() stop("something specific went wrong")

the idiom

obs = tryCatch(fun1(), error=conditionMessage)
exp = "something specific went wrong"
stopifnot(identical(exp, obs))

is maybe a tidier version of Ryan's, and like his avoids the unfortunate case where an error is thrown but for the wrong reason. The same paradigm works for warnings

fun2 = function(x) as.integer(x)
obs = tryCatch(fun2(c("1", "two")), warning=conditionMessage)
stopifnot(identical("NAs introduced by coercion", obs))

and to check for 'clean' evaluation

obs = tryCatch(fun2(c("1", "2")), warning=conditionMessage, 
          error=conditionMessage)
stopifnot(identical(1:2, obs))

This is ok, provided Sys.getlocale() is "C" or another encoding that doesn't change the translation of the condition messages.

like image 78
Martin Morgan Avatar answered Oct 12 '22 23:10

Martin Morgan


You can just wrap each call to testingFunction with a call to tryCatch.:

counter <- 0
testForExpectedError <- function(expr) {
    tryCatch(expr, error=function(err) {
        print(paste(err$message))
        if(err$message == paste("The function should throw this error message",
                                "at the right time.")){
            counter <<- counter + 1
        }
    })
}

testForExpectedError(testingFunction(df0, df1))
testForExpectedError(testingFunction(df2, df3))
testForExpectedError(testingFunction(df4, df5))

stopifnot(counter == 2)
like image 42
Ryan C. Thompson Avatar answered Oct 13 '22 01:10

Ryan C. Thompson