6

我正在开发一个 R 包,我需要一些帮助来编写 R 测试函数,这些函数旨在检查是否在 C 端代码上抛出了正确的警告,然后在 R 端捕获。让我给你一些关于我正在做什么的背景:

  1. 我写的大部分内容都是在 C 端完成的。此外,我在 C 中有一个 if 语句类型的宏,它允许编码器以字符串的形式将警告传递给 R。基本前提是 if(statement_true) pass_warning_to_R("Warning string to pass")。我想做的是通过编写一个使用 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)
    

这是我正在使用的方法,到目前为止,我什至无法通过尝试使 toString(war) 和“我期待/测试的警告”相同来执行 if 语句事物。再加上这种方法非常草率且不可靠,这让我相信有更好的方法。那么,有没有更好的方法来做到这一点?

4

3 回答 3

4

除了实际捕获警告之外,您还需要注意警告消息已被翻译:

library(devtools)
with_envvar(c(LANG = "en"), log(-1))
# In log(-1) : NaNs produced
with_envvar(c(LANG = "de"), log(-1))
# In log(-1) : NaNs wurden erzeugt
with_envvar(c(LANG = "fr"), log(-1))
# In log(-1) : production de NaN
with_envvar(c(LANG = "ko"), log(-1))
# In log(-1) : NaN이 생성되었습니다

因此,如果您在测试中执行此操作,请确保设置LANG环境变量以确保消息不会因运行它的计算机而异。

于 2013-04-20T14:27:35.407 回答
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")
})

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

bad_input <- function(...) {
    w <- simpleWarning(...)
    class(w) <- c("bad_input", class(w))
    w
}

像这样使用warning(bad_input("your input is bad"))并产生输出

fun <- function() {
    warning("oops")
    warning(bad_input("your input is bad"))
    "DONE"
}        

喜欢

>     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
于 2013-04-19T21:33:55.040 回答
0

查看 testthat::expect_warnings()

于 2021-09-03T01:01:50.417 回答