262 lines
7.6 KiB
Python
262 lines
7.6 KiB
Python
"""Testes do parser bíblico.
|
|
|
|
O parser reconstrói livro, capítulo e versículo a partir do texto extraído do PDF.
|
|
O caso de referência é o PDF do projeto (Almeida Revista e Corrigida), em que o
|
|
capítulo aparece como `[N]` e os versículos são numerados no início da linha.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
from app.bible_parser import ( # noqa: E402
|
|
BOOKS,
|
|
BibleParser,
|
|
parse_book_index,
|
|
)
|
|
from app.extraction import PageText # noqa: E402
|
|
|
|
|
|
def make_page(number: int, text: str) -> PageText:
|
|
return PageText(page=number, text=text)
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# Índice de livros
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
def test_parse_book_index_reads_book_and_start_page():
|
|
text = """
|
|
INDICE
|
|
ANTIGO TESTAMENTO: 5
|
|
Gênesis: 6
|
|
Êxodo: 168
|
|
Levítico: 303
|
|
|
|
NOVO TESTAMENTO: 2542
|
|
Mateus: 2543
|
|
Apocalipse: 3314
|
|
"""
|
|
starts = parse_book_index(text)
|
|
|
|
assert starts["Gênesis"] == 6
|
|
assert starts["Êxodo"] == 168
|
|
assert starts["Apocalipse"] == 3314
|
|
assert "ANTIGO TESTAMENTO" not in starts
|
|
assert "NOVO TESTAMENTO" not in starts
|
|
|
|
|
|
def test_parse_book_index_ignores_unknown_entries():
|
|
starts = parse_book_index("Gênesis: 6\nPagina solta: 12\n")
|
|
assert starts == {"Gênesis": 6}
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# Atribuição de livro
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
def test_book_is_assigned_by_page_range():
|
|
parser = BibleParser()
|
|
starts = {"Gênesis": 6, "Êxodo": 168}
|
|
|
|
assert parser.book_for_page(6, starts) == "Gênesis"
|
|
assert parser.book_for_page(167, starts) == "Gênesis"
|
|
assert parser.book_for_page(168, starts) == "Êxodo"
|
|
assert parser.book_for_page(300, starts) == "Êxodo"
|
|
|
|
|
|
def test_page_before_first_book_has_no_book():
|
|
parser = BibleParser()
|
|
assert parser.book_for_page(3, {"Gênesis": 6}) is None
|
|
|
|
|
|
def test_page_after_last_book_keeps_last_book():
|
|
parser = BibleParser()
|
|
assert parser.book_for_page(3363, {"Gênesis": 6, "Êxodo": 168}) == "Êxodo"
|
|
|
|
|
|
def test_book_falls_back_to_page_header_when_index_is_missing():
|
|
parser = BibleParser()
|
|
text = "GÊNESIS\n\n[1]\n1 No princípio criou Deus os céus e a terra."
|
|
|
|
chunks = parser.parse([make_page(6, text)], "biblia.pdf", {})
|
|
|
|
assert chunks, "o fallback por cabeçalho deveria produzir chunks"
|
|
assert chunks[0].book == "Gênesis"
|
|
assert chunks[0].chapter == 1
|
|
assert chunks[0].verse == 1
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# Capítulos e versículos
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
def test_parses_genesis_1_1():
|
|
parser = BibleParser()
|
|
text = (
|
|
"GÊNESIS\n"
|
|
"\n"
|
|
"[1]\n"
|
|
"1 No princípio criou Deus os céus e a terra.\n"
|
|
"2 A terra era sem forma e vazia; e havia trevas\n"
|
|
"sobre a face do abismo, mas o Espírito de Deus\n"
|
|
"pairava sobre a face das águas.\n"
|
|
)
|
|
|
|
chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6})
|
|
|
|
assert len(chunks) == 2
|
|
first = chunks[0]
|
|
assert first.book == "Gênesis"
|
|
assert first.chapter == 1
|
|
assert first.verse == 1
|
|
assert first.page == 6
|
|
assert first.file == "biblia.pdf"
|
|
assert first.text == "No princípio criou Deus os céus e a terra."
|
|
|
|
second = chunks[1]
|
|
assert second.verse == 2
|
|
assert second.text.endswith("pairava sobre a face das águas.")
|
|
|
|
|
|
def test_chapter_marker_in_brackets_increments_chapter():
|
|
parser = BibleParser()
|
|
text = (
|
|
"GÊNESIS\n"
|
|
"[1]\n"
|
|
"1 No princípio criou Deus os céus e a terra.\n"
|
|
"\n"
|
|
"[2]\n"
|
|
"1 E disse Deus: haja luz. E houve luz.\n"
|
|
)
|
|
|
|
chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6})
|
|
|
|
assert {c.chapter for c in chunks} == {1, 2}
|
|
chapter_two = next(c for c in chunks if c.chapter == 2)
|
|
assert chapter_two.verse == 1
|
|
|
|
|
|
def test_verse_number_alone_on_a_line_joins_the_next_line():
|
|
parser = BibleParser()
|
|
text = (
|
|
"GÊNESIS\n"
|
|
"[1]\n"
|
|
"1 No princípio criou Deus os céus e a terra.\n"
|
|
"2\n"
|
|
"A terra era sem forma e vazia.\n"
|
|
)
|
|
|
|
chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6})
|
|
|
|
assert len(chunks) == 2
|
|
assert chunks[1].verse == 2
|
|
assert chunks[1].text == "A terra era sem forma e vazia."
|
|
|
|
|
|
def test_continuation_lines_are_appended_to_the_current_verse():
|
|
parser = BibleParser()
|
|
text = (
|
|
"GÊNESIS\n"
|
|
"[1]\n"
|
|
"1 No princípio criou Deus os céus e a terra.\n"
|
|
"sobre a face do abismo, mas o Espírito de Deus\n"
|
|
)
|
|
|
|
chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6})
|
|
|
|
assert len(chunks) == 1
|
|
assert chunks[0].text.endswith("sobre a face do abismo, mas o Espírito de Deus")
|
|
|
|
|
|
def test_hyphenated_word_at_line_end_is_joined():
|
|
parser = BibleParser()
|
|
text = (
|
|
"GÊNESIS\n"
|
|
"[3]\n"
|
|
"10 Respondeu-lhe o homem: Ouvi a tua voz no\n"
|
|
"jardim e tive medo, porque estava nu; e esconde-\n"
|
|
"me.\n"
|
|
)
|
|
|
|
chunks = parser.parse([make_page(12, text)], "biblia.pdf", {"Gênesis": 6})
|
|
|
|
assert len(chunks) == 1
|
|
assert "escondeme" in chunks[0].text
|
|
assert "esconde-\n" not in chunks[0].text
|
|
|
|
|
|
def test_lexical_hyphen_is_preserved():
|
|
parser = BibleParser()
|
|
text = (
|
|
"GÊNESIS\n"
|
|
"[1]\n"
|
|
"1 E disse Deus: haja uma separação entre águas e águas,\n"
|
|
"para separar as águas.\n"
|
|
)
|
|
|
|
chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6})
|
|
|
|
assert chunks
|
|
assert "para separar" in chunks[0].text
|
|
|
|
|
|
def test_pages_outside_any_book_are_discarded():
|
|
parser = BibleParser()
|
|
index_text = "Gênesis: 6\nÊxodo: 168\n"
|
|
copyright_text = "L.C.C. Publicações Eletrônicas\nProibido todo uso comercial.\n"
|
|
|
|
chunks = parser.parse(
|
|
[make_page(3, index_text), make_page(6, "GÊNESIS\n[1]\n1 No princípio.\n"), make_page(3364, copyright_text)],
|
|
"biblia.pdf",
|
|
{"Gênesis": 6, "Êxodo": 168},
|
|
)
|
|
|
|
assert all(c.book == "Gênesis" for c in chunks)
|
|
assert all("Publicações" not in c.text for c in chunks)
|
|
|
|
|
|
def test_book_names_are_recognized_in_canonical_order():
|
|
# Esta edição da Almeida não inclui Neemias nem Ester: 64 livros.
|
|
assert len(BOOKS) == 64
|
|
assert BOOKS[0] == "Gênesis"
|
|
assert BOOKS[37] == "Mateus"
|
|
assert BOOKS[-1] == "Apocalipse"
|
|
assert "Neemias" not in BOOKS
|
|
assert "Ester" not in BOOKS
|
|
|
|
|
|
def test_esdras_is_followed_directly_by_job():
|
|
"""O índice do PDF vai de Esdras (1407) direto para Jó (1440)."""
|
|
assert BOOKS.index("Esdras") + 1 == BOOKS.index("Jó")
|
|
|
|
|
|
def test_reference_is_formatted_as_book_chapter_verse():
|
|
parser = BibleParser()
|
|
text = "GÊNESIS\n[1]\n1 No princípio criou Deus os céus e a terra.\n"
|
|
|
|
chunks = parser.parse([make_page(6, text)], "biblia.pdf", {"Gênesis": 6})
|
|
|
|
assert chunks[0].reference == "Gênesis 1:1"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"raw,expected",
|
|
[
|
|
("Gênesis", "Gênesis"),
|
|
("Êxodo", "Êxodo"),
|
|
("Números", "Números"),
|
|
("Cântico dos Cânticos", "Cântico dos Cânticos"),
|
|
("I Coríntios", "I Coríntios"),
|
|
("II João", "II João"),
|
|
],
|
|
)
|
|
def test_canonical_book_names_are_preserved(raw, expected):
|
|
assert raw in BOOKS
|
|
assert expected == raw
|