如何在不使用 for 循环的情况下使用参数组合测试函数

How to test a function with a combination of parameters without resorting to a for loop

在 R 中,是否可以在不使用 for 循环的情况下使用参数组合来测试函数?例如,我目前正在做类似的事情:

test_that("Function myfunction() works properly", {

  a1 <- c(1, 2, 3, 10, 20, 100)
  a2 <- c(-500, 0, 500)
  a3 <- c("hello", "world")

  for (a1i in a1) {
    for (a2i in a2) {
      for (a3i in a3) {

        result <- myfunction(a1i, a2i, a3i)
        expect_equal(result, something_expected)
        expect_equal(dim(result), something_else)
        # ...and other checks...

      }
    }
  }
})

然而,这对于嵌套太多的 for 不切实际,并且还会引发 lintr 的圈复杂度错误。

在Python中我们可以用pytest轻松做到这一点(使用测试参数或文本夹具),这在Julia中也很容易实现。

我找到了patrick这个包,但是好像没有这样进行参数组合,只是定义了参数集。我想可以使用 for 循环为 patrick 创建这些参数集,但这似乎没有抓住要点。

如果你想完全避免 for 循环,那么你可以使用包 purrr 的映射函数来迭代数据帧,这是由 expand.grid 产生的:

a1 <- c(1, 2, 3, 10, 20, 100)
a2 <- c(-500, 0, 500)
a3 <- c("hello", "world")

df <- expand.grid(a1,a2,a3, stringsAsFactors = FALSE) 

# purrr::pwalk(df, ~ cat(..1, ..2, ..3, "\n")) <-- avoiding for loop

for (i in 1:nrow(df))
  cat(df[i,1], df[i, 2], df[i, 3], "\n")
#> 1 -500 hello 
#> 2 -500 hello 
#> 3 -500 hello 
#> 10 -500 hello 
#> 20 -500 hello 
#> 100 -500 hello 
#> 1 0 hello 
#> 2 0 hello 
#> 3 0 hello 
#> 10 0 hello 
#> 20 0 hello 
#> 100 0 hello 
#> 1 500 hello 
#> 2 500 hello 
#> 3 500 hello 
#> 10 500 hello 
#> 20 500 hello 
#> 100 500 hello 
#> 1 -500 world 
#> 2 -500 world 
#> 3 -500 world 
#> 10 -500 world 
#> 20 -500 world 
#> 100 -500 world 
#> 1 0 world 
#> 2 0 world 
#> 3 0 world 
#> 10 0 world 
#> 20 0 world 
#> 100 0 world 
#> 1 500 world 
#> 2 500 world 
#> 3 500 world 
#> 10 500 world 
#> 20 500 world 
#> 100 500 world

这里有一个可能的选项,使用 base R(如果你想避免 for 循环),但在@Paulsmith 之后使用 expand.grid

invisible(apply(df, 1, function(x){
    cat(paste0(paste(x[1],x[2],x[3],sep=' '),"\n"))
  }))

输出

  1 -500 hello
  2 -500 hello
  3 -500 hello
 10 -500 hello
 20 -500 hello
100 -500 hello
  1    0 hello
  2    0 hello
  3    0 hello
 10    0 hello
 20    0 hello
100    0 hello
  1  500 hello
  2  500 hello
  3  500 hello
 10  500 hello
 20  500 hello
100  500 hello
  1 -500 world
  2 -500 world
  3 -500 world
 10 -500 world
 20 -500 world
100 -500 world
  1    0 world
  2    0 world
  3    0 world
 10    0 world
 20    0 world
100    0 world
  1  500 world
  2  500 world
  3  500 world
 10  500 world
 20  500 world
100  500 world

数据

a1 <- c(1, 2, 3, 10, 20, 100)
a2 <- c(-500, 0, 500)
a3 <- c("hello", "world")

df <- expand.grid(a1,a2,a3, stringsAsFactors = FALSE)