Skip to content

test(idempotency): cleaning twice must be a fixed point in every mode - #479

Merged
kevincostner17 merged 1 commit into
mainfrom
test/idempotency-modes
Sep 16, 2026
Merged

kevincostner17 merged 1 commit into
mainfrom
test/idempotency-modes

Conversation

@kevincostner17

Copy link
Copy Markdown
Contributor

Why

Idempotency was asserted for the balanced strategy only. tests/expectations.py drives {"balanced": {"idempotent": true}} for the fixtures and test_properties.py:17 covers defaults. Nothing checked conservative or aggressive, any semantic_mode, a compiled context policy, lossy text options, imputation, outlier clipping, the native engines, or memory replay — even though test_compare_matrix.py exercises all three strategies.

It matters because the second pass sees its own output. A repair that is not a fixed point drifts on every rerun:

  • case folding that re-triggers,
  • a sentinel that re-matches what the first pass wrote,
  • a dominant-variant vote that flips once the variants have changed,
  • outlier fences that keep pulling inward on each clip.

A pipeline that cleans on ingest and again on export would keep moving the data.

Coverage

15 cases: defaults; each of the three strategies; each of the three semantic modes; a context policy; string_case="lower"; impute="mean"; outliers="clip" against a frame carrying a real outlier; each of pandas/polars/duckdb; and memory replay.

One deliberate detail

The engine cases use a uniformly-typed frame. A mixed-type object column makes polars and duckdb disclose a fallback to pandas, so the obvious frame would have quietly tested pandas three times.

The test asserts report.backend == engine and an empty fallback_events, so if that ever changes it fails instead of silently testing the wrong thing.

Verification

  • All 15 already hold on main, so these are regression guards rather than bug reports.
  • Full suite py3.12: 6692 passed, 22 skipped, 0 failed, coverage 93.92%.
  • ruff check . clean repo-wide.
  • No library code changed.

Idempotency was asserted for the balanced strategy only. tests/expectations.py
drives {"balanced": {"idempotent": true}} for the fixtures and
test_properties.py:17 covers defaults; nothing checked conservative or
aggressive, any semantic_mode, a compiled context policy, lossy text options,
imputation, outlier clipping, the native engines, or memory replay -- even
though test_compare_matrix.py exercises all three strategies.

It matters because the second pass sees its own output. A repair that is not a
fixed point drifts on every rerun: case folding that re-triggers, a sentinel
that re-matches what the first pass wrote, a dominant-variant vote that flips
once the variants have changed, fences that keep pulling inward on each clip.
A pipeline that cleans on ingest and again on export would keep moving the data.

Fifteen cases: defaults; each of the three strategies; each of the three
semantic modes; a context policy; string_case="lower"; impute="mean";
outliers="clip" against a frame carrying a real outlier; each of pandas, polars
and duckdb; and memory replay.

The engine cases use a uniformly-typed frame on purpose. A mixed-type object
column makes polars and duckdb disclose a fallback to pandas, so the obvious
frame would have quietly tested pandas three times. The test asserts
report.backend == engine and an empty fallback_events, so if that ever changes
the test fails instead of silently testing the wrong thing.

All fifteen already hold, so these are regression guards. No library code
changed.

Full suite 6692 passed / 0 failed, coverage 93.92%; ruff clean repo-wide.
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 3d8503bd-67ab-49f0-9544-eb7c88c269f0


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.

@kevincostner17
kevincostner17 merged commit 772457b into main Sep 16, 2026
19 checks passed
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