问题
I have a function of the form func(expr, data.sizes)
, where the parameter expr
is an expression and the one named data.sizes
is ordinarily as the name suggests, a vector or sequence of data sizes. (eg: c(10, 100, 1000)
or 10^seq(1, 3)
)
I would like to write some test-cases for my function's parameters using testthat
, but am new to unit-testing in R so I would like to know how does one test conditions for a function's parameter(s) using testthat
?
For instance, I want to check for a possible NA value for the parameter data.size
in my function and I wrote this snippet to test in my console: (function is available in Global Env.)
test_that("NA test for data.sizes", {
expect_false(is.na(data.sizes %in% func(expression, data.sizes = c(10, 100))))
})
which throws the error:
* object 'data.sizes' not found
1: expect_false(is.na(data.sizes %in% func(expression, data.sizes = c(10,
10)))) at :2
2: quasi_label(enquo(object), label, arg = "object")
3: eval_bare(get_expr(quo), get_env(quo))
4: data.sizes %in% func(expression, data.sizes = c(10, 10))
What might I be possibly doing wrong? Also what would be the syntax in general to apply test conditions on a function's parameters using testthat?
回答1:
testthat checks if the result of the function is what you expect.
If you want to test the result of the function to NAs, you can make a specific test for this :
library(testthat)
library(assertthat)
func <- function(expr,data.sizes) {
assert_that(noNA(data.sizes))
eval(expr)
}
test_that("data.sizes test for func", {
# Success
expect_error(func(expression(data.sizes[1]+data.sizes[2]), data.sizes = c(1,NA)))
expect_equal(func(expression(data.sizes[1]+data.sizes[2]), data.sizes = c(1,2)),3)
# Failure
expect_equal(func(expression(data.sizes[1]+data.sizes[2]), data.sizes = c(1,2)),4)
})
To test validity of parameters inside the function, you can use assertive programming packages like assertthat.
回答2:
Your unit test can test the output of your function with a given input. It is not a way of allowing your function to screen the given variables for inappropriate inputs. This has to be done inside your function.
The unit test must simply call your function with some parameters and ensure the output is what is expected.
Suppose for example that you want func
to return a list containing repetitions of the evaluated expression according to data.sizes
, like this:
func <- function(expression, data.sizes)
{
expression <- as.expression(as.list(match.call())$expression)
if(!all(!is.na(data.sizes))) stop("data.sizes may not contain NAs")
lapply(data.sizes, function(x) rep(eval(expression), x))
}
So that it does something like this:
y <- 5
func(y^2 + 3, 1:3)
#> [[1]]
#> [1] 28
#>
#> [[2]]
#> [1] 28 28
#>
#> [[3]]
#> [1] 28 28 28
But you want an exception to be thrown if there are NA
values in data.sizes
:
func(y^2 + 3, c(1, NA))
#> Error in func(y^2 + 3, c(1, NA)) : data.sizes may not contain NAs
Then your unit test would look like this:
test_that("NA test for data.sizes", {
expect_list(func(y^2 + 3, 1:3))
expect_error(func(y^2 + 3, c(1, NA)))
})
So you know if this test passes, your error is being picked up appropriately
来源:https://stackoverflow.com/questions/62244007/testing-conditions-on-a-functions-parameter-using-testthat