Testing warnings in R by comparing strings (best idea?)

前端 未结 2 1375
情书的邮戳
情书的邮戳 2021-01-12 19:24

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

相关标签:
2条回答
  • 2021-01-12 20:00

    Apart from actually capturing the warning, you need to be aware that warning messages are translated:

    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이 생성되었습니다
    

    So if you're doing this inside a test, make sure you set the LANG environmental variable to ensure that the message doesn't vary according to what computer it's run on.

    0 讨论(0)
  • 2021-01-12 20:13

    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
    
    0 讨论(0)
提交回复
热议问题