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

testthat是否存在对比两个对象行为的expect_*系列函数?

testthat函数等价性断言相关解答
  • 截至最新的testthat 3.2.x版本,官方没有内置expect_equal_applied这类支持传入函数列表的批量等价断言函数。

该模式没有被纳入官方API的核心原因是testthat的设计更偏向单断言单校验原则:单个断言仅验证一项逻辑,测试失败时可以直接定位到具体的校验点,也方便为每个校验点单独配置提示信息、容错阈值等参数。如果把多个校验逻辑打包到单个断言中,会提升测试失败后的定位成本,也会降低测试用例的可读性。

如果需要简化重复的同类断言,R包开发社区有两种被广泛使用的惯用实现方式:

方式1:借助循环直接实现(最常用)

用purrr循环或者基础循环批量执行断言,代码简洁同时保留原生的错误定位能力:

library(testthat)
library(purrr)

x <- 1:4
y <- matrix(4:1, nrow=2)

test_that("objects behave similarly", {
  # 给函数命名可以让报错信息更清晰
  target_fns <- list(sum = sum, prod = prod)
  walk(target_fns, \(fn) expect_equal(fn(x), fn(y)))
})

方式2:自定义断言函数

如果需要大量复用该逻辑,可以按照testthat的扩展规范自定义断言函数,自定义的断言函数完全兼容testthat的测试报告体系:

expect_equal_applied <- function(object, expected, .fn, ...) {
  stopifnot(is.list(.fn))
  # 为匿名函数自动生成名称,方便报错定位
  if (is.null(names(.fn))) {
    names(.fn) <- paste0("function_", seq_along(.fn))
  }
  obj_nm <- deparse1(substitute(object))
  exp_nm <- deparse1(substitute(expected))
  
  for (fn_nm in names(.fn)) {
    fn <- .fn[[fn_nm]]
    expect_equal(
      fn(object), fn(expected), ...,
      label = paste0(fn_nm, "(", obj_nm, ")"),
      expected.label = paste0(fn_nm, "(", exp_nm, ")")
    )
  }
}

自定义完成后即可直接使用你示例中的写法:

test_that("objects behave similarly", {
  expect_equal_applied(x, y, .fn = list(sum, prod))
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 01:18:00