Skip to content

test: enforce pyx12 code prefix matches err_handler tree node type - #181

Merged
azoner merged 1 commit into
masterfrom
feat/error-codes-prefix-invariants
May 6, 2026
Merged

test: enforce pyx12 code prefix matches err_handler tree node type#181
azoner merged 1 commit into
masterfrom
feat/error-codes-prefix-invariants

Conversation

@azoner

@azoner azoner commented May 6, 2026

Copy link
Copy Markdown
Owner

Add unit-test invariants that pyx12 code prefixes match where the error attaches in the err_handler tree:

  • ELE_* and COMP_* codes must land in err_ele.errors (composites surface as element-level errors).
  • SEG_* codes must land in err_seg.errors.

Also fix the one place that violated this invariant: the historical PR #161 hardcode in apply_segment_errors that stored a literal \"8\" in err_seg.errors when collapsing element-level validator errors (too-many-elements, syntax violations, mandatory composite missing) to a spec-correct IK3 code. Replace with new pyx12 code SEG_8_HAS_DATA_ELEMENT_ERRORS (ak/ik=\"8\"); ack output unchanged because the visitor still resolves to \"8\" via the table, and the original element-level pyx12 code is preserved in the err_str.

New tests

pyx12/test/test_error_codes.py (new file):

  • TableConsistency.test_every_code_has_a_known_prefix
  • TableConsistency.test_prefix_matches_spec_level — the main invariant: every code's name prefix matches its declared ErrorCodeSpec.level
  • TableConsistency.test_key_matches_spec_code
  • TableConsistency.test_ak_and_ik_codes_when_set_are_short_strings
  • X12CodeForResolution.test_known_code_resolves_to_ik_code
  • X12CodeForResolution.test_unknown_code_falls_through — envelope-level codes (\"025\") passthrough
  • X12CodeForResolution.test_ak_preferred_when_ik_is_none

pyx12/test/test_x12n_document.py (new ErrorCodePrefixPlacement class):

  • test_walker_seg_errors_have_seg_prefix — uses bad_2010AA_bug
  • test_validator_ele_errors_have_ele_or_comp_prefix — uses 834_lui_id_5010_non_ascii
  • test_no_raw_x12_code_leaks_into_seg_or_ele_errors — parameterized across 7 fixtures

Updates

  • pyx12/error_codes.py — new SEG_8_HAS_DATA_ELEMENT_ERRORS constant + ERROR_CODES entry
  • pyx12/map_if/_segment.py apply_segment_errors — emit SEG_8_HAS_DATA_ELEMENT_ERRORS instead of literal \"8\"
  • pyx12/test/test_map_if.pyApplySegmentErrorsRouting test updated to expect the new code

Test plan

  • pytest pyx12/test/: 597 passed + 7 subtests (581 + 6 from PR feat: add --suppress CLI flag + suppress_error_codes filter (PR 6 of 6) #180 + 10 new from this PR)
  • mypy --strict pyx12: clean (89 source files; new test_error_codes.py)
  • ruff check + format --check: clean
  • res997 / resAck / resJson fixtures unchanged — the apply_segment_errors collapse path is not exercised by any existing fixture (regenerator helper run, no diffs)

🤖 Generated with Claude Code

Add unit-test invariants that pyx12 code prefixes match where the
error attaches in the err_handler tree:

- ELE_* and COMP_* codes must land in err_ele.errors (composites
  surface as element-level errors).
- SEG_* codes must land in err_seg.errors.

Also fix the one place that violated this invariant: the historical
PR #161 hardcode in apply_segment_errors that stored a literal "8"
in err_seg.errors when collapsing element-level validator errors
(too-many-elements, syntax violations, mandatory composite missing,
etc.) to a spec-correct IK3 code. Replace with new pyx12 code
SEG_8_HAS_DATA_ELEMENT_ERRORS (ak/ik="8"); ack output unchanged
because the visitor still resolves to "8" via the table, and the
original element-level pyx12 code is preserved in the err_str.

New tests:

pyx12/test/test_error_codes.py (new file):
- TableConsistency.test_every_code_has_a_known_prefix
- TableConsistency.test_prefix_matches_spec_level (the main invariant
  the user asked for: every code's name prefix matches its declared
  ErrorCodeSpec.level)
- TableConsistency.test_key_matches_spec_code
- TableConsistency.test_ak_and_ik_codes_when_set_are_short_strings
- X12CodeForResolution.test_known_code_resolves_to_ik_code
- X12CodeForResolution.test_unknown_code_falls_through (envelope-level
  codes like "025" passthrough)
- X12CodeForResolution.test_ak_preferred_when_ik_is_none

pyx12/test/test_x12n_document.py (new ErrorCodePrefixPlacement class):
- test_walker_seg_errors_have_seg_prefix (uses bad_2010AA_bug)
- test_validator_ele_errors_have_ele_or_comp_prefix (uses
  834_lui_id_5010_non_ascii)
- test_no_raw_x12_code_leaks_into_seg_or_ele_errors (parameterized
  across 7 fixtures)

Updates:
- pyx12/error_codes.py: add SEG_8_HAS_DATA_ELEMENT_ERRORS module
  constant and ERROR_CODES entry.
- pyx12/map_if/_segment.py apply_segment_errors: emit
  SEG_8_HAS_DATA_ELEMENT_ERRORS instead of literal "8". The original
  element-level pyx12 code (e.g. SEG_3_TOO_MANY_ELEMENTS,
  COMP_1_MANDATORY_MISSING) is dropped at this collapse point — by
  design, per PR #161's spec-correctness routing.
- pyx12/test/test_map_if.py: ApplySegmentErrorsRouting test updated
  to expect SEG_8_HAS_DATA_ELEMENT_ERRORS instead of "8".

Verification:
- pytest pyx12/test/: 597 passed + 7 subtests (581 + 6 from PR 6 +
  10 new from this PR)
- mypy --strict pyx12: clean (89 source files; new test_error_codes.py)
- ruff check + format --check: clean
- res997 / resAck / resJson fixtures unchanged: the apply_segment_errors
  collapse path is not exercised by any existing fixture (regenerator
  helper run, no diffs).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@azoner
azoner merged commit 3358257 into master May 6, 2026
16 checks passed
@azoner
azoner deleted the feat/error-codes-prefix-invariants branch May 6, 2026 19:36
azoner added a commit that referenced this pull request May 6, 2026
Add a preference: when given a non-trivial task, do not start making
changes until you have ~95% confidence in what to build. Ask follow-up
questions until that bar is met. Catches scope creep and misalignment
early — see PR #181 where I added an apply_segment_errors cleanup the
user hadn't asked for, framed as "the only invariant violator", but
which was a separate behavior change deserving its own decision.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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