在 testthat 中包含变量修改的跟踪

trace that includes variable modification within testthat

我有两个函数,其中一个函数根据参数以半递归方式调用另一个函数。

f1 <- function(use_f2 = FALSE){
  if (use_f2) {
    f2()
  }
}

f2 <- function(){
  f1(use_f2 = FALSE)
}

我想根据参数跟踪每个函数被调用的次数,然后使用 testthat.

将其作为单元测试的一部分

我可以跟踪使用自定义环境进行了多少调用,trace(请参阅 here for what I did previously), as shown in a previous SO question

function_counts <- new.env()
function_counts$f1 <- function_counts$f2 <- 0

trace(f1, tracer = quote(function_counts$f1 <- function_counts$f1 + 1), print = FALSE)
trace(f2, tracer = quote(function_counts$f2 <- function_counts$f2 + 1), print = FALSE)

f1()
function_counts$f1
function_counts$f2

这很好用,直到我添加 testthat 环境的复杂性。

如果我把

count_env <- new.env()

count_env$f1 <- 0

trace(f1, tracer = quote(count_env$f1 <<- count_env$f1 + 1), print = FALSE)

test_that 块的外部或内部,然后是 运行 devtools::test()ctrl-shift-t rstudio中,在特殊环境下测试,我会得到count_env not found。我意识到这是 tracetestthat 环境之间的所有相互作用,但我无法破译它。

我也试过使 count_env 对象成为包本身的未导出对象,但这似乎也没有用。

This repo 有一个包含这两个函数的最小包和一个 testthat 测试目录来玩这个。

任何关于从这里去哪里的帮助都会很棒。

事实证明,答案是使用 local 变量,以及在对 [=11 的调用中定义的 local 函数=].

.f1 <- .f2 <- 0

trace(f1, tracer = function() {.f1 <<- .f1 + 1}, print = FALSE)
trace(f2, tracer = function() {.f2 <<- .f2 + 1}, print = FALSE)

test_that("f1 FALSE", {
  f1()
  expect_equal(1, .f1)
  expect_equal(0, .f2)
})

感谢 Steph Locke 指出使用匿名函数的示例以及初始拉取请求。