"""Corpus golden: para cada `caso_*.input.json` em `sowai_fiscal.goldens`, carrega o `DadosEmissao`, monta+serializa o XML pré-assinatura e compara BYTE A BYTE com o `caso_*.expected.xml` irmão. Estes dados são PACOTE (`importlib.resources`), não fixtures de `tests/` -- o produto consumidor (auto) e o futuro serviço leem os MESMOS arquivos da lib instalada. Regenerar os `.expected.xml` (nunca à mão) com `scripts/gen_goldens.py` -- só quando uma NT mudar o leiaute DE PROPÓSITO.""" import importlib.resources import pytest from sowai_fiscal.golden_helpers import dados_from_json, serialize_infnfe _GOLDENS = importlib.resources.files("sowai_fiscal") / "goldens" def _casos() -> list[str]: with importlib.resources.as_file(_GOLDENS) as goldens_dir: return sorted( p.name.removesuffix(".input.json") for p in goldens_dir.glob("caso_*.input.json") ) _CASOS = _casos() def test_at_least_six_golden_cases_exist(): assert len(_CASOS) >= 6, f"esperado >=6 casos golden, achei {len(_CASOS)}: {_CASOS}" @pytest.mark.parametrize("caso", _CASOS) def test_golden_case_matches_expected_xml_byte_a_byte(caso): with importlib.resources.as_file(_GOLDENS) as goldens_dir: input_path = goldens_dir / f"{caso}.input.json" expected_path = goldens_dir / f"{caso}.expected.xml" dados = dados_from_json(input_path) actual = serialize_infnfe(dados) expected = expected_path.read_bytes() if actual != expected: # Diff legível: aponta o primeiro byte divergente em vez de despejar # os dois XMLs inteiros no assert. first_diff = next( (i for i, (a, e) in enumerate(zip(actual, expected)) if a != e), min(len(actual), len(expected)), ) window = 60 start = max(0, first_diff - window) assert actual == expected, ( f"caso {caso!r} diverge no byte {first_diff}:\n" f" actual: ...{actual[start:first_diff + window]!r}...\n" f" expected: ...{expected[start:first_diff + window]!r}..." )