我正在使用 testthat 测试R包。为S3方法plot.foo
编写测试非常麻烦,因为它只返回NULL
,所以我决定将图保存到文件中,并检查自上次运行以来是否已更改。 >
pdf(file='plot_foo.pdf')
plot.foo(bar)
dev.off()
tools::md5sum('plot_foo.pdf')
问题是每次使用相同的输入获得不同的结果时。输出看起来一样。
replicate(10, {
pdf(file='plot.pdf')
plot(1:10, 10:1)
dev.off()
Sys.sleep(1)
tools::md5sum('plot.pdf')
})
请注意,每次迭代之间需要等待一段时间,否则文件将完全相同,这使我怀疑某些基于时间的元数据已更改。
plot.pdf plot.pdf
"5a0c096fe088342bc3c3d5960c5da1c9" "40d93c26b4901aef55a32b75473d05d2"
plot.pdf plot.pdf
"9815c6d9b2e94cda763a486fcd2ddf08" "a8e8db82d06b79f98416fa034b5aee46"
plot.pdf plot.pdf
"c2770250dbef3b60706559114c434851" "91c8cf124eb61ddebd3edbbb2d01677f"
plot.pdf plot.pdf
"d1594bd83b97fc890410a4c305366682" "f05197f165ec04df3dac4664494f4617"
plot.pdf plot.pdf
"64427124c6a6454e8f0e5944de20be95" "ff1abf2b31dfe688cf8f5994e409cc6d"
如何强制R生成一致的PDF?我出于测试目的暂时切换到PostScript,但是我更喜欢PDF,因为它得到了更好的支持(Windows似乎没有内置的PostScript查看器),因此也可以用作文档。
答案 0 :(得分:1)
虽然我认为在某些方面有些粗略,但我认为vdiffr
会让您做所需的事情。
首先,我将创建一个包;因为vdiffr
仅在严格控制的环境中起作用:使用testthat
的软件包。
usethis::create_package("~/StackOverflow/nalzok")
setwd("~/StackOverflow/nalzok")
usethis::use_testthat()
创建一个test_something.R
测试文件。
context("basic plot tests")
baseplot1 <- function() hist(1:10)
vdiffr::expect_doppelganger("base 1", baseplot1)
(我将假设hist(1:10)
是相关且有趣的东西。基本图解必须是一个函数,ggplot2
对象不是一个函数;有关更多信息,请参阅文档。)
我曾经以为我可以直接调用vdiffr::expect_doppelganger
(因为大多数testthat::expect_*
函数通常可以调用),但是首先需要对其进行“托管”(设置)。
vdiffr::manage_cases(".")
每个图像都需要(由人类进行)“验证”,因此这将打开一个闪亮的应用程序,该应用程序将遍历每个预期的doppelgangers:
验证后,每次test
软件包时,它将验证图像是否未更改:
devtools::test()
# Loading nalzok
# Testing nalzok
# v | OK F W S | Context
# v | 1 | basic plot tests
# == Results =====================================================================
# OK: 1
# Failed: 0
# Warnings: 0
# Skipped: 0
如果某些更改(例如将hist(1:10)
更改为hist(2:11)
),它将在下一个测试中失败:
devtools::test()
# Loading nalzok
# Testing nalzok
# v | OK F W S | Context
# x | 0 1 | basic plot tests
# --------------------------------------------------------------------------------
# test_something.R:3: failure: (unknown)
# Figures don't match: base-1.svg
# --------------------------------------------------------------------------------
# == Results =====================================================================
# OK: 0
# Failed: 1
# Warnings: 0
# Skipped: 0
它通过创建一个./tests/testthat/figs/
目录以及每个期望的目录和.svg
文件来做到这一点,尽管您不需要与之交互,但对于{{1} }进行版本控制(您执行对您的程序包进行版本控制,对吧?)。
一些警告,我想:
它正在保存到.../figs/
个文件中;如果您的S3 .svg
功能不能很好地与SVG配合使用(发生了吗?我不知道),那么我还不知道该如何处理;
因为它使用的是基于文本的SVG格式,所以它将注意到一个点或一个框或某物是否发生了移动,但仅在某些基本公差范围内;例如,即使足够更改了一些元参数(限制),也会触发故障。一般而言,这很好,因为我认为测试应该可以抵抗较小的更改(上游库等)。
plot.foo