courieR is transparent about how it is tested. This document describes the test suite, how to run it on your machine (or as an automated agent), and the current verification status across platforms.
The package is fully AI-implemented and human-directed. Both human and agent testers are listed in the status table below.
Test suite overview
Tests live in tests/testthat/ and are organised into
three layers:
| Layer | Files | What it covers |
|---|---|---|
| Unit |
test-inventory.R, test-manifest.R,
test-ship.R, test-copy-packages.R,
test-estimate.R, and ~12 more |
Pure R logic — comparison, plan building, log parsing, route filtering, rate calibration |
| Integration |
test-find_routes.R, test-migrate.R,
test-wrap.R
|
Spawns real R subprocesses; needs at least one R installation;
guarded with skip_on_cran()
|
| End-to-end (E2E) |
test-e2e-ship.R, test-app-refresh.R
|
Drives the full Shiny dashboard in a headless Chrome browser;
requires two R installations, a Chrome binary, and
COURIER_E2E=true
|
Running tests
1. Unit + integration tests (standard)
# From an R session in the package root
devtools::test()
# Or from the shell
R CMD check --no-manual .All unit tests and CRAN-safe integration tests run without any
environment variables. Tests that spawn subprocesses or modify libraries
are guarded with skip_on_cran() and will run locally but
not on CRAN.
2. E2E browser tests
The E2E tests drive the full dashboard UI with a real Chrome browser
through shinytest2 and chromote. They
require:
- Two real R installations (source and target must differ in version or path)
- Chrome or Chromium installed
-
shinytest2andchromoteR packages - The working-tree courieR installed first
(
R CMD INSTALL .)
# 1. Install working-tree version (required — app subprocess does library(courieR))
R CMD INSTALL .
# 2. Set environment variables
export COURIER_E2E=true
export COURIER_E2E_SRC=/path/to/source/Rscript # e.g. /opt/R/4.4.3/bin/Rscript
export COURIER_E2E_TGT=/path/to/target/Rscript # e.g. /opt/R/4.5.2/bin/Rscript
export COURIER_E2E_TGT_LIB=/path/to/target/library # writable target library dir
# 3. Run
Rscript -e "testthat::test_file('tests/testthat/test-e2e-ship.R')"The E2E test:
- Opens the dashboard in a 1500×950 headless browser
- Picks source and target in Bulk Dispatch, clicks Compare, previews the plan
- Switches to Custom Dispatch, searches for a test
package (
broman), selects offline mode, ships it - Verifies independently (via
manifest()in a clean subprocess) that the package was installed into the target library with a valid layout and is loadable from target R
3. Manual Shiny UI checklist
Run hub() and work through the checklist below. The E2E
test covers the same paths automatically, but manual testing catches
visual regressions and UX issues that browser automation misses.
CLI
library(courieR)
# Startup message shows version, hub(), ?ship, and the vignette link
report_issue("test error message")
# Should open a pre-filled GitHub issue in the browser
find_routes()
# Should find all R installations on the machine
vignette("get-started", package = "courieR")
# Should open the HTML user guidePlatform test status
Last updated: 2026-06-13.
| Platform | Tester | Unit tests | Integration | E2E browser | Manual UI |
|---|---|---|---|---|---|
| Windows 11 (OneDrive + Defender) | Human — Lennon Li | ✅ | ✅ | ⬜ | ✅ |
| Linux — WSL2 Ubuntu 24.04, R 4.6.0 | Agent — Claude Code (Ming) | ✅ | ✅ | ✅ | ✅ partial |
| macOS — Mac mini, Apple Silicon, R 4.6.0 | Agent — Claude Code | ✅ | ✅ | ⬜ | ⬜ |
Legend: ✅ pass · ❌ fail · ⚠️ pass with caveats · ⬜ not yet run
Windows notes
- Probe timeouts were the trigger for raising
find_routes()timeout from 3 s to 30 s. Cold-started R on OneDrive-synced drives regularly exceeded 3 s, causing installations to flicker in and out between scans. - E2E browser tests require Chrome and
chromote. These have not been run on Windows;skip_if_not_installed("chromote")protects the test suite. -
R CMD check --no-manualpasses (inconsolata.sty is absent;--no-manualskips the PDF reference manual).
Linux notes
- Tested on WSL2 Ubuntu 24.04 with R 4.6.0 (
/usr/bin/R). Per-version libraries live under~/R/x86_64-pc-linux-gnu-library/<version>/. - E2E test verified the
.copy_plan()nesting bug fix end-to-end: package installed with a valid layout and loadable from target R. -
R CMD check --as-cran --no-manualproduces 0 errors, 0 warnings, 0 notes.
macOS notes
Results — 2026-06-13, Mac mini (Apple Silicon), R 4.6.0
devtools::test(): FAIL 0 | WARN 0 | SKIP 16 | PASS
180
devtools::check(manual = FALSE, vignettes = FALSE): 0
errors | 0 warnings | 1 note
The 1 note is the ::: call to
.build_issue_url() inside
mod_error_reporter.R. This is intentional — the function is
package-internal and called only from the embedded Shiny app, not from
user code.
macOS-specific quirks discovered
/var→/private/varsymlink.withr::local_tempdir()returns paths under/var/folders/..., butfind_routes()normalises paths viafs::path_real(), resolving them to/private/var/folders/.... The test"find_routes detects installs whose probe takes longer than 3s"was failing becausefake %in% res$rscript_pathcompared the unresolved path against the resolved one. Fixed by wrappingfakeinfs::path_real()in the test assertion.CRAN framework
R_HOMEoverwrite. The official CRAN macOS framework wrapper scripts (Resources/bin/R) hardcodeR_HOME_DIRto the symlink/Library/Frameworks/R.framework/Resources, which always points to the current active version. Running any version-specific wrapper therefore redirectsR_HOMEto whichever version is set asCurrent. Multi-version integration tests must userig-managed binaries or theexec/Rbinary directly; the standard framework wrappers are unreliable for version isolation. The test suite skips multi-install integration tests automatically when only one distinct library is detected.
For future macOS agent runs
Follow the steps below in order.
Environment setup
# Check what R installations are present
ls /Library/Frameworks/R.framework/Versions/
ls ~/Library/Frameworks/R.framework/Versions/ # user-local installs
ls /opt/homebrew/bin/R* 2>/dev/null # Homebrew
~/.local/share/rig/bin/rig list 2>/dev/null # rig-managed
# Verify at least two R installations exist. If only one is present,
# install a second via rig:
curl -Ls https://rig.r-lib.org/macos.sh | bash
rig install 4.4 # example second versionInstall Chrome if not present (needed for E2E)
Run unit + integration tests
# In the package root
devtools::test()Expected: 0 failures. Tests that require two R installations skip automatically if only one is found.
Run E2E tests
R CMD INSTALL .
export COURIER_E2E=true
# Set to actual paths from `rig list` output
export COURIER_E2E_SRC=/Library/Frameworks/R.framework/Versions/4.4/Resources/bin/Rscript
export COURIER_E2E_TGT=/Library/Frameworks/R.framework/Versions/4.5/Resources/bin/Rscript
export COURIER_E2E_TGT_LIB=~/Library/R/x86_64/4.5/library # adjust arch/version
Rscript -e "testthat::test_file('tests/testthat/test-e2e-ship.R')"Run manual checklist
Work through the manual checklist above. Pay particular attention to
find_routes() detecting Homebrew and framework R separately
— macOS has the most detection sources of any platform.
Report results
Update this table in a PR or open an issue with the
testing label. Include:
- macOS version and chip (Intel / Apple Silicon)
- R version(s) tested
- Which tests passed, skipped, or failed
- Any macOS-specific behaviour differences
Adding tests
- Unit tests go in
tests/testthat/test-<topic>.R - Use
skip_on_cran()for anything that spawns a subprocess or modifies a library - E2E tests go in
test-e2e-ship.R(or a newtest-e2e-<feature>.R) and must checkSys.getenv("COURIER_E2E") == "true"before running -
R CMD check --no-manualmust stay at 0 errors / 0 warnings before merging