vdiffr icon indicating copy to clipboard operation
vdiffr copied to clipboard

Support compressed svg in snapshot tests

Open gavinsimpson opened this issue 2 years ago • 7 comments

In relation to r-lib/vdiffr#126 could testthat support compressed svgs produced by {svglite}? It seems that it should be pretty simple to decompress the svg in testthat::compare_file_text using gzfile() of gzcon(), so {brio} doesn't need to support gz compressed files natively. I haven't looked what might be required in the shiny app to review snapshots.

The main use case for this is massively reducing the filesize of SVG snapshots produced by {vdiffr}. This is causing issues with the size of the tarball produced by R CMD build, which are being flagged by CRAN's incoming checks.

Why do we have such large SVGs? Checking these images produced from statistical models seems very sensitive to small differences in the fitted model due to OS differences etc, that go away with larger data. But then plotting outputs from these models often involves plotting data, which inflates the sizes of resulting plots. Regardless, reducing the file size of SVG snapshots would be good in terms of CRAN's policy on retention of package sources.

If you agree this is useful, would it be best to limit such a change to supporting only compressed svg or allowing tests of compressed text files more generally? Only gz compression or others? I'd happily produce a PR implementing the above if there is interest.

gavinsimpson avatar Jan 30 '23 09:01 gavinsimpson

I think the place to start would be to prototype a custom compare function that you can pass to expect_snapshot_file(). If that's sufficient, we can figure out how to include in vdiffr. If it's not enough, it'll suggest what other changes are needed in testthat.

hadley avatar Mar 23 '23 13:03 hadley

Returning to this, here is a pair of functions implementing the compare function @hadley suggested I start with

library("svglite")

# functions for testthat compare
read_svg <- function(f) {
  f <- if (identical(tools::file_ext(f), "svgz")) {
    fc <- gzfile(f)
    on.exit(close(fc))
    base::readLines(fc)
  } else {
    base::readLines(f)
  }
  f
}
compare_file_text_svg <- function(old, new) {
  old <- read_svg(old)
  new <- read_svg(new)
  identical(old, new)
}

# helper to do a plot and store it in temp file as a svg
save_svg <- function(code, compress = FALSE, width = 10, height = 8, ...) {
  extn <- ifelse(compress, ".svgz", ".svg")
  path <- tempfile(fileext = extn)
  svglite::svglite(path, width = width, height = height, ...)
  on.exit(dev.off())
  code

  path
}

# generate some plots
p1 <- save_svg(plot(1:10), compress = TRUE)
p2 <- save_svg(plot(1:5), compress = TRUE)
p3 <- save_svg(plot(1:10), compress = FALSE)

# compare them
compare_file_text_svg(p1, p1) # want this to be TRUE
#> [1] TRUE
compare_file_text_svg(p1, p2) # this should be FALSE
#> [1] FALSE
compare_file_text_svg(p1, p3) # want this to be TRUE
#> [1] TRUE

Created on 2024-03-27 with reprex v2.1.0

brio::read_lines() doesn't handle connections so I switched to using base::readLines() for the compressed version. I'm not sure if this matters, or whether it is safer to use

gavinsimpson avatar Mar 27 '24 11:03 gavinsimpson

@gavinsimpson how much have you been able to reduce your _snaps folder using this method? And any chance this will be implemented in testthat any time soon?

willgearty avatar Oct 16 '24 15:10 willgearty

@willgearty I can't recall now, but it was not insignificant.

gavinsimpson avatar Oct 19 '24 11:10 gavinsimpson

IMO this is a vdiffr feature, not a testthat feature.

hadley avatar Oct 29 '24 13:10 hadley

@hadley I was under the impression that this would need vdiffr modifications to write the compressed svg snapshots, and support for reading compressed text files in testthat to do the actual testing/comparison.

gavinsimpson avatar Oct 29 '24 15:10 gavinsimpson

I'm pretty sure this only needs vdiffr, since vdiffr can pass compare = compare_file_text_svg to expect_snapshot_file(). So I'm going to move this issue to vdiffr.

hadley avatar Aug 08 '25 19:08 hadley