Promover staging → master: v0.9.0 + tests + restore GA4#67
Merged
Conversation
…e 3) Cierra Sprint A (#44 Tipo de dúo end-to-end). El toggle ahora cubre toda la app: Foto, Película, Tasas, Calidad de la muestra y la sección Datos descargables. Calidad de la muestra - regenerar_calidad_panel() acepta parámetro window. En anual los dúos van T_n año X → T_n año X+1, periodo "YYYY_tN". - Detección de inconsistencia de edad usa rango [CH06, CH06 + 2] en anual (vs +1 en trimestral) para reflejar cumpleaños entre los dos años consecutivos. - Nuevo CSV data_output/calidad_panel_anual_pct_historico.csv (78 filas). - mod_calidad_panel_server recibe tipo_duo y usa el dataset correspondiente. Selector "duplas" se adapta al modo: 1→2 / 2→3 / 3→4 / 4→1 ↔ T1 vs T1 / ... / T4 vs T4. - duo_label() acepta window: en anual devuelve "tN" en lugar de "tN-tM". Sección Datos - Nueva tarjeta "Panel longitudinal · interanual" al lado de la intertrimestral. Mismo estilo card + dropdown. - Botones de descarga: Parquet (16 MB) y CSV gzip (18 MB). - Tracking GA4 con dataset = "panel_runtime_anual". - Handlers en app.R servirán los archivos generados por ETL/09b-build_paneles_runtime_anual.R (ya existentes desde v0.7.0). ETL/11-build_historicos_anuales.R - Sumado paso para regenerar_calidad_panel(window = "anual"). Bump v0.9.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sumar la primera capa de tests al proyecto. Stack confirmado por
research técnico: testthat 3.x + shiny::testServer() + shinytest2.
Este commit cierra Sprint test-1 parcial: setup + fixture + 4
archivos de tests con 42 tests pasando.
Setup
tests/testthat.R: runner principal que sourcea ETL y llama
testthat::test_dir(). NO sourcea 01-extract.R (datasets reales)
para que los tests sean rápidos.
tests/testthat/helper-fixtures.R: helper load_panel_mock() para
cargar el fixture sintético desde dentro de los tests.
tests/testthat/fixtures/_generar_fixtures.R: generador del
fixture (100 individuos × 3 ondas trimestrales con CODUSU
controlado, distribuciones EPH realistas, semilla fija).
tests/testthat/fixtures/panel_mock.rds: el fixture en sí
(versionado para reproducibilidad de tests sin tener que
re-generar localmente).
Tests
test-agrega_vars_derivadas.R (6 tests):
- Schema correcto post-función
- Reglas de formalidad clásica (asalariados con/sin PP07H)
- Reglas de formalidad ampliada (cuenta propia + monotributo,
patrones, TFSR siempre informal)
- Defensive: completa cols faltantes con NA, no rompe
- Preserva columnas originales
- Invariante de rango: solo 1L, 2L o NA
test-duos_disponibles_por_anio.R (6 tests):
- Trimestral con periodos completos
- Trimestral filtra cuando falta extremo
- Anual labels T1/T2/T3/T4
- Anual sin t+1 disponible → vacío
- Anual parcial (solo algunos trim de t+1)
- Default window = trimestral
test-armo_tabla_sankey.R (4 tests):
- Defensive con tabla vacía (regresión hotfix v0.7.0)
- Schema esperado en output
- Filtro por categoría con periodo_base = t_anterior
- Idem con t_posterior
test-duo_label.R (2 tests):
- Construye "tN-tM" formato intertrim
- Vectorizado
Resultado
[ FAIL 0 | WARN 0 | SKIP 0 | PASS 42 ]
Pendientes Sprint test-1
Tests sobre arma_tasas_destacadas, regenerar_panel_historico
(con fixture controlado para validar tasas a mano), armo_base_panel
modo legacy. CI GitHub Actions tests-unit.yml.
Sprint test-2 y test-3 quedan registrados en ROADMAP.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v0.9.0: Calidad + Datos descargables en modo Interanual (#47 Fase 3)
chore: setup base de testing (Sprint test-1, #61)
…-1, #61) Cierra Sprint test-1 con cobertura amplia de funciones puras y CI. 79 tests pasando. Tests nuevos test-arma_tasas_destacadas.R (6 tests): Casos controlados con panel mock pequeño donde las tasas se calculan a mano: - Persistencia 80% / Salida 20% / Entrada 27.3% - Caso 100% persistencia (todos siguen) - Caso 0% persistencia (todos transitan) - Categoría sin presencia → 0/100/100 - Variable distinta de ESTADO (CAT_OCUP) - Schema del output (list de 3 numéricos) test-regenerar_panel_historico.R (6 tests): Usa withr::with_tempdir() para no tocar data_output/. - Trimestral genera CSV con schema esperado - Trimestral usa formato de período "YYYY_tA-tB" - Anual usa formato "YYYY_tN" (sin -tM) - Idempotencia: 2da corrida no agrega duplicados - Tipos de columnas (weight numérico, periodo character) - Invariante: weight ∈ [0, 100] test-duo_label.R extendido (5 tests, era 2): Ahora que v0.9.0 está mergeado y la fn acepta `window`: - trimestral: "tN-tM" - anual: "tN" - default trimestral - vectorizado en ambos modos CI .github/workflows/tests-unit.yml: Corre Rscript tests/testthat.R en cada push y PR a master/staging. Cache de paquetes R via setup-r-actions. ~2-3 min de duración. Instala solo lo necesario (sin highcharter/gt/waiter UI-only). Resultado [ FAIL 0 | WARN 0 | SKIP 0 | PASS 79 ] Sprint test-1 cerrado. Próximo: Sprint test-2 (testServer). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Causa El job 'unit-tests' del PR #63 falló con "there is no package called 'highcharter'". El runner no tenía highcharter instalado porque el workflow lo había excluido (UI-only), pero tests/testthat.R sourceaba ETL/00-libraries.R que carga library(highcharter) explícitamente. Fix tests/testthat.R ahora carga solo los paquetes mínimos necesarios (dplyr, tidyr, tibble, eph, arrow, glue) y NO sourcea 00-libraries.R. Las funciones de R/utils_analisis.R que usan highcharter::hchart() internamente (arma_line_chart_areaspline) se DEFINEN al sourcear el archivo pero no se EJECUTAN, así que no requieren el paquete hasta que un test específico las invoque. Comentario actualizado en el workflow YAML para documentar la decisión. Validación local [ FAIL 0 | WARN 0 | SKIP 0 | PASS 79 ] Cuando arranque Sprint test-2 con tests de UI/server (testServer + shinytest2), evaluar si conviene un runner separado con su propia lista de paquetes (highcharter, gt, etc). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore: cerrar Sprint test-1 (#61) con tests de tasas + paneles históricos + CI
Cobertura de funciones puras restantes del Sprint test-1: - arma_matriz_transicion (R/utils_analisis.R): 6 tests para matriz NxN (estructura, suma 100% por fila, orden de etiquetas, manejo de categorías ausentes, soporte CAT_OCUP). - build_tasas_historico (ETL/99-functions.R): 8 tests para output trimestral/anual, invariantes (persistencia + salida = 100, tasas en [0, 100]), filtro desde_panel, vars_extra. - regenerar_calidad_panel (ETL/99-functions.R): 6 tests con with_tempdir() para schema, formato de periodos, idempotencia, % en rango, n_panel <= n_t0. - formato_delta (R/utils_analisis.R): 4 tests para flecha + signo + 'sin comparación' en NA/NULL. - sankey_label_legible (R/utils_analisis.R): 5 tests para mapeo de ESTADO/CAT_OCUP/formalidad, vectorización, fallback. - sankey_nodes_orden (R/utils_analisis.R): 3 tests para estructura de columna y orden no-alfabético. Quedan fuera del Sprint test-1: armo_base_panel modo legacy (mejor cubrirlo en Sprint test-2 junto con runtime mode usando testServer). Suite completa: 149 tests PASS · 0 fail · 1m local. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
test: Sprint test-1 batch 3 — +70 tests (total 149)
Cobertura de la capa server-side: - mod_calidad_panel_server (testServer): 9 tests para los reactives expuestos por el módulo. Switch del dataset según tipo_duo (trim ↔ anual), filtrado por rango de años y dúos, outputs KPI calculando promedios sobre el filtro activo. Mock de globals (df_calidad_panel + df_calidad_panel_anual) y stub global de renderHighchart para no exigir el paquete en CI. - armo_base_panel(window = "anual") (sin testServer): 6 tests con un parquet sintético en with_tempdir(). Verifica filter pushdown sobre (anio_0, trim_0), drop de esas cols del output, error informativo si no existe el parquet, validación de window inválido. Cubre el hotfix v0.7.3 (open_dataset vs read_parquet) sin tocar el archivo de producción. mod_analisis_*_server diferidos a Sprint test-3 (E2E con shinytest2): requieren mockear ~6 globals por módulo y el ROI es bajo vs probar el flujo real desde browser. Suite completa: 185 tests PASS · 0 fail. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
test: Sprint test-2 — server logic + armo_base_panel anual
Versión recortada del Sprint test-3 (scope inicial 5-7 tests + Codecov) con foco en cubrir el smoke y la regresión del toggle Tipo de dúo. ROI suficiente para el costo de mantenimiento de E2E. Tests cubiertos: - smoke: app levanta y registra el input tipo_duo con default "trimestral". - toggle Tipo de dúo: cambiar trimestral ↔ anual se refleja en el reactive state via input. Cubre regresión #44. - módulo Calidad: tras navegar al nav_panel, el output kpi_encontrado renderiza un valor numérico válido (forma "X.X%" o "—"). Infraestructura: - Workflow tests-e2e.yml separado con workflow_dispatch + cron semanal (domingo 06:00 UTC). NO corre en cada PR. tests-unit.yml sigue siendo la barrera obligatoria. - Guard RUN_E2E=true env var: la suite default (Rscript tests/testthat.R) salta los E2E manteniéndose rápida (~30s vs +3min). - Helper new_app() encapsula AppDriver$new + skips defensivos (paquetes ausentes, datasets faltantes, env var). Diferidos a futuro (documentados en ROADMAP): - E2E de descarga (quirk de Chromote con downloadHandler que copia archivos vía file.copy). - Codecov. - E2E de regresión #40 line charts (requiere snapshot testing). Suite total: 192 tests (185 unit + 7 E2E con RUN_E2E=true). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
test: Sprint test-3 lite — 3 tests E2E con shinytest2
Master HEAD venía con GA4_MEASUREMENT_ID <- "" desde el merge de PR #50 (staging → master, 2026-05-03). Ese merge pisó el ID válido de prod (commit f25f900) sin que se aplicara el git checkout master -- previsto en el procedimiento de promoción. Resultado: GA4 está roto en producción desde 2026-05-03 (4 días sin tracking). Restauro el ID. Al hacerse en este PR de promoción staging → master, queda atómico: el merge trae las features + tests Y vuelve el tracking en el mismo deploy. NOTA: Este archivo seguirá siendo el conflict point en futuros staging → master. Considerar git attribute merge=ours en master, o extraer GA4_MEASUREMENT_ID a un archivo separado que solo cambie en master (mejora futura, no implementada). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Promoción de staging a producción tras ~4 días de iteración sobre tests + features.
Cambios productivos (v0.9.0 ya documentado en CHANGELOG):
Infra de testing nueva:
RUN_E2E=truepara no inflar el ciclo dev.tests-unit.yml(cada PR) +tests-e2e.yml(manual + cron semanal).Fix crítico:
R/utils_analytics.R: restauroGA4_MEASUREMENT_ID = \"G-NQPB4BHWMM\". Master venía con "" desde el merge Setup staging environment and improve UI features #50 (4 días sin tracking en prod).Test plan
RUN_E2E=true: 192 tests verde.tests-unit.ymlverde sobre este PR.🤖 Generated with Claude Code