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

时间:2018-07-11 21:35:01

标签: r testthat

我有这样的功能:

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

    print(1)

  } else {

    print(2)

  }

我想使用testthat编写触发两种情况的测试。但是当然broom是安装在我的计算机上还是没有安装。该怎么办?

2 个答案:

答案 0 :(得分:4)

编辑:此功能自/usr/local/bin/mup起不再有效。根据{{​​3}}:

  
      
  • “无法在基本程序包中模拟函数”:您不能再使用#count ,date 98.000000, 2014-03-16 267.000000, 2014-03-23 298.000000, 2014-03-30 313.000000, 2014-04-06 225.000000, 2014-04-13 226.000000 2014-04-20 在基本程序包中模拟函数,因为由于字节码编译器的更改,它在R-devel中不再起作用。我建议改为使用change in Oct 2017mockery
  •   

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


with_mock()应该做您想要的。

testthat

一些简单的测试:

testthat::with_mock

成功。

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

预期。

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

expect_equal( somefunc(), 1L )

注意:成功后,expect_equal( somefunc(), 2L ) # Error: somefunc() not equal to 2. # 1/1 mismatches # [1] 1 - 2 == -1 会无形地返回返回值,因此在第一个示例中看不到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 expect_equal成功时会返回返回值,但不会隐式返回。在这两种情况下,失败都会返回修改后的返回值。这一微小差异不会影响任何测试。

根据您要重写的函数,对我而言,谨慎定义具有相同形式的模拟函数是有意义的。如果您确切地知道 在测试期间在 all 下级函数中总是 调用的方式,则可以简化此操作,但我认为这是多余的仔细注意形式会避免真正难以解决的测试失败。

NB:帮助说明:

  

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

答案 1 :(得分:0)

    old_fn <- base::requireNamespace
    myrequireNamespace <- function(...) FALSE
    unlockBinding("requireNamespace", as.environment("package:base"))
    assign("requireNamespace",myrequireNamespace, "package:base")
    expect_error(read_data("meta",data_table,  frame=NULL),"Package \"readxl\" 
    needed for this function to load excel files")
    assign("requireNamespace",old_fn, "package:base")
    lockBinding("requireNamespace", as.environment("package:base"))
    rm(old_fn, myrequireNamespace)

对我来说是一种解决方法,它确实可以在testthat内部工作。