Skip to content

test: gate the canonical/legacy test split - #239

Merged
pftg merged 1 commit into
masterfrom
test/gate-canonical-legacy-split
Aug 23, 2026
Merged

test: gate the canonical/legacy test split#239
pftg merged 1 commit into
masterfrom
test/gate-canonical-legacy-split

Conversation

@pftg

@pftg pftg commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

rake test:canonical is defined as "exactly what must still pass once
test/legacy/ and the v1 trees are gone". Three times in one day a test
asserting legacy behaviour was written into test/unit/, i.e. into that
suite:

Each was green on the day it was written and red the day the deletion lands,
long after its author moved on. Reviews caught all three. The fourth ships.

The gate

test/unit/canonical_suite_has_no_legacy_refs_test.rb — the test-tree twin of
test/unit/core_tree_has_no_legacy_deps_test.rb, which guards the same edge
for lib/. No file under test/unit/ or test/integration/ may:

pattern catches
LEGACY_REQUIRE require/require_relative of capybara/screenshot…, capybara_screenshot_diff…, the capybara-screenshot-diff gem-name entry, or snap_diff/{legacy_shims,deprecation}. Plain require "capybara" must not match. Unanchored, unlike the lib-side twin: tests drive subprocesses, so a legacy require is as likely to sit inside a heredoc or a -e string, and both really load it.
LEGACY_CONSTANT a read or write of Capybara::Screenshot / CapybaraScreenshotDiff.
LEGACY_SHIM_SURFACE names that look canonical but are defined in the doomed files: SnapDiff.start, SnapDiff.silence_deprecations, SnapDiff::Deprecation, suppress_migration_notice!. This is incident (a)'s shape.

test/legacy/ is deliberately not policed — exercising the legacy surface
is its whole job, and it is deleted with what it tests.

Conventions match the twin: reports file:line: reason -- \code``, ignores
whole-line comments (a comment about where a forwarder used to live is history,
not a dependency), carries a vacuity guard, and has a sub-test that fails on
stale allowlist entries.

The allowlist

Two entries, and neither is a test of legacy behaviour:

  • unit/deletion_3_0_test.rb (5 lines) — it simulates the deletion for real,
    so it names the deletion set, the edits, and its own gate line by
    construction. It cannot assert that its gate rejects an intact tree without
    spelling the doomed names.
  • unit/core_tree_has_no_legacy_deps_test.rb (1 line) — the twin gate's
    LEGACY_CONSTANT literal. A detector has to spell what it detects.

A third entry means canonical tests are still entangled with the legacy
surface: that needs a decision, not a green build.

Self-exclusion. The gate does not scan its own file, and says why in a
comment: a line-level allowlist has to quote the exact lines it blesses, every
such quote is itself a legacy reference, and blessing them would need an
allowlist entry whose text is again an offence. No fixed point exists.

Mutation evidence

mutation result
three legacy lines added to test/unit/vcs_test.rb (a require, a constant, SnapDiff.start) red, one line each, named: unit/vcs_test.rb:4: requires a doomed path, :5: references a v1 namespace constant, :6: uses a shim-only name that the deletion removes
MUTATION_LEGACY_DIR = CapybaraScreenshotDiff added to test/legacy/errors_alias_test.rb green — same run, not reported; the gate does not police that directory
bogus line added to the deletion_3_0_test.rb allowlist red in the second sub-test: allowlisted line no longer present

All probes reverted; git diff against the probe baseline is empty.

Suites

  • rake test:unit — 572 runs, 0 failures (baseline 570; +2 is this gate)
  • rake test:canonical — 469 runs, 0 failures, 1 skip (baseline 467/0/1)
  • standardrb clean

Known gap, stated plainly

Incident (a) is caught only when the shim-only name is written as
SnapDiff.start. In #236 it was a bare start inside a %w[] surface table —
textually indistinguishable from any other word, so no scan can catch that
without unbearable false positives. The other two incident shapes are caught
outright.

