se reorganiza tests/ y se agrega suite pytest
Los scripts manuales pasan a tools/ y los correos de ejemplo a tests/fixtures/. Suite de 95 pruebas: caracterización de la extracción sobre los 46 correos (resultados esperados en tests/golden/, fuera de la carpeta que descargar_correos_prueba borra), unitarias de draft_sap, notificaciones, documentos, adjuntos y config_validator, y flujo completo de _procesar_un_correo con SAP/HANA/Outlook simulados. pytest como dependencia dev y configuración en pyproject.toml. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d4c1e0a264
commit
9d295d6485
261 files changed
+7876
-7
No files matched your search
@@ -10,4 +10,7 @@ adjuntos/
|
|||||||
resultado/
|
resultado/
|
||||||
emails.db
|
emails.db
|
||||||
.env.dev
|
.env.dev
|
||||||
|
.pytest_cache/
|
||||||
|
*.egg-info/
|
||||||
|
build/
|
||||||
procesos/
|
procesos/
|
||||||
@@ -41,6 +41,19 @@ python tools/consulta_rapida.py --set <nombre> # reprocesar correos por ID (se
|
|||||||
|
|
||||||
El demonio trabaja por bloques horarios (cada 1, 5, 30 o 60 minutos según la hora) y duerme fuera de ellos. Los bloques están en `HORARIOS` de `main.py` y se explican en [`docs/main.md`](docs/main.md).
|
El demonio trabaja por bloques horarios (cada 1, 5, 30 o 60 minutos según la hora) y duerme fuera de ellos. Los bloques están en `HORARIOS` de `main.py` y se explican en [`docs/main.md`](docs/main.md).
|
||||||
|
|
||||||
|
## Pruebas
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -e ".[dev]" # instala pytest
|
||||||
|
pytest # ~95 pruebas, unos 3 segundos; no tocan SAP, HANA ni Outlook
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Extracción** (`tests/test_extraccion_correos.py`): corre la extracción real sobre cada correo de `tests/fixtures/correos_prueba/` y la compara con `tests/golden/<caso>.json`. Esos resultados esperados fijan el comportamiento actual; no prueban que sea correcto. Si cambias la extracción a propósito, revisa el diff y regenéralos con `UPDATE_GOLDEN=1 pytest tests/test_extraccion_correos.py`.
|
||||||
|
- **Unitarias**: validación de precios, construcción del draft, notificaciones, guías, copia a red, filtrado de adjuntos y validación del `.env`.
|
||||||
|
- **Flujo completo** (`tests/test_pipeline_flujo.py`): `_procesar_un_correo` con SAP, HANA, Outlook y la BD simulados.
|
||||||
|
|
||||||
|
Los scripts de `tools/` (`procesar_pdfs_prueba.py`, `procesar_xmls_prueba.py`, etc.) son anteriores a la suite: escriben `xml_resultado_*.json` y `pdf_resultado_*.json` dentro de cada carpeta de `tests/fixtures/correos_prueba/`. Esos archivos no los usa ninguna prueba y pueden estar desactualizados. `tools/descargar_correos_prueba.py` **borra y vuelve a descargar** toda esa carpeta de correos reales.
|
||||||
|
|
||||||
## Carpetas de salida (ignoradas por git)
|
## Carpetas de salida (ignoradas por git)
|
||||||
|
|
||||||
| Ruta | Contenido |
|
| Ruta | Contenido |
|
||||||
@@ -62,8 +75,8 @@ El demonio trabaja por bloques horarios (cada 1, 5, 30 o 60 minutos según la ho
|
|||||||
| `sunat_schema.py`, `pdf_utilities.py` | Lectura de XML SUNAT y de PDF |
|
| `sunat_schema.py`, `pdf_utilities.py` | Lectura de XML SUNAT y de PDF |
|
||||||
| `database_utilities.py`, `email_utilities.py` | SQLite local; ZIP y filtrado de adjuntos |
|
| `database_utilities.py`, `email_utilities.py` | SQLite local; ZIP y filtrado de adjuntos |
|
||||||
| `logger_manager.py`, `config_validator.py`, `pipeline_utils.py` | Logging, validación del `.env`, utilidades |
|
| `logger_manager.py`, `config_validator.py`, `pipeline_utils.py` | Logging, validación del `.env`, utilidades |
|
||||||
| `tools/` | Scripts manuales (`consulta_rapida.py`, `aberio.http`, datos de prueba) |
|
| `tools/` | Scripts manuales: reprocesar correos, regenerar/inspeccionar los correos de prueba, `aberio.http` |
|
||||||
| `tests/` | Scripts de prueba manual y correos de ejemplo (`tests/correos_prueba/`) |
|
| `tests/` | Suite pytest, correos de ejemplo (`tests/fixtures/`) y resultados esperados (`tests/golden/`) |
|
||||||
|
|
||||||
## Documentación
|
## Documentación
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
| `outlook_utilities.py` | 249 | Comunicación con Microsoft Graph |
|
| `outlook_utilities.py` | 249 | Comunicación con Microsoft Graph |
|
||||||
| `hana_manager.py` | 141 | Comunicación con SAP HANA directa (fallback de `sapb1_manager` y valor referencial) |
|
| `hana_manager.py` | 141 | Comunicación con SAP HANA directa (fallback de `sapb1_manager` y valor referencial) |
|
||||||
| `database_utilities.py` | 117 | SQLite local (cache de correos) |
|
| `database_utilities.py` | 117 | SQLite local (cache de correos) |
|
||||||
|
| `tools/*_prueba.py`, `tools/completar_guias_pipeline.py`, `tools/explorar_notes_xml.py` | — | Scripts manuales sobre `tests/fixtures/correos_prueba/` (anteriores a la suite pytest) |
|
||||||
| `tools/consulta_rapida.py` | 120 | Script auxiliar para reprocesar correos por ID (sets en `tools/ids_prueba.json`) |
|
| `tools/consulta_rapida.py` | 120 | Script auxiliar para reprocesar correos por ID (sets en `tools/ids_prueba.json`) |
|
||||||
| `config_validator.py` | 83 | Valida el `.env` al arrancar (obligatorias, ruta de red, avisos de SSL) |
|
| `config_validator.py` | 83 | Valida el `.env` al arrancar (obligatorias, ruta de red, avisos de SSL) |
|
||||||
| `email_utilities.py` | 55 | Utilitarios de adjuntos (ZIP, filtrado) |
|
| `email_utilities.py` | 55 | Utilitarios de adjuntos (ZIP, filtrado) |
|
||||||
|
|||||||
@@ -16,6 +16,15 @@ dependencies = [
|
|||||||
"urllib3==2.7.0",
|
"urllib3==2.7.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest==9.1.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["tests"]
|
||||||
|
pythonpath = ["."]
|
||||||
|
|
||||||
[tool.setuptools]
|
[tool.setuptools]
|
||||||
py-modules = [
|
py-modules = [
|
||||||
"adjuntos",
|
"adjuntos",
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
RAIZ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
FIXTURES = os.path.join(RAIZ, "tests", "fixtures", "correos_prueba")
|
||||||
|
GOLDEN = os.path.join(RAIZ, "tests", "golden")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def actualizar_golden() -> bool:
|
||||||
|
"""True si se ejecutó con ``UPDATE_GOLDEN=1`` (regenera los resultados esperados)."""
|
||||||
|
return os.environ.get("UPDATE_GOLDEN") == "1"
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 261 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user