Skip to content

test(validation): one bad cell must trip each rule, and nothing may mutate - #476

Merged
kevincostner17 merged 1 commit into
mainfrom
test/validation-integrity
Sep 16, 2026
Merged

kevincostner17 merged 1 commit into
mainfrom
test/validation-integrity

Conversation

@kevincostner17

Copy link
Copy Markdown
Contributor

Why

Three properties the suite did not assert directly.

1. One-value violations

A rule tested only against a wholly-broken frame can pass while detecting something else entirely; a rule never tested against a clean frame can pass by always failing. Each rule is now asserted both ways.

Rule one bad cell detected clean frame stays silent
unique
allowed_values
min_value/max_value
nullable=False
max_missing_ratio
regex
compound_unique
min_rows / max_rows n/a
missing required column n/a
strict_columns extras n/a

All 16 already behave correctly.

2. Non-mutation, by digest

The existing checks use assert_frame_equal, which compares values and dtypes but ignores .attrs and the index name — an in-place change to either would go unnoticed. These hash content + labels + dtypes + attrs + index name.

run_suite, validate_fields, profile, suggest_plan, infer_roles, explain_clean and clean all leave the input byte-identical.

3. Cross-field, including min <= max

The inventory recorded "no explicit min<=max test". The capability does exist, through caller-supplied cross_rules callables — so this was a coverage gap, not a missing feature.

On a frame with one date inversion and one price inversion on the same row: both rules fire, only that row is reported, the action is manual_review rather than an automatic repair, and a row with a missing half of either pair is correctly not reported — absence is not inversion.

4. Remediation integrity

  • accepted + quarantined + rejected + needs_review == len(df) — no row silently dropped.
  • The original "apple" stays recoverable from the quarantine frame.
  • The audit entry carries original, action, applied, classification and the reason "expected numeric in 'amount' but got text value 'apple'; not silently converted".
  • The report's claim and the frames agree — row 1 absent from accepted, present in quarantined.

Verification

  • 31 tests. Every property already holds on main, so these are regression guards rather than bug reports.
  • Full suite py3.12: 6674 passed, 22 skipped, 0 failed, coverage 93.91%.
  • ruff check . clean repo-wide.
  • No library code changed.

…utate

Three properties the suite did not assert directly.

One-value violations. A rule tested only against a wholly-broken frame can
pass while detecting something else, and a rule never tested against a clean
frame can pass by always failing. Each of unique, allowed_values, range,
nullable, max_missing_ratio, regex, compound_unique and min_rows is now
asserted both ways: exactly one bad cell is detected, and the same rule stays
silent on clean data. max_rows, a missing required column and strict_columns
extras are covered too. All 16 already behave correctly.

Non-mutation by digest. The existing checks use assert_frame_equal, which
compares values and dtypes but ignores .attrs and the index name, so an
in-place change to either would go unnoticed. These hash content, labels,
dtypes, attrs and index name, and all seven of run_suite, validate_fields,
profile, suggest_plan, infer_roles, explain_clean and clean leave the input
byte-identical.

Cross-field. The inventory recorded "no explicit min <= max test"; the
capability exists through caller-supplied cross_rules callables, so this was a
coverage gap rather than a missing feature. On a frame carrying one date
inversion and one price inversion on the same row, both rules fire, only that
row is reported, the action is manual_review rather than an automatic repair,
and a row with a missing half of either pair is correctly not reported --
absence is not inversion.

Remediation integrity. accepted + quarantined + rejected + needs_review equals
the input row count, so no row is silently dropped; the original 'apple' stays
recoverable from the quarantine frame; and the audit entry carries original,
action, applied, classification and the reason "expected numeric in 'amount'
but got text value 'apple'; not silently converted". The report's claim and the
frames agree, which is the property worth guarding: row 1 is absent from
accepted and present in quarantined.

Every property already holds, so these are regression guards rather than bug
reports. No library code changed.

Full suite 6674 passed / 0 failed, coverage 93.91%; 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: db96216d-882e-45e3-9b03-16a1acbeeca7


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 598500a 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