Title: Result Stability Checks for Empirical R Projects
Version: 0.1.4
Description: Lightweight helpers for checking whether empirical results remain substantively unchanged across code revisions, platform differences, and package updates. The package supports regression-style testing of derived datasets, statistical model outputs, tables, and plots, helping researchers detect unintended result drift early and distinguish material from non-material changes in empirical workflows.
License: MIT + file LICENSE
Encoding: UTF-8
RoxygenNote: 7.3.3
Imports: withr, rprojroot, yaml
Suggests: knitr, rmarkdown, testthat (≥ 3.0.0), waldo
URL: https://github.com/kv9898/resultcheck/, https://kv9898.github.io/resultcheck/
BugReports: https://github.com/kv9898/resultcheck/issues
VignetteBuilder: knitr
NeedsCompilation: no
Packaged: 2026-04-14 12:24:32 UTC; Dianyi
Author: Dianyi Yang ORCID iD [aut, cre, ctb]
Maintainer: Dianyi Yang <dianyi.yang@politics.ox.ac.uk>
Repository: CRAN
Date/Publication: 2026-04-21 08:52:09 UTC

Get project root for sandbox operations

Description

Internal helper to get project root, falling back to current directory if root cannot be determined.

Usage

.get_project_root()

Value

Character path to project root or current working directory


Reset sandbox state (internal)

Description

Reset sandbox state (internal)

Usage

.reset_last_sandbox()

Clean Up a Sandbox Environment

Description

Removes a sandbox directory and all its contents. This should be called after testing is complete to free up disk space.

Usage

cleanup_sandbox(sandbox = NULL, force = TRUE)

Arguments

sandbox

Optional. A sandbox object created by setup_sandbox(). If NULL (default), cleans up the most recently created sandbox.

force

Logical. If TRUE (default), removes directory even if it contains files.

Value

Logical indicating success (invisible).

Examples

with_example({
  sandbox <- setup_sandbox()
  cleanup_sandbox(sandbox)
})

Compare Two Snapshot Values

Description

Compares two serialized snapshots and returns differences.

Usage

compare_snapshot_text(old_text, new_text, precision = NULL)

Arguments

old_text

Character vector with old snapshot text.

new_text

Character vector with new snapshot text.

precision

Optional integer. When non-NULL, both texts are rounded to this many decimal places before comparison (see round_snapshot_numbers). Useful for ignoring floating-point noise introduced by platform differences.

Value

A character vector of differences, or NULL if identical.


Find Project Root Directory

Description

Finds the root directory of the current R project using various heuristics. The function searches for markers like _resultcheck.yml (preferred), resultcheck.yml (legacy), .Rproj files, or a .git directory. When running inside a sandbox created by setup_sandbox(), it will search from the original working directory.

Usage

find_root(start_path = NULL)

Arguments

start_path

Optional. The directory to start searching from. If NULL (default), uses the current working directory or the stored original working directory if in a sandbox.

Value

The path to the project root directory.

Examples

with_example({
  root <- find_root()
  print(root)
})

Get Snapshot File Path

Description

Constructs the path to a snapshot file within the project's snapshot directory. Snapshot files are stored under tests/_resultcheck_snaps/ by default, organized by script name. This location can be overridden with snapshot.dir in _resultcheck.yml.

Usage

get_snapshot_path(name, script_name = NULL, ext = "md")

Arguments

name

Character. The name of the snapshot (without extension).

script_name

Optional. The name of the script file creating the snapshot. If NULL, attempts to detect from the call stack.

ext

Character. The file extension for the snapshot file (default: "md").

Value

The full path to the snapshot file.


Get start path for find_root

Description

Helper function to determine the starting path for find_root(). Checks for stored sandbox WD first, then falls back to getwd().

Usage

get_start_path_for_find_root()

Value

Character path to start searching from


Detect Testing Context

Description

Determines if code is running in a testing context (sandbox via run_in_sandbox). This is used to change snapshot() behavior: interactive mode prompts for updates, while testing mode throws errors on mismatch.

Usage

is_testing()

Value

Logical indicating if in testing mode.


Mask [ignored] Lines in New Snapshot Text

Description

Any line in old_text that equals "[ignored]" (after trimming whitespace) causes the corresponding line in new_text to be replaced with "[ignored]", so that known-volatile lines never trigger a snapshot failure. Lines beyond the shorter vector are left unchanged.

Usage

mask_ignored_lines(old_text, new_text)

Arguments

old_text

Character vector of the stored snapshot lines.

new_text

Character vector of the freshly generated snapshot lines.

Details

This helper is used both during comparison (so the lines are skipped) and when writing an updated snapshot (so the markers are preserved).

Value

new_text with [ignored] substituted at matching positions.


Normalize Snapshot Text Before Comparison

Description

Replaces volatile environment representations (for example memory addresses in .Environment attributes) with a stable placeholder so snapshots remain comparable across different execution contexts.

Usage

normalize_snapshot_text(text)

Arguments

text

Character vector with serialized snapshot lines.

Value

Character vector with normalized snapshot lines.


Read resultcheck Configuration

Description

Reads configuration settings from the _resultcheck.yml file located at the project root (falling back to legacy resultcheck.yml if needed). Returns an empty list if neither file exists or parsing fails.

Usage

read_resultcheck_config()

Value

A named list of configuration values, or an empty list.


Round Floating-Point Numbers in Snapshot Text

Description

