0

I'd like to test that a function returns the expected data.frame. The data.frame is too large to define in the R file (eg, using something like structure()). I'm doing something wrong with the environments when I try a simple retrieval from disk, like:

test_that("SO example for data.frame retreival", {   
  path_expected <- "./inst/test_data/project_longitudinal/expected/default.rds"
  actual <- data.frame(a=1:5, b=6:10) #saveRDS(actual, file=path_expected)
  expected <- readRDS(path_expected)
  expect_equal(actual, expected, label="The returned data.frame should be correct")
})

The lines execute correctly when run in the console. But when I run devtools::test(), the following error occurs when the rds/data.frame is read from a file.

1. Error: All Records -Default ----------------------------------------------------------------
cannot open the connection
1: withCallingHandlers(eval(code, new_test_environment), error = capture_calls, message = function(c) invokeRestart("muffleMessage"), 
       warning = function(c) invokeRestart("muffleWarning"))
2: eval(code, new_test_environment)
3: eval(expr, envir, enclos)
4: readRDS(path_expected) at test-read_batch_longitudinal.R:59
5: gzfile(file, "rb")

To make this work, what adjustments are necessary to the environment? If there's not an easy way, what's a good way to test large data.frames?

wibeasley
  • 5,000
  • 3
  • 34
  • 62
  • 1
    I haven't used this (hence untested), but does `system.file()` not apply here? It allows you to specify a package and then the bits of the path from the package base to the file. So give `path_expected <- system.file("inst", "test_data", "project_longitudinal", expected", "default.rds")` a try... – Gavin Simpson Apr 08 '15 at 05:15
  • That helped. I was distracted about environments, and had forgotten that the testing process changes the working directory. For some reason I had trouble with `path_qualified <- base::system.file("inst/test_data/project_longitudinal/expected/dummy.rds", package="REDCapR")`. However `path_qualified <- base::file.path(devtools::inst(name="REDCapR"), "test_data/project_longitudinal/expected/dummy.rds")` works. If you post an official answer pointing me towards the working directory issue, I'll gladly accept it. – wibeasley Apr 08 '15 at 14:49

2 Answers2

2

I suggest you check out the excellent ensurer package. You can include these functions inside the function itself (rather than as part of the testthat test set). It will throw an error if the dataframe (or whatever object you'd like to check) doesn't fulfill your requirements, and will just return the object if it passes your tests. The difference with testthat is that ensurer is built to check your objects at runtime, which probably circumvents the entire environment problem you are facing, as the object is tested inside the function at runtime. See the end of this vignette, to see how to test the dataframe against a template that you can make as detailed as you like. You'll also find many other tests you can run inside the function. It looks like this approach may be preferable over testthat in this case.

Peter Verbeet
  • 1,786
  • 2
  • 13
  • 29
  • Thanks for addressing the larger picture, @Peter Verbeet. I marked the file path solution as the answer because it solved this specific problem more directly. However I'm glad I learned about the `ensurer` package and plan to use it in the future. Among other things in the vignette, I like the template idea. It seems like a great way to quickly make the testing suite more granular. It would allow the suite to identify when the returned structure is correct, but the values aren't (and thus point me to the problem code more directly). – wibeasley May 03 '15 at 21:09
0

Based on the comment by @Gavin Simpson, the problem didn't involve environments, but instead the file path. Changing the snippet's second line worked.

path_qualified <- base::file.path(
    devtools::inst(name="REDCapR"),
    test_data/project_longitudinal/expected/dummy.rds"
)  

The file's location is found whether I'm debugging interactively, or testthat is running (and thus whether inst is in the path or not).

wibeasley
  • 5,000
  • 3
  • 34
  • 62