R中的包可以在其他包上具有不同类型的依赖关系.有些类型的指示硬要求,即Depends,Imports和LinkingTo.
然而,还有第二类表明依赖性较弱,即Suggests和Enhances.在这两种情况下,如果建议/增强包可用,则包提供附加功能.
这是一个具体的例子:包checkpoint导入knitr因为knitr有助于checkpoint解析rmarkdown文件.
但现在我正在考虑更改knitr为Suggests依赖项,即仅knitr在实际安装时才提供此功能.
对于正确的单元测试,这意味着我必须测试两种情况:
knitr可以,那就去做吧.knitr是不提供,则抛出一个警告,什么也不做.实际的R代码很简单:
if(require(knitr)) {
do_stuff()
} else {
message("blah")
}
Run Code Online (Sandbox Code Playgroud)
题
但是,如何为这两种方案设置单元测试?
我看到它的方式,检查的简单事实require(knitr)将加载knitr包,如果它在本地库中可用.
因此,为了测试案例1,我必须在knitr本地安装,这意味着我无法测试案例2.
有没有testthat为这个用例配置(或任何其他单元测试框架)的方法?
要测试 use 失败时遵循的分支require(knitr),请使用trace()临时修改require(),以便它不会找到knit,即使它存在于 上.libPaths()。具体来说,在 的正文中require(),将 的值重置lib.loc=为指向R.home()-- 不包含knitr包的现有目录。
这在包中似乎与在运行以下命令的交互式会话中一样有效:
find.package("knitr")
trace("require", quote(lib.loc <- R.home()), at=1)
isTRUE(suppressMessages(suppressWarnings(require(knitr))))
untrace("require")
isTRUE(suppressMessages(suppressWarnings(require(knitr))))
Run Code Online (Sandbox Code Playgroud)
据我了解,您有一个具有两个分支的函数,一个在成功的 R 会话中执行require(knitr),另一个在失败的会话中执行。然后,您希望从knit实际上处于打开状态的单个 R 实例“双向”测试此函数.libPaths()。
所以基本上你需要某种方法来暂时隐藏对knitrrequire(knitr)实际存在的调用。完全暂时重置返回的值看起来很有希望,但似乎不可能。.libPaths()
另一个有前途的途径是以某种方式将lib.locin 调用的默认值重置为require()from NULL(这意味着“使用 的值)到knitr不可用的.libPaths()其他位置。您不能通过覆盖来完成此操作,(在包中)也不能您可以通过使用所需值定义本地掩码版本来实现这一点。base::require()require()lib.loc
不过,看起来您确实可以通过使用trace()临时修改来逃脱require()(通过设置使其对knitr的可用性视而不见lib.loc=R.home())。然后untrace()恢复require()到香草版本,这将继续并找到knitr。
这是我测试的虚拟包中的样子。首先是一个 R 函数,它允许我们测试两个分支是否成功
## $PKG_SRC/R/hello.R
hello <- function(x=1) {
if(require(knitr)) {
x==2
} else {
x==3
}
}
Run Code Online (Sandbox Code Playgroud)
然后进行一些测试,每个分支一个:
## $PKG_SRC/inst/tests/testme.R
## Test the second branch, run when require(knitr) fails
trace("require", quote(lib.loc <- R.home()), at=1)
stopifnot(hello(3))
untrace("require")
## Test the first branch, run when require(knitr) succeeds
stopifnot(hello(2))
Run Code Online (Sandbox Code Playgroud)
为了测试这一点,我曾经pkgKitten::kitten("dummy")设置一个源目录,复制这两个文件,添加Suggests: knitr到DESCRIPTION文件中,然后从适当的目录运行devtools::install()和。devtools::check()该软件包安装得很好,并通过了所有检查。
| 归档时间: |
|
| 查看次数: |
282 次 |
| 最近记录: |