vdiffr 1.0.0

  ggplot2, testthat

  Lionel Henry

We’re delighted to announce the release of vdiffr 1.0.0. vdiffr is a testthat extension that makes it easy to automatically check code that generates R graphics. In particular, vdiffr is used by the ggplot2 team to ensure that changes and contributions do not affect the expected output of plots.

You can install vdiffr from CRAN with:


This blog post briefly introduces the vdiffr workflow and describes the changes in this 1.0 version. In the last section you will learn how to migrate your existing vdiffr snapshots to the new version. You can see a full list of changes in the release notes.

Attach these three packages to follow the examples:

Regression testing for R graphics

vdiffr is a testthat extension for monitoring the appearance of R plots and graphics over time. Its goals are to make it easy to test graphics, make it easy to review changes, and to be reproducible across platforms.

The only vdiffr function you will need to use is expect_doppelganger(). It takes a plot title and a plot object.

test_that("ggplot2 histogram works", {
  p <- ggplot(mtcars) + geom_histogram(aes(disp))
  expect_doppelganger("default histogram", p)

With base graphics a slightly different syntax is needed because base plots are created by side effects rather than by constructing a plot object as in ggplot2. In this case you can supply a function that generates the plot:

test_that("base histogram works", {
  p <- function() hist(mtcars$disp)
  expect_doppelganger("base histogram", p)

Then run devtools::test() as usual. The first time it is run, expect_doppelganger() generates a reproducible SVG file that represents the expected appearance of your plot and saves it inside your test folder. After that, the generated SVG is compared to the saved version and any mismatch is reported as a failure in the testthat output.

Note that, by default, mismatches do not cause failures on CRAN machines. That’s because testing the appearance of a plot is inherently fragile. Small upstream changes (e.g.┬áin the R graphics device or in the ggplot2 package) might cause subtle differences in the appearance of a plot that are not real failures. If every such change caused a CRAN failure this would be distracting for both you and the CRAN maintainers. This is why vdiffr expectations only report failures when they are ran locally or in your CI platform. This allows you to monitor the appearance of your plots over time without causing distracting and time-consuming failures on CRAN.

New snapshot management system via testthat 3

The main user visible change in vdiffr 1.0.0 is the replacement of the case management system and the accompanying Shiny app by the snapshot system introduced in testthat 3. Following this change, a lot of vdiffr code has been removed and the package is now a simple generator of reproducible SVGs.

Snapshot management in testthat 3 is much more straightforward than the mechanism in previous versions of vdiffr.

  • New cases are automatically recorded in the snapshot folder. They no longer need to be validated via the Shiny app.

  • Orphaned cases are automatically deleted from the snapshot folder.

  • Failures are reviewed with testthat::snapshot_review(), a minimalist Shiny app powered by the diffviewer package.

This workflow integrates nicely with other kinds of testthat snapshots such as error, warning, or output snapshots.

A simpler SVG engine

To generate reproducible snapshots, vdiffr embeds an SVG generation engine based on svglite. This engine has been updated and simplified.

  • The main user-visible change from this update is that points now look smaller in the new SVGs. In the old snapshots they were too large.

  • The computation of character sizes is now hardcoded which allowed us to simplify the dependencies of vdiffr. It should also be less maintenance work for us in the long term.

Migrating existing vdiffr snapshots

Because of the switch to testthat 3 snapshots and the update to the SVG engine, you will need to regenerate all of your figures if you are an existing vdiffr user. Thankfully the process is straightforward and only includes two steps.

  1. This step is optional. Since the update to the SVG engine alters the appearance of your plots, you might want to review the changes. To do so, install the github-only 0.4.0 version of vdiffr with remotes::install_github("r-lib/vdiffr@v0.4.0"). This release only contains the new SVG engine. You can then review the snapshot changes as usual with vdiffr::manage_cases().

  2. Install vdiffr 1.0.0 from CRAN. Delete the tests/figs directory where the old snapshots were saved (they will now be saved in tests/testthat/_snaps) and run devtools::test() to generate the new snapshots.

Please let us know of any trouble during migration, we’re here to help!


vdiffr 1.0.0 wouldn’t be possible without my colleague Thomas Lin Pedersen. His experience with R graphics device ( raggs, textshaping, …) was crucial to the update and simplification of the SVG engine. Thanks Thomas!

We also would like to thank all the issues and code contributors for this release: @aghaynes, @IndrajeetPatil, @JauntyJJS, @jgabry, @krassowski, @mtalluto, @pat-s, @rfaelens, and @Sumidu.