通过比较字符串测试R中的警告(最好的主意?)

Dec*_*ave 6 warnings r

我正在研究一个R包,我需要一些帮助来编写R测试函数,这些函数用于检查是否在C端代码上抛出正确的警告然后在R端捕获.让我给你一些关于我正在做的工作的背景:

  1. 我写的大部分内容都是在C方面完成的.另外,我在C中有一个if语句类型的宏,允许编码器以字符串的形式向R传递警告.基本前提是if(statement_true)pass_warning_to_R("要传递的警告字符串").我想要做的是测试是否在通过编写使用tryCatch块的R文件期望/需要它们时抛出这些警告.
  2. 到目前为止,我写了类似的东西:

    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)
    
    Run Code Online (Sandbox Code Playgroud)

这是我正在使用的方法,到目前为止,我甚至无法通过尝试获取toString(war)和"警告我期望/测试"来获得if语句.事情.除此之外,这种方法非常草率和不可靠,这使我相信有更好的方法.那么,有没有更好的方法来做到这一点?

Mar*_*gan 4

通常带有警告,您希望允许评估继续;tryCatch用于停止评估。因此,请使用withCallingHandlers警告处理程序来执行您想要的操作,然后调用“muffleWarning”重新启动。可以使用以下命令提取错误/警告消息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")
})
Run Code Online (Sandbox Code Playgroud)

由于您正在编写自己的包,因此创建可以以更可靠的方式识别的警告是有意义的,例如,以下返回可在 中使用的条件warning,但具有可使用的类“bad_input”在withCallingHandlers

bad_input <- function(...) {
    w <- simpleWarning(...)
    class(w) <- c("bad_input", class(w))
    w
}
Run Code Online (Sandbox Code Playgroud)

类似使用warning(bad_input("your input is bad"))并产生输出

fun <- function() {
    warning("oops")
    warning(bad_input("your input is bad"))
    "DONE"
}        
Run Code Online (Sandbox Code Playgroud)

喜欢

>     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
Run Code Online (Sandbox Code Playgroud)