Release Prep Tasks
This package requires release prep steps before merging to main:
- All tests pass (devtools::test())
- Build/Check without notes, warnings, errors (devtools::check())
- Coverage >80% (covr::package_coverage())
httptest2 Fixture Stability (Mocking Exception)
The Problem
Tests in test-artwork-ai.R and test-artwork-plus-ai.R use httptest2 to record/replay API responses. httptest2 derives fixture filenames from a hash of the request body, which includes base64-encoded images.
The b64EncodeImage() function uses magick to resize and encode images. However, magick produces non-deterministic output across R sessions due to:
- Internal state that varies based on prior magick operations in the session
- Subtle differences in PNG compression/metadata
-
magick_set_seed()does not fully solve the issue (first call after session start still varies)
This causes httptest2 request hashes to differ between recording and replay, resulting in “unexpected request” errors when fixtures exist but hashes don’t match.
The Solution
We mock b64EncodeImage() within these specific tests using testthat::local_mocked_bindings() to bypass magick and use raw file encoding:
local_mocked_bindings(
b64EncodeImage = function(img_path) {
raw <- readBin(img_path, "raw", n = file.info(img_path)$size)
base64enc::base64encode(raw)
}
)Why This Exception is Correct
- Scope: The mock is local to each test, not global
- Purpose: We’re not testing magick’s image processing - we’re testing API integration. The mock isolates the test from an external dependency’s non-determinism
-
Production unchanged: The real
b64EncodeImage()(with magick resizing) is used in production -
Alternative considered: A global
getOption()bypass was rejected as it obscured the issue and spread test-specific logic into production code
