Tests to compare plots for R packages
This is for vdiffr version 1.0.2.9000. The package is in development so syntax and behavior is likely to change. Read the testing chapter in the R packages book for background on writing tests for R packages.
https://vdiffr.r-lib.org/ is a package that integrates with the testthat package to allow tests that compare plot outputs.
usethis::use_testthat()
Makes the tests
folder and testthat
subfolder.
Within the testthat
folder,
usethis::use_test(name="xyz")
This will make a test file test-xyz.R
in the testthis
subfolder. When you make your own test files, replace “xyz” with your test name.
To run the tests, you can open test-xyz.R
in RStudio and it will recognize that this is a test file. “Run tests” will show up on the upper right of the file.
The first time that you run expect_doppelganger("xyz", plt1)
within a test_that()
call, a snapshot expectation will run and a svg of plt1
will be made in tests/testthat/_snaps/xyz
called xyz.svg
. The next time expect_doppelganger("xyz", plt2)
is run within a test_that()
call, a svg of plt2
will be made and compared to xyz.svg
. If it is different, the file xyz.new.svg
will be made in tests/testthat/_snaps/xyz
.
Because of this workflow, we want to make sure tests/testthat/_snaps/xyz
is empty before we start because we have to run expect_doppelganger("xyz", plt1)
to create xyz.svg
but if xyz.svg
is already there from previous tests, we might end up creating xyz.new.svg
if plt1
is a different plot than xyz.svg
.
The full test-xyz.R
test file is below. Here I break down the parts of that file.
Give some info about the tests (context
), load packages, and then clean up the _snaps
folder. Having old svgs there can mess up your tests.
context("xyz")
library(ggplot2)
library(vdiffr)
# Clean up the _snaps folder for this test file
# Note this won't be necessary in some situations
fils <- dir(file.path(here::here(), "tests", "testthat", "_snaps", "xyz"), full.names = TRUE)
file.remove(fils)
Here is the contents of test-xyz.R
to compare two plots. This test should fail because the plots are different.
expect_doppelganger()
to create a svg file in _snaps
that is used to compare against. The name of the file is the first argument and must be the same in the expect_doppelganger()
calls.plt <- ggplot(mtcars, aes(mpg)) + geom_histogram()
# Save as ggplot-test1.svg in _snaps folder
# This will appear as a successful test, i.e. plot successfully created
test_that("setup", {
expect_doppelganger("ggplot-test1", plt)
})
ggplot-test1.svg
already in _snaps
folder.plt <- ggplot(mtcars, aes(disp)) + geom_histogram()
test_that("plots are different", {
expect_doppelganger("ggplot-test1", plt)
})
Since they are different, you will see ggplot-test1.new.svg
in the _snaps
folder.
The syntax here is a little different. The object that you pass into expect_doppelganger()
as the second argument is a function that creates the base plot. Otherwise the steps are the same.
plt <- function(){ hist(mtcars$mpg) }
# Step 1. Create base-test.svg
# This will appear as a successful test, i.e. plot successfully created
test_that("setup", {
expect_doppelganger("base-test", plt)
})
# Step 2. Test new plot against base-test.svg
# Test will fail since they are different
plt <- function(){ hist(mtcars$disp) }
test_that("plots are different", {
expect_doppelganger("base-test", plt)
})
test-xyz.R
fileThis should be in the testthat
folder in tests
folder. Running this will show 2 Fails and 4 Passes. To run, you can open the file in RStudio and look for the “Run Tests” button in top right of file. Or run this code.
fil <- file.path(here::here(), "tests", "testthat", "test-xyz.R")
testthat::test_file(fil)
Or open the file in RStudio and run this code:
devtools::test_active_file()
The full test file.
context("xyz")
library(ggplot2)
library(vdiffr)
# Clean up the _snaps folder for this test file
# Note this won't be necessary in some situations
fils <- dir(file.path(here::here(), "tests", "testthat", "_snaps", "xyz"), full.names = TRUE)
file.remove(fils)
# This test should fail. The plots are different
# Step 1 make first plot
plt <- ggplot(mtcars, aes(mpg)) + geom_histogram()
# Save as ggplot-test1.svg in _snaps folder
# This will appear as a successful test, i.e. plot successfully created
test_that("setup", {
expect_doppelganger("ggplot-test1", plt)
})
# Step 2. Create 2nd plot and compare to ggplot-test1.svg in _snaps folder
plt <- ggplot(mtcars, aes(disp)) + geom_histogram()
test_that("plots are different", {
expect_doppelganger("ggplot-test1", plt)
})
# Since they are different, you will see ggplot-test1.new.svg in the _snaps folder
# This test should not fail. The plots should be the same.
fun <- function(dat){ return(ggplot(dat, aes(mpg)) + geom_histogram()) }
plt <- fun(mtcars)
# Step 1. Create ggplot-test2.svg
# This will appear as a successful test, i.e. plot successfully created
test_that("setup", {
expect_doppelganger("ggplot-test2", plt)
})
# Step 2. Test new plot against ggplot-test2.svg
plt <- fun(na.omit(mtcars))
test_that("plots are the same", {
expect_doppelganger("ggplot-test2", plt)
})
# Since they are the same, you will NOT see ggplot-test2.new.svg in the _snaps folder
# Comparing plots made with base graphics; Create a function that makes the plot
plt <- function(){ hist(mtcars$mpg) }
# Step 1. Create base-test.svg
# This will appear as a successful test, i.e. plot successfully created
test_that("setup", {
expect_doppelganger("base-test", plt)
})
# Step 2. Test new plot against base-test.svg
# Test will fail since they are different
plt <- function(){ hist(mtcars$disp) }
test_that("plots are different", {
expect_doppelganger("base-test", plt)
})
For attribution, please cite this work as
Holmes (2021, Sept. 28). R-Govys: vdiffr package. Retrieved from https://rgovys.github.io/posts/2021-09-28-vdiffr/
BibTeX citation
@misc{holmes2021vdiffr, author = {Holmes, E. Eli}, title = {R-Govys: vdiffr package}, url = {https://rgovys.github.io/posts/2021-09-28-vdiffr/}, year = {2021} }