Getting Started with snapr

Introduction

Snapshot testing captures the output of a function or computation and saves it to a file. On subsequent test runs, the output is compared to the saved snapshot. If the output changes, the test fails — alerting you to unexpected behaviour.

snapr builds on top of testthat’s expect_snapshot_file() to provide convenient helpers for common R objects:

Installation

Install the development version from GitHub:

# install.packages("pak")
pak::pak("d-morrison/snapr")

Basic Workflow

Snapshot tests live inside test_that() blocks, just like any other testthat expectation.

Snapshot a data.frame

Use expect_snapshot_data() when you want a human-readable CSV snapshot:

library(snapr)

test_that("iris subset is stable", {
  expect_snapshot_data(iris[1:5, ], name = "iris_head")
})

The first time you run this test, snapr creates tests/testthat/_snaps/iris_head.csv. On subsequent runs the data.frame is compared against that file and the test fails if anything has changed.

Snapshot any R object

Use expect_snapshot_object() for objects that cannot be easily represented as a CSV. The default writer (save_rds()) stores the object as an .rds file and uses diffobj to produce human-readable diffs during review:

test_that("model structure is stable", {
  model <- lm(mpg ~ wt, data = mtcars)
  expect_snapshot_object(model, name = "mpg_model")
})

Choosing a Writer

The writer argument of expect_snapshot_object() controls the file format. snapr ships four built-in writers:

Writer Format Best for
save_rds() .rds (binary) Any R object; rich diffs via diffobj
save_json() .json (text) Lists and data that map cleanly to JSON
save_csv() .csv (text) data.frames (also used by expect_snapshot_data())
save_deparse() .txt (text) Simple objects; always human-readable

JSON example

test_that("config list is stable", {
  config <- list(name = "my_app", version = "1.0.0", debug = TRUE)
  expect_snapshot_object(config, name = "config", writer = save_json)
})

Deparse example

test_that("simple list is stable", {
  expect_snapshot_object(list(x = 1:3), name = "simple", writer = save_deparse)
})

Handling Platform Differences

Some R objects (particularly RDS files and results from numerical algorithms) can differ across operating systems or R versions. snapr provides helper functions to create variant strings that are appended to snapshot names, keeping snapshots separate per platform:

Function Variant string Use when…
system_os() "linux", "darwin", "windows" Output differs by OS only
darwin_variant() "darwin" / NULL Only macOS differs; Linux & Windows share one snapshot
platform_variant() "linux-4.4" etc. Output differs by both OS and R version
test_that("RDS snapshot is platform-safe", {
  result <- list(x = rnorm(3))
  expect_snapshot_object(
    result,
    name = "result",
    variant = platform_variant()
  )
})

Text-based formats (JSON, CSV, deparse) typically produce identical output across platforms and do not require a variant.

Reviewing Snapshots

When a snapshot test fails, you can interactively review the differences with:

testthat::snapshot_review()

This opens a Shiny app that displays the old and new snapshots side-by-side, letting you accept or reject each change.

For richer, visual diffs when reviewing RDS snapshots, install the d-morrison/diffviewer fork of diffviewer. This fork wraps diffobj to compare deserialized R objects with arbitrary structures rather than raw bytes:

pak::pak("d-morrison/diffviewer")

To accept all new snapshots at once (e.g., after an intentional change):

testthat::snapshot_accept()

Summary

Task Function
Snapshot a data.frame expect_snapshot_data(x, name)
Snapshot any object (RDS) expect_snapshot_object(x, name)
Snapshot as JSON expect_snapshot_object(x, name, writer = save_json)
Snapshot as CSV expect_snapshot_object(x, name, writer = save_csv)
Snapshot as plain text expect_snapshot_object(x, name, writer = save_deparse)
OS-specific variant variant = system_os()
macOS-only variant variant = darwin_variant()
OS + R-version variant variant = platform_variant()
Review failing snapshots testthat::snapshot_review()
Accept new snapshots testthat::snapshot_accept()