Skip to content

Add pytest coverage for the barcode registry, EAN/UPC/ITF/Codabar encoders, ISXN validation and charset tables (239 tests) - #269

Closed
wxs-lang wants to merge 1 commit into
WhyNotHugo:mainfrom
wxs-lang:main
Closed

wxs-lang wants to merge 1 commit into
WhyNotHugo:mainfrom
wxs-lang:main

Conversation

@wxs-lang

Copy link
Copy Markdown

The existing suite (55 tests) covers one checksum example per barcode type, EAN-13's checksum/no-checksum interplay, GS1-128 symbol sequences, Code 128 build stability, and the writers. Several encoders and the lookup layer had no dedicated tests at all (UPC-A, ITF and Codabar only appeared in the visual test_manually.py). This PR adds 239 tests covering that missing pure-encoding logic; no production code is changed and no image rendering is asserted (only build() patterns and value-level behaviour).

  • barcode/__init__.py registry (test_registry.py) — PROVIDED_BARCODES is exactly the 22 sorted names; every name resolves via get_barcode_class to its class; aliases (ean→ean13, gtin→ean14, isbn/gs1→isbn13, nw-7→codabar, upc→upca) resolve to the identical class object; lookup is case-insensitive; unknown names (including "" and names with stray whitespace) raise BarcodeNotFoundError with the message The barcode '<name>' is not known., with or without a code; get with a code returns an instance, without one the class, and options are passed through to the constructor
  • EAN family (test_ean_family.py) — EAN-13: overlong input is trimmed to 12 digits and the checksum recomputed, too-short input raises NumberOfDigitsError, non-digits and empty input raise IllegalCharacterError, calculate_checksum(value) for explicit values, the exact 95-module build() pattern, guard-bar fullcode format, to_ascii() output; EAN-8 and EAN-14: checksums for a range of values (including all-zero and all-nine inputs), trimming, length/character errors, build lengths (67 / 102 modules), EAN-8 guard fullcode; JAN: country codes at the 450/459/490/499 boundaries accepted, 460/489/500 rejected with WrongCountryCodeError, and the country check running before the length check
  • UPC-A (test_upc.py) — checksums for five values, 12-digit input being trimmed with the checksum recomputed (a wrong 12th digit is silently ignored), length/character errors, make_ean=True prefixing a 0 in str()/get_fullcode() while the stored code keeps 12 digits, the exact 95-module build() pattern, and to_ascii() using _ for spaces
  • ITF (test_itf.py) — odd-length input padded with a leading zero, exact interleaved build() patterns for digit pairs, pattern length scaling with pair count, narrow/wide width scaling, and IllegalCharacterError for non-digit input (including empty and separator-containing strings)
  • ISXN validation (test_isxn_validation.py) — ISBN-13: hyphen stripping, rejection of non-978/979 prefixes, the 979 fourth-digit rule raising the plain BarcodeError, accepted 979-1 and 979-8 prefixes; ISBN-10: the documented example, the supplied check digit being ignored and always recomputed, hyphen stripping, and X check digits for four values; ISSN: X and numeric check digits, conversion to EAN-13, hyphen handling, and make_ean() output
  • Code 39 and PZN (test_code39_pzn.py) — appended checksum characters for a range of inputs, upper-casing of lowercase input, add_checksum=False, building every one of the 43 legal characters framed by the start/stop pattern, illegal-character error paths, and PZN length validation, non-digit rejection, trimming, the checksum-10 rejection, and PZN8's seven-digit form
  • Codabar (test_codabar.py) — exact build() patterns at default and custom narrow/wide widths, all six special characters ($:/.+-) building, and validation being deferred to build(): bad start/end characters raise BarcodeError, illegal body characters raise IllegalCharacterError, while the constructor accepts anything
  • Code 128 charsets (test_code128_charsets.py) — charset A/B dictionary values and sizes, the charset C switch table (TO_B 100, TO_A 101, FNC1 102), start/switch tables, and encoded symbol sequences for digit pairs, start-code folding to START_B, a trailing odd digit switching to charset B, and control characters switching to charset A; plus the illegal-character error
  • Charset table invariants (test_charset_tables.py) — EAN LEFT_PATTERN shape, C patterns being the bitwise complement of A and B the reverse of C, UPC tables being identical to the EAN A/C tables, ITF's two-of-five property (exactly two wide elements per digit), Code 39 table/map shape and sequential values, Code 128's 106 unique 11-module patterns, and the Codabar table shape
  • Errors and base class (test_errors.py) — BarcodeError message storage/rendering, the four specific errors subclassing BarcodeError, the base Barcode raising NotImplementedError on instantiation, and the default writer being SVGWriter

Behaviour pinned as-is (possible upstream quirks, documented in the tests rather than "fixed"):

  • Code39 with an illegal character raises KeyError (not IllegalCharacterError) under the default add_checksum=True, because the checksum is computed before character validation; with add_checksum=False the proper IllegalCharacterError is raised
  • Code39.calculate_checksum() sums self.code including the already-appended checksum character, so calling it after construction returns a different character than the one in the code
  • Code39("") silently produces the code "0"
  • JAN with a non-numeric prefix raises a plain ValueError from int(), not a BarcodeError
  • ISSN performs no length validation: ISSN("12345") silently produces issn == "123455" and a meaningless EAN-13 (9771234550029)
  • ISSN.make_ean() returns the check digit verbatim, so it can contain X (e.g. 977114487500X); the numeric EAN checksum is only applied by the EAN-13 layer
  • The ISBN-13 979 check accepts a fourth digit of 1 or 8, although the error message only mentions 97910 and 97911
  • Code128("") raises IndexError (in _try_to_optimize), and CODABAR("") raises IndexError on build()

Verification (Python 3.12, package installed with pip install -e ".[images]", plus pytest and pytest-cov; no new conftest is needed — the tests live in the existing tests/ package and run from the repository root):

$ python -m pytest tests/test_registry.py tests/test_ean_family.py tests/test_upc.py tests/test_itf.py tests/test_isxn_validation.py tests/test_code39_pzn.py tests/test_codabar.py tests/test_code128_charsets.py tests/test_charset_tables.py tests/test_errors.py -q
239 passed
$ python -m pytest tests/ -q   # full suite, repository's own addopts (with coverage)
294 passed   # 55 pre-existing + 239 new

…XN validation, Code39/PZN and Code128 charsets
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