是否有用于比较两个对象行为的 expect_* 函数测试?

Is there a testthat expect_* function for comparing two objects behavior?

我正在使用 testthat 为 R 包编写一些单元测试。我想比较两个对象,其中并非所有细节都需要匹配,但它们必须在一组感兴趣的函数方面保持等价。

举个简单的例子,我想用

library(testthat)

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

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

  ## which would be shorthand for:
  ## expect_equal(sum(x), sum(y))
  ## expect_equal(prod(x), prod(y))
})

实际上,xy 可能是 S3 对象,而不仅仅是基础数据结构。

显然,这很容易实现,但如果已经存在,我更喜欢惯用的东西。所以,问题是,testthat 是否实现了这样的 expect 函数?

通过 API 搜索,我觉得没有什么符合这个描述,但它似乎是一个自然的模式。或者也许有一个原因让我忽略了这种模式令人反感的原因。

查看 documentation {testthat} 目前(第三版)没有像 expect_equal_applied 那样的功能。但是,正如你已经提到的,我们可以很容易地构造这样一个函数:

library(testthat)

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


expect_equal_applied <- function(object, expected, fns) {
  fns <- purrr::map(fns, rlang::as_function)
  purrr::map(fns, ~ expect_equal(.x(object), .x(expected)))
}

test_that("objects behave similarly", {
  expect_equal_applied(x, y, fns = list(sum, prod))
})
#> Test passed

x <- 1:3

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

#> -- Failure (<text>:19:3): objects behave similarly -----------------------------
#> .x(object) not equal to .x(expected).
#> 1/1 mismatches
#> [1] 6 - 10 == -4
#> Backtrace:
#>  1. global::expect_equal_applied(x, y, fns = list(sum, prod))
#>  2. purrr::map(fns, ~expect_equal(.x(object), .x(expected)))
#>  3. .f(.x[[i]], ...)
#>  4. testthat::expect_equal(.x(object), .x(expected))
#> 
#> -- Failure (<text>:19:3): objects behave similarly -----------------------------
#> .x(object) not equal to .x(expected).
#> 1/1 mismatches
#> [1] 6 - 24 == -18
#> Backtrace:
#>  1. global::expect_equal_applied(x, y, fns = list(sum, prod))
#>  2. purrr::map(fns, ~expect_equal(.x(object), .x(expected)))
#>  3. .f(.x[[i]], ...)
#>  4. testthat::expect_equal(.x(object), .x(expected))

reprex package (v2.0.1)

于 2021-09-17 创建

关于为什么在{testthat}中似乎缺少这样的功能,我认为这不是真正必要的,我们可以用lapplymap构造它。