eric_kernfeld
eric_kernfeld

Reputation: 528

R testthat and devtools: why does a minimal unit test break my package?

I'm working on an R package for sparse matrix handling. It kinda works; here's a minimal example to set the stage for my question.

devtools::install_github("ekernf01/MatrixLazyEval", ref = "eef5593ad")
library(Matrix)
library(MatrixLazyEval)
data(CAex)
M = rbind(CAex, CAex)
M = matrix(stats::rnorm(prod(dim(M))), nrow = nrow(M))
M_lazy = AsLazyMatrix( M )
svd_lazy = RandomSVDLazyMatrix(M_lazy)

But, when I run even a minimal unit test, it breaks the package permanently (I have to restart my R session or reinstall the package). The immediate cause is that R can't find some S4 methods from packages I depend on (e.g. for matrix transpose t or colSums from the Matrix package). I run the unit test like this:

devtools::test(filter = "minimal")
svd_lazy = RandomSVDLazyMatrix(M_lazy)

Here's the contents of the test files.

> cat tests/testthat.R
library(testthat)
testthat::test_check("MatrixLazyEval")
> cat tests/testthat/testthat_minimal.R
context("minimal")

Why does this happen? Maybe this is naive, but the unit test shouldn't even do anything.

Edit

Possibly related:

r - data.table and testthat package

https://github.com/r-lib/devtools/issues/192

R data.table breaks in exported functions

Upvotes: 0

Views: 140

Answers (1)

Lionel Henry
Lionel Henry

Reputation: 6803

You need to import all the generics you're using in your package namespace:

#' @importFrom Matrix t tcrossprod colSums rowMeans
NULL

This will fix the issue that you're observing and you'll be able the tests multiple times in the same session.

Also this will allow other packages that import Matrix::t to consistently use your custom methods. Currently, since you're calling setMethod() in your package, you're creating a new t() generic local to your namespace whenever Matrix is not attached to the search path at load-time (this is why it worked the first time you ran the tests). This prevents other packages using Matrix::t() to access your methods. Importing Matrix::t() explicitly will fix this because you'll never create a local generic for t().

Upvotes: 1

Related Questions