Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 使用TestThis解决环境问题_R_Testthat_Nse - Fatal编程技术网

R 使用TestThis解决环境问题

R 使用TestThis解决环境问题,r,testthat,nse,R,Testthat,Nse,我对当前在单元测试中表现出来的环境有一些微妙的问题。我的基本结构是这样的 我有一个main函数main,它有许多参数 wrapper是一个包装函数(众多函数中的一个),它只与main helper是所有包装函数都使用的中间helper函数 我使用eval和match.call()在包装器和主函数之间平滑移动我现在的问题是,当我逐行运行测试时,测试工作正常,但不使用test\u that() 这是一个显示问题的MWE。如果手动单步执行测试中的行,则测试通过。但是,对整个test_()进行评估(

我对当前在单元测试中表现出来的环境有一些微妙的问题。我的基本结构是这样的

  • 我有一个main函数
    main
    ,它有许多参数
  • wrapper
    是一个包装函数(众多函数中的一个),它只与
    main
  • helper
    是所有包装函数都使用的中间helper函数
我使用
eval
match.call()
在包装器和主函数之间平滑移动我现在的问题是,当我逐行运行测试时,测试工作正常,但不使用
test\u that()

这是一个显示问题的MWE。如果手动单步执行测试中的行,则测试通过。但是,对整个
test_()进行评估(
chunk)测试失败,因为找不到其中一个参数

library(testthat)

wrapper <- function(a, b) {
  fun_call <- as.list(match.call())
  ret <- helper(fun_call)
  return(ret)
}

helper <- function(fun_call) {
  fun_call[[1]] <- quote(main)
  fun_call <- as.call(fun_call)
  fun_eval <- eval(as.call(fun_call))
  return(fun_eval)
}

main <- function(a, b, c = 1) {
  ret <- list(a = a, b = b, c = c)
  return(ret)
}

test_that("Test", {
  a <- 1
  b <- 2
  x <- wrapper(a = a, b = b)
  y <- list(a = 1, b = 2, c = 1)
  expect_equal(x, y)
})
库(testthat)

wrapper您希望在父环境而不是本地函数环境中评估调用。将助手更改为

helper <- function(fun_call) {
  fun_call[[1]] <- quote(main)
  fun_call <- as.call(fun_call)
  fun_eval <- eval.parent(fun_call, n=2)
  return(fun_eval)
}

这里的
wrapper
只是将它的所有参数值绑定到一个列表中。然后,您可以将参数列表传递给
helper
do。call
将该列表作为参数传递给
main
函数。这将在调用时评估
包装器的参数。您不必担心执行环境。

您希望在父环境而不是本地函数环境中评估调用。将助手更改为

helper <- function(fun_call) {
  fun_call[[1]] <- quote(main)
  fun_call <- as.call(fun_call)
  fun_eval <- eval.parent(fun_call, n=2)
  return(fun_eval)
}

这里的
wrapper
只是将它的所有参数值绑定到一个列表中。然后,您可以将参数列表传递给
helper
do。call
将该列表作为参数传递给
main
函数。这将在调用时评估
wrapper
的参数。您不必担心执行环境。

在wrapper主体中定义helper可能会起作用。在wrapper主体中定义helper可能会起作用。这似乎很好,但我不明白为什么!
eval.parent()
中的默认值是
n=1
eval.parent(expr,n)
eval(expr,parent.frame(n))的缩写。因此
eval.parent(expr,1)
eval(expr,parent.frame(1))
,但是
eval
中的默认环境是
parent.frame()
-,
parent.frame()
的默认环境是
n=1
!因此,tl;dr:
eval.parent(expr)
eval(expr)
不一样吗?(显然不是,但我不明白为什么。)此外,我刚刚意识到,如果在测试中设置
a2@hejseb,那么这种情况就会发生故障。首先,需要注意的是,当您将参数传递给函数时,它们会在调用环境中进行计算,但当您有一个默认参数值时,这些都是在不同的功能环境中执行的。因此,
parent.frame
在传递给函数时与作为默认参数值时的行为不同。如果helper总是从weapper内部调用,那么您可以做
fun\u eval谢谢,我在这里学到了很多<代码>包装器
始终调用
帮助程序
,因此可以安全地假定。然而,我不会说我故意拖延评估——这正是我所经历的。最初,我想要一堆包装器,它们都只是修改
main
的某些参数。然后我使用了
match.call()
,以避免大量硬编码包装,因为所有包装的结构都是相同的,所以我将这些内容放入
帮助程序中
。我还可以补充一点,在我的情况下,
wrapper
也有默认值,我需要跟踪这些值和已被覆盖的值。我使用
formals()
实现,并将其传递给
助手
,因此我确实认为中间函数是必要的(尽管它带来了一些意想不到的复杂情况!)。这似乎很好,但我不明白为什么!
eval.parent()
中的默认值是
n=1
eval.parent(expr,n)
eval(expr,parent.frame(n))的缩写。因此
eval.parent(expr,1)
eval(expr,parent.frame(1))
,但是
eval
中的默认环境是
parent.frame()
-,
parent.frame()
的默认环境是
n=1
!因此,tl;dr:
eval.parent(expr)
eval(expr)
不一样吗?(显然不是,但我不明白为什么。)此外,我刚刚意识到,如果在测试中设置
a2@hejseb,那么这种情况就会发生故障。首先,需要注意的是,当您将参数传递给函数时,它们会在调用环境中进行计算,但当您有一个默认参数值时,这些都是在不同的功能环境中执行的。因此,
parent.frame
在传递给函数时与作为默认参数值时的行为不同。如果helper总是从weapper内部调用,那么您可以做
fun\u eval谢谢,我在这里学到了很多<代码>包装器
始终调用
帮助程序
,因此可以安全地假定。然而,我不会说我故意拖延评估——这正是我所经历的。最初,我想要一堆包装器,它们都只是修改
main
的某些参数。然后我使用了
match.call()
,以避免大量硬编码包装,因为所有包装的结构都是相同的,所以我将这些内容放入
帮助程序中
。我还可以补充一点,在我的情况下,
wrapper
也有默认值,我需要跟踪这些值和已被覆盖的值。我使用
formals()
并将其传递给
助手
,因此我确信中间函数是必要的(尽管它已经出现)