Replaces every floating-point literal (decimal or scientific notation) found in a character vector of snapshot lines with its value rounded to digits decimal places. Integer literals that contain no decimal point and no exponent are left untouched, so index ranges such as [1:1071] are never modified.

Usage

round_snapshot_numbers(text, digits)

Arguments

text

Character vector of snapshot text lines.

digits

Integer; number of decimal places to keep (passed to round()). Must be a finite integer.

Details

digits is passed directly to round: 0 rounds to the nearest integer, negative values round to the left of the decimal point.

Value

Character vector with floating-point numbers rounded.


Run Code in a Sandbox Environment

Description

Executes an R script within a sandbox directory, suppressing messages, warnings, and graphical output. This is useful for testing empirical analysis scripts without polluting the console or creating unwanted plots.

Usage

run_in_sandbox(
  script_path,
  sandbox = NULL,
  suppress_messages = TRUE,
  suppress_warnings = TRUE,
  capture_output = TRUE
)

Arguments

script_path

Path to the R script to execute.

sandbox

Optional. A sandbox object created by setup_sandbox(). If NULL (default), uses the most recently created sandbox.

suppress_messages

Logical. Whether to suppress messages (default: TRUE).

suppress_warnings

Logical. Whether to suppress warnings (default: TRUE).

capture_output

Logical. Whether to capture output (default: TRUE).

Value

Invisible TRUE on successful execution.

Examples

with_example({
  sandbox <- setup_sandbox()
  on.exit(cleanup_sandbox(sandbox), add = TRUE)
  run_in_sandbox("analysis.R", sandbox)
})

Serialize Value to Human-Readable Text

Description

Converts an R object to a human-readable text representation for snapshots.

Usage

serialize_value(value, method = c("both", "print", "str"))

Arguments

value

The R object to serialize.

method

Character. Controls which serialization method(s) are used. "both" (default) uses both print() and str(). "print" uses only print(). "str" uses only str().

Value

A character vector with the text representation.


Setup a Sandbox Environment for Testing

Description

Creates a temporary directory and copies specified files and/or directories into it while preserving their path structure. This is useful for testing empirical analysis scripts in isolation.

Usage

setup_sandbox(files = NULL, temp_base = NULL)

Arguments

files

Character vector of relative file or directory paths to copy to the sandbox. Leave as NULL (default) to create an empty sandbox. Paths are resolved relative to the project root (found using find_root()); if the project root cannot be determined the current working directory is used. When a path refers to a directory, the entire directory is copied recursively. Absolute paths and path traversal attempts (e.g., ..) are rejected for security. Snapshot files do not need to be listed here: snapshot() always reads snapshots from the project root, not from the sandbox.

temp_base

Optional. Custom location for the temporary directory. If NULL (default), uses tempfile().

Value

A list with class "resultcheck_sandbox" containing:

path

The path to the created temporary directory

id

A unique timestamp-based identifier for this sandbox

Examples

with_example({
  sandbox <- setup_sandbox()
  print(sandbox$path)
  cleanup_sandbox(sandbox)
})

Interactive Snapshot Testing

Description

Creates or updates a snapshot of an R object for interactive analysis. On first use, saves the object to a human-readable snapshot file (.md). On subsequent uses, compares the current object to the saved snapshot.

Usage

snapshot(value, name, script_name = NULL, method = c("both", "print", "str"))

Arguments

value

The R object to snapshot (e.g., plot, table, model output).

name

Character. A descriptive name for this snapshot.

script_name

Optional. The name of the script creating the snapshot. If NULL, attempts to auto-detect from the call stack.

method

Character. Controls which serialization method(s) are used when capturing the snapshot. "both" (default) applies type-specific logic that uses both print() and str(). "print" uses only print(), and "str" uses only str(). Use "print" or "str" when one of the methods produces volatile output that should be excluded from the snapshot (e.g. objects that embed session-specific paths or IDs in their str() representation).

Details

In interactive mode (default), prompts the user to update if differences are found and emits a warning. In testing mode (inside testthat or run_in_sandbox), throws an error if snapshot doesn't exist or doesn't match.

Snapshots are stored under tests/_resultcheck_snaps/ by default, organized by script name, and configurable via snapshot.dir in _resultcheck.yml.

Value

Invisible TRUE if snapshot matches or was updated. In testing mode, throws an error if snapshot is missing or doesn't match.

Examples

with_example({
  model <- stats::lm(mpg ~ wt, data = datasets::mtcars)
  snapshot(model, "model_both", script_name = "analysis", method = "both")
  snapshot(model, "model_print", script_name = "analysis", method = "print")
  snapshot(model, "model_str", script_name = "analysis", method = "str")
})

with_example({
  sandbox <- setup_sandbox()
  on.exit(cleanup_sandbox(sandbox), add = TRUE)
  run_in_sandbox("analysis.R", sandbox)
})

if (interactive()) with_example({
  sandbox <- setup_sandbox()
  on.exit(cleanup_sandbox(sandbox), add = TRUE)
  run_in_sandbox("analysis.R", sandbox)
}, mismatch = TRUE)

Run Code Inside a Temporary Example Project

Description

Creates a self-contained example project under tempdir(), including:

then temporarily sets the working directory to that project while evaluating code.

Usage

with_example(code, mismatch = FALSE)

Arguments

code

Code to evaluate inside the temporary example project.

mismatch

Logical. If TRUE, replaces the active snapshot with a mismatched version before evaluating code.

Value

The value of code.

Examples

with_example({
  root <- find_root()
  print(root)
})