test: close measured coverage gaps + actually run the 3.0 deletion - #238
Conversation
Six gaps a coverage+mutation audit measured, each closed with a test that was proven to go red against the mutation it is meant to catch. The headline is test/unit/deletion_3_0_test.rb: the alias-only gate and the reverse gate are static PROXIES for "git rm the v1 surface and the gem still loads". This runs it -- copies lib/ to a tmpdir, applies the deletion set and the two edits it needs, and requires every canonical entry point in a fresh subprocess. Every probe hard-asserts the deletion is in effect BEFORE it asserts anything about the surface, because a run that cannot tell the deleted tree from the intact one is not evidence. Also: the vips tolerance floor, SnapDiff.compare's default_options merge, Reporters::Default#generate's equal-path cleanup, Viewport.prepare!'s selenium arm, and all four screenshot_area path-segment combinations. No lib/ changes.
Reviewer's GuideAdds targeted tests to close coverage and mutation gaps around 3.0 legacy deletion, configuration defaults, reporters, viewport sizing, and screenshot path composition, without modifying lib/; also introduces a subprocess-based gate to ensure the 3.0 deletion is actually exercised. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThe pull request adds regression tests for viewport mismatch messages, comparison configuration, equal-image artifact cleanup, and removal of the declared 3.0 legacy surface. ChangesComparison and reporting regressions
Viewport mismatch diagnostics
3.0 deletion compatibility
Estimated code review effort: 4 (Complex) | ~45 minutes ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Screenshot diffs detected
|
Closes the gaps a measured coverage+mutation audit found. The audit ran on 9822cc6, before #236; every item was re-verified against current master first, and two of the three "blockers" turned out to be already closed by #236 — reported below as negative results.
No
lib/changes, no version/CHANGELOG changes. Test-only.Already closed by #236 (negative results)
Blocker A —
lib/snap_diff-capybara.rbhas zero coverage. No longer true. #236 added"snap_diff-capybara"toSupportLoadProbeTest::CANONICAL_ENTRY_POINTS,CANONICAL_ADVERTISED_CONSTANTSand the dual-install-guard probe, so the full canonicalSnapDiffsurface is asserted for it today. What was still missing is its post-3.0 shape — covered here by the deletion test (see below), which requires it from the deleted tree with the repointing edit applied.Blocker C — config default values and require-time freezing pinned only through legacy holders. No longer true.
ConfigDefaultTimingTestis already canonical: it lives intest/unit/, reads throughSnapDiff.configonly, and pins the 27-setting default table plus both freezings. TheCapybara::Screenshot.*half was split out totest/legacy/legacy_config_default_timing_test.rb.Verified by mutation rather than by reading it — both freezings really are load-bearing:
lib/snap_diff/config.rbfail_if_newmade a lazy memoized readerfail_if_new: expected true, got false(probe B) andexpected false, got true(probe A)rootmade a lazy memoized readerroot: expected /fake-rails-root-at-require, got /fake-rails-root-after-require(probe C) andexpected <launch pwd>, got <tmpdir>(probe A)Blocker B — nothing actually RAN the deletion
test/unit/deletion_3_0_test.rb. Copieslib/to a tmpdir, deletes the 3.0 set (lib/capybara*,lib/capybara-screenshot-diff.rb,lib/capybara_screenshot_diff.rb,lib/snap_diff/legacy_shims.rb,lib/snap_diff/deprecation.rb), applies the two known edits, and requires every canonical entry point in a fresh subprocess — surface methods and advertised constants both.The deletion set and the edits are exact-matched against the real files, so a reworded require line goes red here rather than silently not applying.
Gate-line design
An earlier lane's "green" run was later shown to have measured the intact tree, because
BUNDLE_GEMFILEpointed at a gemspec that unshifts its ownlibahead of-Ilib. So before a single surface assertion, every probe hard-asserts that the deletion is in effect:SnapDiff.respond_to?(:start)isfalse(it is defined inlegacy_shims.rb)defined?(CapybaraScreenshotDiff)is nillegacy_shims/deprecationin$LOADED_FEATURESlib/capybara*path in$LOADED_FEATURES— this is also Blocker A's post-3.0 assertionsnap_difffile starts with the tmpdir path — theBUNDLE_GEMFILEtrap itselfIt is an
abort, not a comment. And it is tested:"the gate line rejects an intact tree"runs the same probe against an untouched copy oflib/, where every surface assertion would pass, and asserts the gate rejects it (SnapDiff.start is still defined).The isolation is real, and measured
While building this I confirmed the trap is not hypothetical, and that the obvious defense is not sufficient. Scrubbing
RUBYOPT/BUNDLE_GEMFILEalone does not work if the cwd is still inside the project: RubyGems auto-discoversgems.rb, puts-rbundler/setupback intoRUBYOPT, and the gemspec unshifts the reallib/ahead of the-Idir.So the probe does both — scrubs the env and
chdirs to the tmpdir — and the comment on#probesays which half is load-bearing. The gate line is what notices if either stops working.Red→green evidence
Reintroducing one core→legacy edge (
require "capybara/screenshot/diff/os"inlib/snap_diff/region.rb, a leaf the whole core loads):Both deletion tests red. The
snap_diff-capybaratrace also showssnap_diff-capybara.rb:8loadingsnap_diff/integrations/minitestfrom the deleted tree — i.e. the repointing edit applied and that entry point is genuinely exercised post-deletion. Reverted; green.Gate globs — checked, deliberately not widened
lib/snap_diff-capybara.rbdoes fall outside both gates' globs, as the audit says. I did not widen either, and this is a call rather than an omission:snap_diff/**/*.rb, survives 3.0): widening it goes red today — the file legitimately requirescapybara_screenshot_diff/minitestfor the whole 2.x line — so it would need anALLOWEDentry. That allowlist is deliberately empty and its own comment says an entry needs an ADR update, never a red build turned green. Not worth spending for a claim the deletion test now makes executably.test/legacy/, deleted in 3.0): its subject is the v1 compatibility surface.snap_diff-capybara.rbis the canonical gem's Bundler entry, and the guard would disappear in 3.0 anyway.Happy to reverse either if a reviewer disagrees.
Three mutations that survived the full suite
Each was applied, the new test observed red, then reverted and observed green.
git diff --stat lib/is empty on this branch.1. Vips tolerance floor (
config.rb:155then-arm, hit count 0) —tolerance: tolerance || ((driver == :vips) ? 0.001 : nil)→tolerance: tolerance2.
SnapDiff.comparedrops the defaults merge —config.default_options.merge(options)→optionsThe existing test only pinned that an explicit option round-trips, so callers who configure once and then call
.comparewith no options were silently losing every configured default.3.
Reporters::Default#generateskipsclean_tmp_fileson the equal pathThe existing test called
clean_tmp_filesdirectly, so#generate's own call had no coverage. The equal comparison is built with the same artifact paths as the differing one, so what gets cleaned is exactly what got written.Two thin branches
Viewport.prepare!'s selenium arm — never taken (viewport_teststubbedselenium? => falseonly), so the wholesession.driver.browser.manage.window.sizechain, the only reason the message is ever useful, was unexecuted. Mutation — collapse the ternary tocurrent_size = "unknown":screenshot_area's two path-segment flags — only ever exercised together (both true insystem_test_case.rband the rspec fixtures, both nil everywhere else), so eitherifcould be swapped for the other flag unnoticed. All four combinations, withOs.name/Capybara.current_driverstubbed so the assertion names the expected path literally. Mutation —parts << Os.name if add_os_path→if add_driver_path:Numbers
rake test:unitrake testrake test:canonicalstandardrb: 157 files, no offenses. Reverse gate and alias-only gate both green (they run inside the above).🤖 Generated with Claude Code
Summary by Sourcery
Close measured coverage and mutation gaps while making the 3.0 legacy-surface deletion an executable compatibility test.
Bug Fixes:
Enhancements:
Tests:
Summary by CodeRabbit