如何将 testthat 测试应用于我的包中与特定命名模式匹配的所有函数?

Posted

技术标签:

【中文标题】如何将 testthat 测试应用于我的包中与特定命名模式匹配的所有函数?【英文标题】:How can I apply a testthat test to all functions in my package that match a certain naming pattern? 【发布时间】:2021-11-04 22:04:13 【问题描述】:

我有一个包,其中包含许多名为 viz_foo()viz_bar() 等的函数。

我想测试这些函数中的每一个是否都会产生一个 gg 类的对象。这很简单,有两个函数,如下所示:

testthat::test_that("viz_ functions produce a plot", 
    testthat::expect_s3_class(viz_foo(), "gg")
    testthat::expect_s3_class(viz_bar(), "gg")
)

但在实践中,我有许多使用这种命名约定的函数,并且包贡献者一直在添加新函数。我想确保以这种方式测试任何新功能,而不必将它们显式添加到单元测试中。

我想到的处理这个问题的笨拙方式是:

testthat::test_that("viz_ funcs produce a plot", 
  viz_funcs <- ls("package:mypackage", pattern = "viz_")
  
  eval_func <- function(func_name) 
    suppressMessages(
      eval(str2lang(paste0(func_name, "()")))
    )
  
  
  plots <- lapply(viz_funcs, eval_func)
  
  lapply(plots, testthat::expect_s3_class, "gg")
  
)

这在使用devtools::test() 运行测试时有效,但不适用于R CMD check

有没有办法对包中名称中包含特定模式的所有函数进行测试?

【问题讨论】:

【参考方案1】:

getNamespaceExports 可能是更适合支持包反射的函数

for (f in base::getNamespaceExports("mypackage")) 
  if (grepl("viz_", f)) 
    testthat::expect_s3_class(get(paste0("mypackage::", f))())
  

【讨论】:

谢谢@Hugh。受您的回答启发,我选择了:for (f in ls(getNamespace("mypackage"), pattern = "viz_")) testthat::expect_s3_class(get(f)(), "gg")

以上是关于如何将 testthat 测试应用于我的包中与特定命名模式匹配的所有函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何编写测试用例以使用r中的testthat检查函数是否正常工作?

如何将 .SQLite 正确添加到 App 的包中?

安装具有特定版本和测试的 R 包

你如何从 Laravel 的包中扩展视图?

vue 将共享计算函数编译到单独的包中

将 LIME 解释应用于我的微调 BERT 以进行序列分类模型?