我正在为R软件包编写一些测试,并希望R CMD check
验证函数是否显示某些输入的正确警告。但我无法弄清楚如何捕获警告输出,以便我可以测试它。
所以,如果我有这样的功能:
throwsWarning<-function(x){
if(x>0){
warning('Argument "x" is greater than zero, results may be incorrect')
}
# do something useful ...
}
我想在我的测试文件中添加一些内容,如:
warningOutput <-try( throwsWarning(1))
if (warningOutput!='Argument "x" is greater than zero, results may be incorrect'){
stop('function "throwsWarning" did not produce correct warning when x>0')
}
到目前为止,我已经通过更改options
找到了可能的部分解决方案,以便将警告视为错误,并将trycatch
块视为周围环境。也考虑了last.warning
的测试值,但如果没有抛出警告(将测试之前的值),这似乎很危险。似乎必须有一个简单的方法来做到这一点,我错过了?
答案 0 :(得分:6)
testthat package有一个expect_warning
和gives_warning
功能可以使用。
从示例中,您可以执行以下操作:
R> library(testthat)
R> expect_that(warning("this is a warning"), gives_warning("is a"))
## This does not raise an error, but:
R> expect_that(warning("this is a warning"), gives_warning("nope"))
Error: warning("this is a warning") does not match 'nope'. Actual value:
this is a warning
因此,gives_warning
是正则表达式,它与应该发出的警告相匹配。如果正则表达式不匹配(或者没有抛出警告),则会引发红色标记。
同样,使用较短的expect_warning
:
R> expect_warning(warning("this is a warning"), "is a")
答案 1 :(得分:2)
如果您正在编写自己的包,那么通过抛出(并捕获)特定类型的错误或警告来利用R的条件系统可能是有意义的。所以
myFun <- function(x) {
if (any(is.na(x))) {
w <- simpleWarning("'x' contains NA values")
class(w) <- c("HasNA", class(w))
warning(w)
}
if (any(x < 0))
warning("'x' contains values less than 0")
x
}
然后在您的测试中,例如,使用library(RUnit)
,使用tryCatch
并选择您感兴趣的测试条件,即类HasNA
的警告:< / p>
test_myFun_NAwarning <- function() {
warnOccurred <- FALSE
tryCatch(myFun(1:5), HasNA = function(w) warnOcccurred <<- TRUE)
checkTrue(!warnOccurred)
tryCatch(myFun(-(1:5)), HasNA = function(w) warnOcccurred <<- TRUE)
checkTrue(!warnOccurred)
tryCatch(myFun(c(1:5, NA)), HasNA = function(w) warnOccurred <<- TRUE)
checkTrue(warnOccurred)
}
导致
> test_myFun_NAwarning()
[1] TRUE
Warning message:
In myFun(-(1:5)) : 'x' contains values less than 0
表明tryCatch只捕获您感兴趣的特定警告,并且这样做的方式不依赖于匹配字符串的文本。也许你有一个辅助函数.warn
来为你的包发出所有警告。有关其他详细信息,请参阅?withCallingHandlers
; withCallingHandlers
和muffleRestart
是警告发生后如何处理持续评估,而不是停止tryCatch
的方式。