Use functions of an R package loaded with load_all() in r() and r_bg() {callr} functions

I'm devoloping an R package and want to run some of the functions in the package under development in the background, using callr::r() or callr::r_bg().

As an example, I created a package mytest with only one function

hello <- function() {
  print("Hello, world!")

Then loaded the package with pkgload::load_all(), the function to load a package in development using devtools package. After this, I can run the function in the console but not in the background using callr::r().

#> Error: callr subprocess failed: there is no package called 'mytest'
#> Type .Last.error.trace to see where the error occurred

On the other hand, if I install the package and run library(mytest), the code above run without problems

#> [1] "Hello, world!"

Please, any clue why callr::r() does not find function mytest::hello()?

It looks like load_all() is not adding the path to the folder where the source code of the package mytest can be found.

I found a solution based on an issue in callr GitHub.

After loading the package mytest, that only has the function hello() in it as defined in the question, with devtools::load_all() the following code works

z <- list(mytest::hello)

}, args = list(z))
#> [1] "Hello, world!"

It looks like the function hello() in the package loaded with load_all() cannot be referred as mytest::hello() in callr::r() or in callr::r_bg() while you can do so if the package was installed and loaded after through library(mytest).

Please, is there another solution?

I posted the same question in Stackoverflow with no success. Thanks a lot for you help.

I'm not familiar with {callr}, my understanding is that it start a new R session in a separate process. So in that case it doesn't inherit the namespace of the Global Environment.

What pkgload::load_all() does is basically run source() on the package files (plus a few other things). So that way all the functions defined in the package become available in the Global Environment. But it does not actually install the package, so mytest::xx is not available (the actual call to library() is irrelevant).

Unfortunately, I don't have a solution to offer: load_all() is a bit of a convenience hack to easily and rapidly test your package within a session, {callr} goal is to start a separate session, I don't see how to reconcile the two. I guess you're stuck with reinstalling your package for every test (or passing the function from the global environment to {callr} as an argument).


Thanks a lot @AlexisW for your answer.
The problem I have is precisely as you explain.
I have to install the package I'm testing in the separate session before I can use new package function in the new background session. Indeed, the following code works!

#> [1] "Hello, world!"

Nevertheless, I feel I'm missing something. The problem I'm sharing is just a simple step in my real goal to find a workflow to build, test and deploy a Plumber API as a package. I found notes here and there about it (for instance sol-eng RStudio github but not a full workflow that works with load_all().

For in development package testing, use testthat with unit tests. It is integrated within RStudio, and it does the whole live load all dance for you before executing tests. You can run all tests or just a single test file

Thanks for your answer @meztez

I'm indeed using {testthat} for all my tests.

It is precisely in the tests where I need to run a background process using {callr} that calls the functions in the package under development. I have not managed to do this using load_all(). Instead, I'm forced to run install() before running the tests.

For these kinds of test (full integration), we run the script manually after installing the package. You can do a lot without using callr. You can also mock request to the API without running plumber. Best of luck to you.

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.