You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为R包创建支持动态输入的函数并适配roxygen2示例与testthat测试

1 Roxygen2示例兼容方案

核心原因是readline()仅在交互式R会话中生效,非交互式场景(如R CMD check、CI运行示例)会返回空值导致报错。解决方法分为两步:

  1. 函数内增加交互式环境判断,非交互式场景给定合理默认值,同时预留直传参数跳过交互
    修改后的完整函数逻辑:
#' Dynamic Input Example
#'
#' @param input A number
#' @param dynamic_input 可选,直接传入动态值跳过交互,默认NULL
#' @return Console input times 2 minus 1
#' @export
#'
#' @examples
#' \dontrun{
#' # 交互式场景走弹窗输入
#' exampler(4)
#' }
#' # 非交互式场景/提前知晓输入值时直接传参,可正常跑通检查
#' exampler(4, dynamic_input = 10)
exampler <- function(input, dynamic_input = NULL){
  if (is.null(dynamic_input)) {
    dynamic_input <- if (interactive()) {
      as.numeric(readline(prompt=paste("Give a value between", input*3-1, "and", input*7+2)))
    } else {
      # 非交互式默认取区间中间值,可根据业务需求调整
      input * 5
    }
  }
  return(dynamic_input*2-1)
}
  1. 示例中需要人工交互的部分用\dontrun{}包裹,同时补充可自动运行的传参示例,即可通过R CMD check的示例检查。
2 testthat测试方案

核心思路是mock掉readline()函数的返回值,不需要真的等待用户输入,测试代码示例:

library(testthat)

test_that("exampler计算逻辑符合预期", {
  # 方法1:使用testthat内置mock功能(testthat >=3.0.0支持)
  local_mocked_bindings(
    readline = function(...) "12",
    .package = "base"
  )
  expect_equal(exampler(4), 12*2 -1) # 预期返回23

  # 方法2:使用mockery包的stub功能,兼容性更好
  # mockery::stub(exampler, "readline", "8")
  # expect_equal(exampler(4), 15)
})

如果有输入校验逻辑(比如判断用户输入是否在要求的区间内),也可以通过mock不同的输入值覆盖边界场景测试。

3 R包场景下的动态输入最优方案
  • 基础交互场景:base包自带的readline()已经足够使用,只要做好交互式/非交互式分支判断、预留直传参数即可,不需要引入额外依赖
  • 复杂交互场景:
    • 密码输入:使用getPass::getPass(),输入内容不会在控制台回显
    • 菜单式多选:使用base包自带的menu()函数,无需额外依赖
    • 样式化交互/输入校验:使用cli包的cli_ask_*系列函数,支持输入格式校验、自定义提示样式,是当前R包生态的主流选择
  • 所有交互类函数都建议预留直传参数,方便用户在脚本、批处理场景调用,也能简化测试流程。

内容的提问来源于stack exchange,提问作者Kezrael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 08:09:03