Out of scope by design: test/test_helper.rb and test/support/, which are
shared with test/legacy/. test_helper.rb still calls
SnapDiff::Deprecation.suppress_migration_notice! — that is deletion fallout,
handled where the deletion happens, not by this gate.

Summary by Sourcery

Prevent canonical tests from becoming coupled to the legacy surface ahead of its removal.

New Features:

  • Add a canonical test-suite guard that rejects references to legacy requires, namespaces, and shim-only APIs in unit and integration tests.

Enhancements:

  • Add scoped allowlisting for intentional legacy references and validate that allowlist entries remain present.
  • Add diagnostics identifying offending files, lines, and legacy-reference categories while excluding legacy tests and the guard itself.

Tests:

  • Add mutation coverage demonstrating detection of legacy references, exemption of test/legacy, and stale-allowlist failures.

`rake test:canonical` is defined as "exactly what must still pass once
test/legacy/ and the v1 trees are gone". Three times in one day a test
asserting LEGACY behaviour was written into test/unit/, i.e. into that
suite: a canonical surface table demanding the shim-only SnapDiff.start
(#236), three legacy-constant probes in a canonical file (#237), and a
pre-existing umbrella guard #236 had to relocate. Each would have failed
the day the deletion landed, long after its author moved on. Reviews
caught all three; the fourth would ship.

The test-tree twin of core_tree_has_no_legacy_deps_test.rb: no file under
test/unit/ or test/integration/ may require a doomed path, name a v1
namespace constant, or use a shim-only name (SnapDiff.start,
.silence_deprecations, SnapDiff::Deprecation, suppress_migration_notice!).
test/legacy/ is deliberately not policed -- exercising the legacy surface
is its job.

Same conventions as the twin: file:line: reason -- `code`, whole-line
comments ignored, a vacuity guard, and a sub-test that fails on stale
allowlist entries. The allowlist holds two entries, both gates rather
than tests of behaviour (deletion_3_0_test.rb, which names the deletion
set by construction, and the twin gate's own pattern literal). A third
entry means canonical tests are still entangled and needs a decision, not
a green build.

This file cannot scan itself: a line-level allowlist has to quote the
lines it blesses, and every quote is itself an offence -- no fixed point
exists.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @pftg, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@pftg, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ed7e5332-3356-40c0-bc19-e3beaf19245b

📥 Commits

Reviewing files that changed from the base of the PR and between c3ad16e and 3d22034.

📒 Files selected for processing (1)
  • test/unit/canonical_suite_has_no_legacy_refs_test.rb

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds a test-based gate that scans canonical test suites to ensure they do not reference legacy namespaces, shim-only APIs, or doomed require paths, with a precise allowlist and self-consistency checks to prevent stale entries and self-scanning issues.

File-Level Changes

Change Details Files
Introduce a canonical test gate that scans unit and integration test files for legacy references and fails the build if any are found.
  • Define globbing over test/unit and test/integration trees to build the file set under enforcement, excluding the gate file itself.
  • Implement regex detectors for legacy requires, legacy constants, and shim-only SnapDiff APIs intended for deletion.
  • Add a test that aggregates offences across all canonical test files and reports detailed file:line:reason messages to guide relocating or rewriting tests.
test/unit/canonical_suite_has_no_legacy_refs_test.rb
Add a line-level allowlist with integrity checks to permit only specific legacy references in gate-related tests while preventing stale entries.
  • Create an ALLOWED hash keyed by path relative to test/, listing exact offending lines tolerated and documenting why each is allowed.
  • Implement a sub-test that verifies all allowlisted files still exist and that each allowlisted line is still present, failing with guidance if any become stale.
  • Explain and enforce that the gate file cannot scan itself because its own allowlist entries would be self-offending, avoiding an impossible fixed point.
test/unit/canonical_suite_has_no_legacy_refs_test.rb

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

Copy link
Copy Markdown

Screenshot diffs detected

Artifact Link
HTML report (inline) N/A
Full report with images N/A
All artifacts Browse all

@pftg
pftg merged commit 785f413 into master Aug 23, 2026
6 of 8 checks passed
@pftg
pftg deleted the test/gate-canonical-legacy-split branch August 23, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant