R中的tryCatch与testthat期望值

5

I have the following function:

fun = function(expr) {
  mc = match.call()

  env = as.environment(within(
    list(),
    expr = eval(mc$expr)
  ))

  return(env)
}

该函数在tryCatch()中被调用,以便优雅地处理expr中的任何错误条件。

它可以很好地处理标准错误条件:

tryCatch({
  fun({
    stop('error')
  })
}, error = function(e) {
  message('error happened')
})

# error happened

然而,它无法捕获testthat的预期错误(这在我的特定用例中是首选):

library(testthat)

tryCatch({
  fun({
    expect_true(FALSE)
  })
}, error = function(e) {
  message('expectation not met')
})

# Error: FALSE isn't true.

或者更简单地说:
library(testthat)

tryCatch({
  expect_true(FALSE)
}, error = function(e) {
  message('expectation not met')
})

# Error: FALSE isn't true.

期望错误未被捕获。
在从R 3.2.2升级到R 3.3.0后出现了这个问题 - 即在R 3.2.2中完全捕获了期望错误。
是否有方法可以使tryCatch()在R 3.3.0中捕获testthat期望?

expect_xxx 函数调用 expect,而 expect 又调用 withRestarts。我不确定它的确切作用,但似乎这是你遇到问题的根源。 - Dason
@Dason 是的,我注意到了。我不确定这是否一直是这种情况(例如,在我使用 R 3.2.2 开发代码时)。理想情况下,我希望在不进行猴子补丁的情况下规避其当前行为。 - oddHypothesis
1个回答

10
我设置了调试器在expect()上,然后逐行通过几行代码(为简洁编辑输出),并查看被发出信号的条件的类。
> debug(expect)
> xx = expect_true(FALSE)
...
Browse[2]> n
debug: exp <- as.expectation(exp, ..., srcref = srcref)
Browse[2]>
...
Browse[2]> class(exp)
[1] "expectation_failure" "expectation"         "condition"   
Browse[2]> Q
> undebug(expect)       

因此,它不是“错误”类的条件,可以明确捕获。
> tryCatch(expect_true(FALSE), expectation_failure=conditionMessage)
[1] "FALSE isn't true.\n"

您还可以捕获expectation类。

如果这是重要的,重新启动允许您继续。

result <- withCallingHandlers({
    expect_true(FALSE)
    expect_true(!TRUE)
    expect_true("this sentence")
}, expectation_failure=function(e) {
    cat(conditionMessage(e))
    invokeRestart("continue_test")
})

输出

FALSE isn't true.
!TRUE isn't true.
"this sentence" isn't true.
> result
[1] FALSE

你也可以捕获或处理成功。

> tryCatch(expect_true(TRUE), expectation_success=class)
[1] "expectation_success" "expectation"         "condition"  

谢谢!从tryCatch()的文档中我并没有清楚地了解到可以为特定类别指定处理程序。这是我R技巧列表中要添加的另一个技巧。 - oddHypothesis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接