如何测试取决于是否安装软件包的行为

Ale*_*ock 1 r testthat

我有一个这样的功能:

func <- function(x) {
  if (requireNamespace("broom", quietly = TRUE)) {

    print(1)

  } else {

    print(2)

  }
Run Code Online (Sandbox Code Playgroud)

我想使用testthat触发两种情况编写测试。但是,当然broom我的计算机上已经安装或未安装。该怎么办?

r2e*_*ans 5

编辑:从此不再有效testthat-2.0.0。根据2017年10月更改

  • “不能在基本程序包中模拟函数”:您不再可以with_mock()在基本程序包中模拟函数,因为由于字节码编译器的更改,这在R-devel中不再起作用。我建议改用嘲笑嘲笑

其余的答案仅适用于的旧版本testthat


testthat::with_mock 应该做你想做的。

library(testthat)
somefunc <- function() if (requireNamespace("base", quietly=TRUE)) 1L else 2L
Run Code Online (Sandbox Code Playgroud)

一些简单的测试:

expect_equal( somefunc(), 1L )
Run Code Online (Sandbox Code Playgroud)

成功了

expect_equal( somefunc(), 2L )
# Error: somefunc() not equal to 2.
# 1/1 mismatches
# [1] 1 - 2 == -1
Run Code Online (Sandbox Code Playgroud)

预期。

让我们创建一个覆盖基本函数的“模拟”函数:

with_mock(
  `base::requireNamespace` = function(package, ..., quietly=FALSE) FALSE,
  expect_equal( somefunc(), 1L )
)
# Error: somefunc() not equal to 1.
# 1/1 mismatches
# [1] 2 - 1 == 1

with_mock(
  `base::requireNamespace` = function(package, ..., quietly=FALSE) FALSE,
  expect_equal( somefunc(), 2L )
)
# [1] 2
Run Code Online (Sandbox Code Playgroud)

注意:成功后,将expect_equal无形地返回返回值,因此[1] 1在第一个示例中看不到。with_mock成功时会返回返回值,但不会隐式返回。在这两种情况下,失败都会返回修改后的返回值。此微小差异不应影响任何测试。

根据您要覆盖的功能,对我而言,谨慎定义具有相同形式的模拟功能是有意义的。如果您确切地知道在测试期间所有从属函数中总是如何调用它,则可以简化此操作,但是我认为对形式的额外关注将排除真正难以解决的测试失败。

注意:帮助指出

...仍处于实验阶段,请谨慎使用

  • 我不确定这个答案是否不再有效......我收到一个错误“错误:无法模拟基础包(基础)中的函数” (2认同)