4

我正在尝试在 R 脚本中测试单个函数,其中包含一个函数调用作为脚本的最后一个语句,即这里是 R 代码:

mul.R
#!/usr/bin/env Rscript

mul <- function(n, m) {
        prod <- n * m
        return (prod)
}


mul(4,5)

这是测试脚本:

test_simpleProgram.R
#!/usr/bin/env Rscript

library('RUnit')
source("./../simpleProgram.R")

test.mul <- function() {
        checkEqualsNumeric(mul(n= 2,m= 3), 4)
}

我使用以下命令执行测试脚本:

runTestFile(absFileName= file.path("test_simpleProgram.R"))

现在,当我获取要测试的 R 脚本时,即mul.R,由于最后一条语句已经调用了该mul函数,因此将执行整个脚本,然后测试脚本再次运行该函数。source(..)这使得测试目的不需要第一次执行(由于)。

有没有办法测试这样的脚本,而不是在测试脚本中获取脚本时运行脚本?

4

1 回答 1

4

使用parse代替source

code <- parse("c:/R/mul.R") # actual file path may vary

这会将文件加载为未评估的表达式。可以看作:

# > as.list(code)
# [[1]]
# mul <- function(n, m) {
#     prod <- n * m
#     return(prod)
# }
# 
# [[2]]
# mul(4, 5)

上面列表的第一个元素实际上是对'<-'函数的调用:

# > as.list(code[[1]])
# [[1]]
# `<-`
# 
# [[2]]
# mul
# 
# [[3]]
# function(n, m) {
#     prod <- n * m
#     return(prod)
# }

第二个元素 OTOH 是对mul函数的调用:

# > as.list(code[[2]])
# [[1]]
# mul
# 
# [[2]]
# [1] 4
# 
# [[3]]
# [1] 5

因此,如果您的文件由分配和不需要的函数调用组成,我们可以通过检查上面列表中每个条目的第一个元素来识别:

filter <- sapply(code, function(x)as.character(x[[1]])=="<-")

# >filter
# [1] TRUE FALSE

现在我们只能评估分配:

eval(code[filter], envir=globalenv())

然后你可以调用你的test.mul函数。您可以使用这些语句来替换您的source调用。

这可以推广到其他过滤器。例如,如果你想评估除最后一个之外的所有语句,你可以使用这个:

eval(code[-length(code)], envir=globalenv())
于 2013-03-27T04:51:35.350 回答