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

Posted

技术标签:

【中文标题】是否有一个 testthat expect_* 函数用于比较两个对象的行为?【英文标题】:Is there a testthat expect_* function for comparing two objects behavior? 【发布时间】:2021-11-12 01:27:51 【问题描述】:

我正在使用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 是否实现了这样的期望函数?

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

【问题讨论】:

【参考方案1】:

查看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 构造它。

【讨论】:

以上是关于是否有一个 testthat expect_* 函数用于比较两个对象的行为?的主要内容,如果未能解决你的问题,请参考以下文章

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

我们可以使用 testthat 包中的函数来测试向量的元素吗?

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

使用 testthat 在单元测试中重用变量。是不是有一种可接受的做法来避免重新创建计算量大的变量

pytest 是不是有类似谷歌测试的非致命 EXPECT_* 行为?

在推力函子中使用 CURAND