如何为建议的包编写单元测试?

And*_*rie 7 r testthat

R中的包可以在其他包上具有不同类型的依赖关系.有些类型的指示硬要求,即Depends,ImportsLinkingTo.

然而,还有第二类表明依赖性较弱,即SuggestsEnhances.在这两种情况下,如果建议/增强包可用,则包提供附加功能.

这是一个具体的例子:包checkpoint导入knitr因为knitr有助于checkpoint解析rmarkdown文件.

但现在我正在考虑更改knitrSuggests依赖项,即仅knitr在实际安装时才提供此功能.

对于正确的单元测试,这意味着我必须测试两种情况:

  1. 如果knitr可以,那就去做吧.
  2. 如果knitr提供,则抛出一个警告,什么也不做.

实际的R代码很简单:

if(require(knitr)) {
  do_stuff()
} else {
  message("blah")
}
Run Code Online (Sandbox Code Playgroud)

但是,如何为这两种方案设置单元测试?

我看到它的方式,检查的简单事实require(knitr)将加载knitr包,如果它在本地库中可用.

因此,为了测试案例1,我必须在knitr本地安装,这意味着我无法测试案例2.

有没有testthat为这个用例配置(或任何其他单元测试框架)的方法?

Jos*_*ien 3

太长了;博士

要测试 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: knitrDESCRIPTION文件中,然后从适当的目录运行devtools::install()和。devtools::check()该软件包安装得很好,并通过了所有检查。