Snapshot testing for R objects

Description

A flexible wrapper around testthat::expect_snapshot_file() that allows snapshotting any R object, not just data.frames. This function provides a convenient interface for snapshot testing with sensible defaults for serialization.

When using RDS format (the default), snapshots are compared using waldo::compare() which provides rich, visual diffs in testthat::snapshot_review(). This makes it much easier to review changes to complex R objects.

Usage

expect_snapshot_object(
  x,
  name,
  writer = save_rds,
  print = FALSE,
  tolerance = NULL,
  ...
)

Arguments

x An R object to snapshot. Can be any R object including lists, models, data.frames, vectors, etc.
name character snapshot name (file extension added automatically)
writer function Function to write the object to a file. Default is save_rds(). Other options include save_json(), save_deparse(), save_csv(). Custom writer functions should accept x and return a file path.
print logical whether to print waldo::compare output to R console; can become very long for complex objects like lms
tolerance If non-NULL, used as threshold for ignoring small floating point differences when comparing numeric vectors. Only applies when writer produces an RDS file (the default); silently ignored for text-based formats (JSON, CSV, deparse, etc.). See waldo::compare() for full details.

Arguments passed on to testthat::expect_snapshot_file

binary
[Deprecated] Please use the compare argument instead.
cran
Should these expectations be verified on CRAN? By default, they are not, because snapshot tests tend to be fragile because they often rely on minor details of dependencies.
transform
Optionally, a function to scrub sensitive or stochastic text from the output. Should take a character vector of lines as input and return a modified character vector as output.
variant

If not-NULL, results will be saved in _snaps/{variant}/{test}/{name}. This allows you to create different snapshots for different scenarios, like different operating systems or different R versions.

Note that there’s no way to declare all possible variants up front which means that as soon as you start using variants, you are responsible for deleting snapshot variants that are no longer used. (testthat will still delete all variants if you delete the test.)
old,new
Paths to old and new snapshot files.

Details

When using RDS format (the default), snapshots can vary across R versions and platforms even with fixed serialization versions. Consider using variant = platform_variant() for RDS snapshots to handle these differences, or use text-based formats like JSON or deparse for more stable snapshots across platforms and versions.

The RDS comparison uses waldo::compare() internally, which provides rich visual diffs in testthat::snapshot_review(). This is particularly useful for complex objects like models, nested lists, or data structures where byte-level comparison would be difficult to interpret.

Value

NULL (from testthat::expect_snapshot_file())

Examples

Code
library("snapr")


# expect_snapshot_object() must be called inside a test_that() block with
# testthat 3rd edition active. Outside a test suite, the snapshot is
# skipped because there is no reference file to compare against.
withr::with_tempdir({
  testthat::test_that("snapshot examples", {
    testthat::local_edition(3)

    # Snapshot a list (RDS format with platform/version variant)
    expect_snapshot_object(
      list(a = 1, b = 2), name = "config", variant = platform_variant()
    )

    # Snapshot a model
    model <- lm(mpg ~ wt, data = mtcars)
    expect_snapshot_object(
      model, name = "model", variant = platform_variant()
    )

    # Snapshot with JSON format (for human-readable diffs)
    # Text formats don't need variants
    expect_snapshot_object(iris[1:5, ], name = "iris", writer = save_json)

    # Snapshot with deparse format
    expect_snapshot_object(
      list(x = 1:5), name = "simple_list", writer = save_deparse
    )
  })
})
── Snapshot ────────────────────────────────────────────────────────────────────
/tmp/Rtmp3a7Dan/file1c331d40e492.rds
────────────────────────────────────────────────────────────────────────────────
── Snapshot ────────────────────────────────────────────────────────────────────
/tmp/Rtmp3a7Dan/file1c3378eea514.rds
────────────────────────────────────────────────────────────────────────────────
── Snapshot ────────────────────────────────────────────────────────────────────
/tmp/Rtmp3a7Dan/file1c333fee0dd2.json
────────────────────────────────────────────────────────────────────────────────
── Snapshot ────────────────────────────────────────────────────────────────────
/tmp/Rtmp3a7Dan/file1c33528841d0.txt
────────────────────────────────────────────────────────────────────────────────
── Skip: snapshot examples ─────────────────────────────────────────────────────
Reason: empty test