📑 Índice del documento
- Tabla de notas
- Group ONE — 8.6 / 10
- Systeam — 8.1 / 10
- Proxy Team — 8.75 / 10
- CFZ++ — 8.4 / 10
- Puntos transversales
Correcciones — TP 1 · Parte 1
Corrección de los cuatro grupos que entregaron la Parte 1 del TP 1 (Selenium + MercadoLibre, Hits #1–#3). Para cada grupo se detallan los puntos positivos destacables y las razones concretas de cada descuento. La metodología completa se puede consultar en la consigna original.
Tabla de notas
| Grupo | Integrantes | Repositorio | Nota |
|---|---|---|---|
| Group ONE | Anito, Cristian · Soto, Roberto · Claros, Federico · Romero, Nicolas · Buzzo Marcelo, Rocco · Echeverria Crenna, Gonzalo | GonzaEC/TP2-SIP | 8.6 / 10 |
| Systeam | Hoffmann, Axel · Babino, Abril · Avila, Tobias · Collazo, Naiara · Nomico, Mateo · Casal, Ulises | UlisesCasal/SIP-Selenium-Systeam | 8.1 / 10 |
| Proxy Team | Ponti, Mateo Daniel · Scialchi, Luciano Agustin · Romero Monteagudo, Valentín Joel · Cacciatore, Bautista · Correa, Miqueas | correamiq/Testing-Selenium-ProxyTeam | 8.75 / 10 |
| CFZ++ | Saracho, Franco Mateo · Ausqui, Mateo · Zander, Matt · Contardi, Gustavo · Huici, Nicolas | GustavoContardi/TP1-Selenium | 8.4 / 10 |
Group ONE — 8.6 / 10
Lo que está bien
- HIT #2 perfecto (25/25):
BrowserFactory.javacon jerarquía de resolución argumento → system property → env var → default, que es exactamente el comportamiento esperado en un entorno CI/CD. - Selectores con fallback: lista ordenada de selectores CSS (
a.poly-component__title,.ui-search-item__title, etc.) que tolera cambios de DOM de MercadoLibre. - Tests completos (8/8):
BrowserFactoryTest,MercadoLibreScrapperTestyProductResultSchemaTestcon JUnit 5 + Mockito, con validación de schema y tipos.
Lo que resta nota
Docker implementado en HIT6, no en HIT1–3 (−3.5 pts en sección Docker): La consigna de Parte 1 requería Docker como entregable progresivo desde los primeros hits; al concentrarlo en HIT6 queda fuera del alcance de evaluación de Parte 1. El Dockerfile en sí es de buena calidad (multi-stage, versiones pinneadas), pero su ausencia en HIT1–3 penaliza la sección.
Logging con prefijos manuales en HIT1–3 (−1 pt): El código usa strings como
[INFO],[WARN],[ERROR]en lugar de un framework real (SLF4J/Logback). No permite filtrar por nivel ni redirigir la salida; SLF4J aparece recién en HIT6.Cobertura de productos en HIT3 incompleta (−2 pts en 3.3): Solo hay evidencia clara de que HIT3 procesa "bicicleta rodado 29"; los productos iPhone 16 Pro Max y GeForce RTX 5090 parecen incorporarse recién en HIT4. El código de HIT3 debería iterar explícitamente sobre los 3 productos requeridos.
Informe de selectores no unificado (−1 pt en 4.4): Las decisiones técnicas están distribuidas en los READMEs de cada HIT y en los ADRs, pero la consigna pedía un informe unificado con la estrategia de selectores y la comparativa Chrome/Firefox en un único documento.
Systeam — 8.1 / 10
Lo que está bien
- HIT #2 perfecto (25/25): Separación
BrowserOptions/BrowserFactorypermite testear la lógica de configuración sin instanciar un WebDriver real; es el diseño más testeable de los grupos evaluados. - FiltersPage con triple fallback (15/15 en 3.1): Estrategia CSS → XPath sección → XPath texto con soporte de componente
<select>nativo y dropdown Andes custom. - Docker con usuario no-root y Chrome oficial (9.5/10): buena práctica de seguridad y estabilidad.
Lo que resta nota
FALLBACK_PRODUCTScon datos hardcodeados (−10 pts en sección 3.4): EnHIT3/src/scrapers/mercadolibre.jsexiste un objeto con 5 productos ficticios por query (conurl: nully precios inventados) que se activa cuando el scraping falla tras los reintentos. Esto hace que los tests siempre pasen aunque el scraper esté completamente roto, quitándole todo valor al suite de tests como mecanismo de control de calidad. La solución correcta es dejar que el scraper falle con un error explícito y que los tests reflejen ese fallo.CI con "mock data enabled" (incluido en el −10): El workflow
scrape.ymlcorre con una flag que bypasea el scraping real, lo que significa que el pipeline de CI nunca verifica que el scraper funcione en producción. Un pipeline que siempre pasa no es evidencia de que el sistema funciona.Integrantes ausentes del README raíz (−1 pt en 4.4): Ningún README del repo lista los integrantes ni sus legajos, que es un requisito básico de entrega del TP.
Proxy Team — 8.75 / 10
Lo que está bien
- HIT #2 perfecto (25/25):
create_driver()con prioridad CLI → env var → default correctamente implementada; tabla comparativa Chrome/Firefox documentada en el README. - Cero antitrampas: sin fallback hardcodeado, sin datos dummy, sin bypass de scraping en CI.
- Tests estructurados (8/8):
test_extractors.py,test_schema.py,test_driver_factory.pycon mocks, validación de tipos y gate de cobertura ≥ 70 % enforced tanto en CI como en el Dockerfile.
Lo que resta nota
Sin logging estructurado en HIT1 (−2 pts en 1.3): El código usa únicamente
print()en lugar del módulologgingde Python con niveles INFO/WARN/ERROR; esto impide filtrar por severidad, redirigir la salida o integrar con sistemas de observabilidad.safe_click()no loguea WARNING cuando el filtro no está disponible (−2 pts en 3.1): La función capturaTimeoutExceptiony retornaFalseen silencio total. El comportamiento correcto eslogger.warning(f"Filtro no disponible: {xpath} para '{product}'")para que el operador sepa qué filtros no se aplicaron en cada ejecución.Dockerfile no usa
requirements.txt(−1 pt en 4.1):hit4/Dockerfileejecutapip install selenium pytestsin versiones y sin-r requirements.txt, lo que hace que la imagen instale versiones distintas a las del entorno local y rompe la reproducibilidad. La imagen basepython:3.13-slim-trixieusa Debian "trixie" (branch testing), no recomendado para producción.
CFZ++ — 8.4 / 10
Lo que está bien
- HIT #2 perfecto (25/25):
browser_factory.pycomo módulo dedicado (noconftest.py) con prioridad CLI → env var → default documentada explícitamente. - Docker perfecto (10/10): multi-stage build,
python:3.12.10-slimpinneado a nivel patch, geckodriverv0.35.0versionado,docker-compose.ymlen la raíz con todas las variables relevantes. - Pipeline CI/CD más completo del curso: gitleaks → build Docker → scraping paralelo Chrome/Firefox → tests con coverage → validación de manifests k8s con
kubeconform.
Lo que resta nota
HIT3 procesa solo 1 producto (−8 pts en 3.2 y 3.3):
QUERY = "bicicleta rodado 29"está hardcodeado enhit3/scraper.py; la parametrización multi-producto recién aparece en hit4. La consigna de HIT3 exige iterar sobre los 3 productos (bicicleta, iPhone 16 Pro Max, GeForce RTX 5090), y cada uno debe tener sus filtros aplicados.Sin graceful degradation en los filtros (−4 pts en 3.1):
apply_condition_nuevo(),apply_tienda_oficial()yapply_sort_relevancia()no tienentry/except; si algún filtro no está disponible para un producto elwait.until()lanzaTimeoutExceptionno capturada y el script termina abruptamente. El patrón correcto es envolver cada llamada en un bloque que captureTimeoutException, loguee un WARNING y continúe con el siguiente paso.Versiones no pinneadas en hit1–hit3 (−1 pt en 1.1):
requirements.txtusaselenium>=4.20en lugar deselenium==4.21.0, lo que permite que instalaciones en distintos momentos resuelvan a versiones diferentes y potencialmente incompatibles.
Puntos transversales a todos los grupos
README raíz sin integrantes: ningún grupo lista correctamente los integrantes en el README raíz del repositorio; es el primer ítem que verifica cualquier corrector.
Graceful degradation de filtros: la mayoría aplicó los filtros correctamente cuando están disponibles, pero el manejo del caso en que un filtro no existe — capturar
TimeoutException, loguear WARNING y continuar — fue el criterio con más fallas transversales. No romper ante un filtro ausente es tan importante como aplicar el filtro cuando está disponible.time.sleep()prohibido: todos los grupos cumplen este punto en hit1–hit3, lo cual es positivo. Cualquier uso en hits posteriores debe estar justificado con una constante nombrada y un comentario explicando por qué es necesario.