4

I am trying to test a individual functions in a R script which contains a function call as the last statement of the script i.e. Here is the R code:

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

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


mul(4,5)

Here is the test script:

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

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

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

I execute the test script using the following command:

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

Now, when I source the R script I want to test i.e. mul.R, since the last statement already makes a call to the mul function, the entire script is executed and then the test script runs the function again. This makes the 1st execution(due to source(..)) not needed for testing purpose.

Is there a way to test such scripts, without running the script when sourcing it in the test script?

3
  • Develop a package with tests? Commented Mar 27, 2013 at 4:11
  • you can create a library file that only contains your mul function and maybe even test.mul. Then both your script and test script will source that file. Commented Mar 27, 2013 at 4:21
  • @mnel: Having worked on few programming languages, I am accustomed to not creating a package just to test a particular piece of code. And I would prefer not creating a package every time I have to test it. Commented Mar 27, 2013 at 12:16

1 Answer 1

4

Use parse instead of source:

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

This load the file as unevaluated expression. It can be seen as:

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

The first element of the list above is actually a call to the '<-' function:

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

The second element, OTOH, is a call to the mul function:

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

So, if your files are made of assignments and undesired function calls, we can identify that by inspecting the first element of each entry in the list above:

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

# >filter
# [1] TRUE FALSE

Now we can evaluate only the assignments:

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

Then you can call your test.mul function. You can use these statements to replace you source call.

This can generalized to other filters. For instance, if you want to evaluate all statements except the last one, you can just use this:

eval(code[-length(code)], envir=globalenv())
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.