R 使用TestThis对唯一性进行大规模测试

R 使用TestThis对唯一性进行大规模测试,r,unit-testing,testthat,R,Unit Testing,Testthat,我有一个使用testthat的自动化测试包。然而,我想知道当一个人想要进行大量测试时,最佳实践是什么。一种常见的情况是,我正在测试所有参数/PAR是否都有独特的功能。下面是一个非功能性示例,给出一个想法: # GG_heatmap -------------------------------------------------------------- #save plots to list heatmaps = list( #various options default = mt

我有一个使用testthat的自动化测试包。然而,我想知道当一个人想要进行大量测试时,最佳实践是什么。一种常见的情况是,我正在测试所有参数/PAR是否都有独特的功能。下面是一个非功能性示例,给出一个想法:

# GG_heatmap --------------------------------------------------------------

#save plots to list
heatmaps = list(
  #various options
  default = mtcars[, c(1,3,4,5,6,7)] %>% GG_heatmap(),
  no_reorder = mtcars[, c(1,3,4,5,6,7)] %>% GG_heatmap(reorder_vars = F),
  no_values = mtcars[, c(1,3,4,5,6,7)] %>% GG_heatmap(add_values = F),
  many_digits = mtcars[, c(1,3,4,5,6,7)] %>% GG_heatmap(digits = 5)
)

test_that("GG_heatmap", {
  #check that plots work
  walk(heatmaps, ~expect_s3_class(., class = "ggplot"))

  #check for non-identity
  #cant think of an easy smart way to do this
  expect_true(!identical(heatmaps$default, heatmaps$no_reorder))
  expect_true(!identical(heatmaps$default, heatmaps$no_values))
  expect_true(!identical(heatmaps$default, heatmaps$many_digits))
  expect_true(!identical(heatmaps$no_reorder, heatmaps$no_values))
  expect_true(!identical(heatmaps$no_reorder, heatmaps$many_digits))
  expect_true(!identical(heatmaps$no_values, heatmaps$many_digits))
})
因此,有一个名为
GG_heatmap()
(稍加修改)的函数,它返回一个
ggplot2
绘图

walk()
中,我们只检查类是否正确。我尝试过,但当类出错时,它确实失败了,并且执行
devtools::test()
时的测试摘要是正确的,即它发现
walk()
调用运行4个测试,而不是1个

在下面的6个测试中,我检查每个绘图对象是否不同,即参数是否有作用,所有这些都是不同的。在我的例子中,由于我有4个版本,我需要测试6个(即,
选择(4,2)
)组合,以确保它们都是唯一的。比如说,如果我有10个参数要测试,这将需要编写大量手动代码(
choose(10,2)
=45)

所以我的问题是,当进行这样的测试时,什么是最佳实践?是否有一个函数允许测试每个对象的唯一性?我所能想到的最好的方法是循环输出:

> gtools::combinations(4, 2)
     [,1] [,2]
[1,]    1    2
[2,]    1    3
[3,]    1    4
[4,]    2    3
[5,]    2    4
[6,]    3    4
然后调用每一行:

expect_true(!identical(heatmaps[[v1]], heatmaps[[v2]]))

其中,
v1
v2
指的是以上列中的整数。

在您的具体案例中,我想说的是——无论您最终如何实施它们——这些测试几乎没有价值,其结果甚至可能不可信

这些测试没有什么价值,因为如果它们通过了,你仍然会得到非常有限的信息:你会知道所有的热图看起来都不一样(好吧,也许,见下文),但你不会知道它们看起来是否像你期望的那样。然而,尽管结果很差,但测试可能需要很长的时间,当添加其他热图样式时,测试甚至会大幅增加

就有限的信息而言,测试可能不可信:取决于ggplot的工作方式,即使外观相同的热图也可能不相等,例如,如果工具为每个生成的热图添加了一些时间戳。即使工具今天不能像这样工作,您也可能无法保证将来会这样。因此,即使您的测试通过,一些图可能看起来仍然相同,但比较起来不相等


当然,热图的外观是否符合您的要求,这是单元测试无法确定的。相反,您需要查看生成的输出—一个可能最好归类为系统测试的测试。

在您的特定情况下,我要说的是—无论您最终如何实现它们—这些测试几乎没有价值,甚至可能不可信

这些测试没有什么价值,因为如果它们通过了,你仍然会得到非常有限的信息:你会知道所有的热图看起来都不一样(好吧,也许,见下文),但你不会知道它们看起来是否像你期望的那样。然而,尽管结果很差,但测试可能需要很长的时间,当添加其他热图样式时,测试甚至会大幅增加

就有限的信息而言,测试可能不可信:取决于ggplot的工作方式,即使外观相同的热图也可能不相等,例如,如果工具为每个生成的热图添加了一些时间戳。即使工具今天不能像这样工作,您也可能无法保证将来会这样。因此,即使您的测试通过,一些图可能看起来仍然相同,但比较起来不相等


当然,热图的外观是否符合您的要求,这是单元测试无法确定的。相反,您需要查看生成的输出-一个可能最好归类为系统测试的测试。

我看不出您的建议有问题。我看不出您的建议有问题。可以解构
ggplot
s的属性,看看它们是否具有正确的层等(使用
ggplot\u build()
,请参阅),因此,可以进行更精确的这种性质的测试,但需要更多的编码来设置。在我的例子中,只知道它们产生不同的结果对我来说已经足够好了(这是我的私人软件包,不是很多$$$依赖于结果的东西)。我明白了-那么,如果性能对你来说也不是问题,我会说你的方法很好。如果性能在某个时间点成为一个问题,那么您可能会考虑为每个图创建一些散列值,而不是对这些图进行成对比较,比较散列。可以解构<代码> ggPrP>代码> s,以查看它们是否具有正确的层等(使用<代码> GGOPTTJBug()< <代码> >,请参阅)因此,可以进行更精确的这种性质的测试,但需要更多的编码来设置。在我的例子中,只知道它们产生不同的结果对我来说已经足够好了(这是我的私人软件包,不是很多$$$依赖于结果的东西)。我明白了-那么,如果性能对你来说也不是问题,我会说你的方法很好。如果性能在某个时间点成为一个问题,那么您可能会考虑为每个图创建一些散列值,而不是成对比较的曲线图,比较散列。