30-Day Course
Clinical SAS → R
Day 29 of 30·ADaM, TLFs & Advanced Topics

Reproducibility, Validation & Environment Management

renv, double programming, unit tests and a qualified R environment.

Learning objectives

  • 1Use renv to create a reproducible, pinned package environment for a study.
  • 2Design a robust double-programming QC workflow with diffdf.
  • 3Write automated unit tests for derivation functions using testthat.
  • 4Understand what 'validated' or 'qualified' means for R in a regulated setting.

Key SAS® → R comparison

TaskSAS®R
Environment pinningSAS 9.4 + hotfix levelrenv.lock + renv::restore()
Dataset QCPROC COMPARE + manual reviewdiffdf + structured reports + CI checks
Function testingAd-hoc checks in drivertestthat::test_that() with expectations
QualificationIQ/OQ/PQ documentationSimilar rigor: package validation reports + locked env

Code examples

Setting up renv for a study
SAS®
/* No equivalent — everyone uses same SAS version */
R
# At project start
renv::init()

# After adding packages
renv::snapshot()

# Months later on any machine
renv::restore()   # exact same versions as original run

Note: The renv.lock file becomes part of the study archive — reviewers can see exactly which versions of admiral, dplyr, etc. were used.

Double programming with diffdf
SAS®
proc compare base=adam_prod compare=adam_qc;
  id usubjid paramcd;
  var aval chg;
run;
R
# Production programmer
adsl <- build_adsl(...)

# Independent QC programmer (different person)
qc_adsl <- build_adsl_qc(...)

diffdf(adsl, qc_adsl,
       keys = c("USUBJID"),
       tolerance = 1e-6)

Note: diffdf produces clear, actionable reports (missing rows, value differences, type mismatches) and integrates beautifully into automated validation pipelines.

Unit testing a derivation with testthat
SAS®
/* Usually manual or %assert macro */
R
test_that("derive_var_trtdurd handles missing dates correctly", {
  input <- tibble(USUBJID = "001", TRTSDT = as.Date("2020-01-01"), TRTEDT = NA)
  output <- derive_var_trtdurd(input)
  expect_true(is.na(output$TRTDURD))
})

Note: Small, focused tests for your most critical derivation functions give you fast feedback and serve as living documentation for the next programmer.

Explanation

The reproducibility story in R used to be the biggest objection from regulators and quality groups. renv largely closes that gap by giving you a one-file record of every package version used on a study — something SAS never provided natively.

Validation discipline translates directly. You still perform independent double programming for critical datasets. The tooling (diffdf + testthat) is simply more modern and produces better audit artifacts than the classic SAS approach.

Many sponsors now run formal qualification packages for the specific versions of R and key packages they intend to use in submissions — exactly analogous to the IQ/OQ/PQ work done for SAS. Once the environment is locked and qualified, the process is actually more reproducible than traditional SAS because the lockfile removes version ambiguity.

Practice exercise

Initialize an renv project for a small ADaM derivation script. Write 3-4 testthat tests for your most important derivation functions. Create an independent QC version of the ADaM and demonstrate clean reconciliation with diffdf. Snapshot the renv lockfile.