仅测试R脚本中的各个函数

时间:2013-03-27 04:08:03

标签: r unit-testing

我正在尝试在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(..))不需要用于测试目的。

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

1 个答案:

答案 0 :(得分: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())