Skip to content

test(mutation): mutate masking.py live via a duckdb-free fixtureless test#111

Merged
brownjuly2003-code merged 1 commit into
mainfrom
test/mutation-gate-masking
Jun 29, 2026
Merged

test(mutation): mutate masking.py live via a duckdb-free fixtureless test#111
brownjuly2003-code merged 1 commit into
mainfrom
test/mutation-gate-masking

Conversation

@brownjuly2003-code

Copy link
Copy Markdown
Owner

What

Bring src/serving/masking.py (the PII masker) under the live mutation gate.
Until now it was only declared in pyproject [tool.mutmut].paths_to_mutate; the
gate that actually runs (scripts/mutation_report.py MODULE_TARGETS) mutated
only retry.py and sql_guard.py, so a weakened masking rule could pass CI.

Why this needed a new test

  • The ordinary tests/unit/test_masking.py imports the API router → DataCatalog
    → the duckdb engine chain, which drags duckdb's compiled subpackage into
    mutmut's mutants/ workspace and crashes the run.
  • A prior attempt mutated masking through a fixture-built masker. Under
    mutate_only_covered_lines = true that left every method line uncovered, so
    only __init__ was mutated (score 0%).

What this adds

  • tests/unit/test_masking_mutation.py — a narrow, duckdb-free, fixtureless
    test that builds the masker inline and calls each method directly (the shape
    that made test_sql_guard_mutation.py work), so coverage attributes every
    method line. Dual-context import (serving.* under the harness, src.serving.*
    under ordinary pytest). It also runs in the normal unit suite.
  • serving/masking.py added to MODULE_TARGETS at threshold 0.90 (same bar
    as sql_guard).
  • Comments in pyproject [tool.mutmut] and test_mutmut_policy.py updated so the
    declared-vs-live note stays honest (masking is now live, not declared-only).

Verification

Replayed the runner's own workspace layout locally with mutmut 3.6:
184 mutants across all methods, 176 killed = 95.7% (≥ 0.90). The 8 survivors
are equivalent/unreachable mutants: the yaml is None guard under
# pragma: no cover, encoding="utf-8" vs the platform default on an ASCII
config, and dialect-equivalent sqlglot.parse_one calls.

The mutation.yml workflow has been dispatched on this branch to confirm the
score through the real runner on Python 3.11. Local gates: ruff check + format
clean, test_mutmut_policy.py + test_mutation_report.py + test_masking*.py
all green.

🤖 Generated with Claude Code

…test

The PII masker redacts cleartext PII, but the mutation gate only declared it
(pyproject paths_to_mutate) without mutating it -- the live runner
(scripts/mutation_report.py MODULE_TARGETS) ran only retry.py and sql_guard.py.
A prior attempt mutated masking.py through a fixture-built masker, which under
`mutate_only_covered_lines` left every method line uncovered, so only __init__
got mutated (score 0%).

Add tests/unit/test_masking_mutation.py: a narrow, duckdb-free test (the ordinary
test_masking.py pulls the API router -> DataCatalog -> duckdb chain, which crashes
mutmut's workspace) that builds the masker inline and calls each method directly
-- the shape that made test_sql_guard_mutation.py work -- so coverage attributes
every method line and the whole module is mutated. Wire serving/masking.py into
MODULE_TARGETS at threshold 0.90, matching sql_guard.

Verified end-to-end with the runner's own workspace layout (mutmut 3.6): 184
mutants across all methods, 176 killed = 95.7%. The 8 survivors are equivalent or
unreachable mutants (the yaml-None guard under `# pragma: no cover`,
encoding="utf-8" vs the platform default on an ASCII config, and dialect-equivalent
sqlglot.parse_one calls).

Comments in pyproject [tool.mutmut] and test_mutmut_policy.py updated so the
declared-vs-live note stays honest: masking is now live, not declared-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

DORA Metrics

  • Window: last 30 days
  • Branch: main
  • Deployment frequency: 152 total / 35.47 per week
  • Lead time for changes: avg 0.29h / median 0.0h
  • Change failure rate: 61.18% (93/152)
  • MTTR: 0.25h across 3 incident(s)

@brownjuly2003-code brownjuly2003-code merged commit 245f8dd into main Jun 29, 2026
21 checks passed
@brownjuly2003-code brownjuly2003-code deleted the test/mutation-gate-masking branch June 29, 2026 18:59
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.

2 participants