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

时间:2015-01-12 17:40:23

标签: r testthat

R中的包可以在其他包上具有不同类型的依赖关系。其中一些类型表明了硬性要求,即DependsImportsLinkingTo

但是,还有第二类表明依赖性较弱,即SuggestsEnhances。在这两种情况下,如果建议/增强包可用,该包提供了额外的功能。

以下是一个具体示例:包checkpoint导入knitr因为knitr帮助checkpoint解析rmarkdown个文件。

但现在我正在考虑将knitr更改为Suggests依赖关系,即仅在实际安装knitr时才提供此功能。

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

  1. 如果knitr可用,则执行操作。
  2. 如果knitr 可用,则抛出警告并不执行任何操作。
  3. 实际的R代码很简单:

    if(require(knitr)) {
      do_stuff()
    } else {
      message("blah")
    }
    

    问题

    但是如何为这两种情况设置单元测试?

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

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

    是否有办法为此用例配置testthat(或任何其他单元测试框架)?

1 个答案:

答案 0 :(得分:3)

TL;博士

要在使用require(knitr)失败时测试分支,请使用trace()临时修改require(),以便找不到 knitr ,甚至如果它出现在.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))))

据我所知,你有一个带有两个分支的函数,一个在R会话中执行,require(knitr)成功,另一个在失败的会话中执行。然后你想要测试这个功能&#34;两种方式&#34;来自单个R实例,其中 knitr 实际上在.libPaths()上。

所以基本上你需要某种方法暂时将通话require(knitr)视为 knitr 的实际存在。完全暂时重置.libPaths()返回的值看起来很有希望,但似乎不可能。

另一个有希望的途径是以某种方式重置lib.loc来自require()的{​​{1}}调用的默认值(这意味着&#34;使用NULL的值)到 knitr 不可用的其他位置。您无法通过覆盖.libPaths()来实现此目的,也不能(在包中)通过定义具有所需值base::require()的{​​{1}}的本地屏蔽版本来实现此目的。

但是,看起来您可以使用require()暂时修改lib.loc(通过设置{将其隐藏到 knitr &#39; s可用性) {1}})。然后执行trace()require()恢复为vanilla版本,该版本将继续并找到 knitr

这是我在测试过的虚拟包装中的样子。首先是一个R函数,它允许我们测试两个分支的成功

lib.loc=R.home()

然后进行几个测试,每个分支一个:

untrace()

为了测试这一点,我使用require()设置了一个源目录,复制了这两个文件,将## $PKG_SRC/R/hello.R hello <- function(x=1) { if(require(knitr)) { x==2 } else { x==3 } } 添加到## $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)) 文件,然后运行pkgKitten::kitten("dummy")和相应目录中的Suggests: knitr。软件包安装得很好,并通过了所有检查。