Reputation: 6921
I have a package with a suggested dependency enabling optional behaviour.
Following the best practice, I added this dependency in my "Suggests" and check if it's installed with requireNamespace
before using it.
In this particular case, the suggested package is data.tree
and the optional behaviour is making a pretty print instead of a more boring one.
myfun <- function(...) {
if (requireNamespace("data.tree", quietly = TRUE)) {
# do pretty print
} else {
# do boring print
}
}
My question is: how do I test this behaviour with testthat
? I want to test both branches of the if/else
, but since I do have data.tree installed, I only ever run the first branch.
test_that("myfun does a pretty print with data.tree", {
myfun()
})
test_that("myfun does a boring print if data.tree is not installed", {
# Ideally I am looking for a bit of code like this:
with(simulate_missing("data.tree"),
myfun())
})
Is there a way to simulate a missing dependency with testthat
, or more generally a way to test myfun
?
Upvotes: 6
Views: 258
Reputation: 935
The only solution I can think about is mocking, I am not aware of others at the moment.
Mock requireNamespace() using the with_mock() function from the testthat package. This approach allows you to temporarily redefine requireNamespace() so that it returns FALSE as if the package were not installed.
test_that("myfun does a pretty print with data.tree", {
# Assuming `requireNamespace` returns TRUE as `data.tree` is installed
expect_true(requireNamespace("data.tree", quietly = TRUE))
# Test the pretty print functionality
# You might want to capture output and expect certain content
output <- myfun()
expect_true(grepl("Expected pretty content", output))
})
test_that("myfun does a boring print if data.tree is not installed", {
# Mock `requireNamespace` to return FALSE for `data.tree`
with_mocked_bindings(
{
# Now `myfun()` should behave as if `data.tree` is not installed
output <- myfun()
expect_true(grepl("Expected boring content", output))
},
`requireNamespace` = function(pkg, quietly = TRUE) {
if (pkg == "data.tree") {
return(FALSE)
}
# Call the real `requireNamespace` for other packages
base::requireNamespace(pkg, quietly = quietly)
},
package="base"
)
})
I haven't tested it locally, you might need to tweak it a little bit, but I wanted to share the concept.
Cheers
Upvotes: 1