feat: Enhance testing framework by adding new PDF files for count-api latency tests, updating .gitignore to include additional CSV reports, and refining documentation for improved clarity on test results and methodologies.

This commit is contained in:
erik
2026-07-13 22:46:19 -05:00
parent 1935552f4e
commit e47ef4f8c6
30 changed files with 488 additions and 217 deletions
@@ -10,11 +10,11 @@
\midrule
\texttt{bots/bot\_descarga/tests} & \pass & 19/19 & 3{,}21\,s \\
\texttt{services/bot\_descarga/tests} & \pass & 7/7 & 1{,}45\,s \\
\texttt{go test} count-api (\texttt{internal/pipeline}) & \pass$^{*}$ & 3+8 nuevos & ver Timing \\
\texttt{go test} count-api (\texttt{internal/pipeline}) & \pass & 11/11 & + Timing/HTTP en cap.~\ref{ch:count-latency} \\
Vitest desktop & \neje & --- & No ejecutado en esta sesi\'on \\
\bottomrule
\end{tabular}
\caption{Resultados unitarios. $^{*}$Base 3 PASS confirmados en Ubuntu; ampliaci\'on features/clustering (+8) y Timing sobre 3 PDFs reales requieren \texttt{go test} en host con Tesseract.}
\caption{Resultados unitarios.}
\end{table}
\section{Cobertura agent}
@@ -24,12 +24,8 @@ Incluye excel reader, PDF validator, file manager, cancel, browser fatal, MinIO
Incluye helpers MinIO, register/heartbeat/offline, claim at\'omico, cancel, events, filtros por job padre (7 casos).
\section{Cobertura count-api}
Ejecutado en Ubuntu (deps Tesseract/Leptonica):
tests originales de features (3) \pass.
Ampliaci\'on: \texttt{features\_extra\_test.go} + \texttt{clustering\_test.go} (+8 casos).
Medici\'on de documentos: \texttt{processor\_timing\_test.go} sobre
\texttt{docs/plan\_pruebas/data/*.pdf} (3 archivos); ver cap.~\ref{ch:count-latency}.
\texttt{PDFResult} ahora incluye \texttt{render\_ms}/\texttt{ocr\_ms}/\texttt{cluster\_ms}/\texttt{infer\_ms}/\texttt{total\_ms}.
Ver cap\'itulo~\ref{ch:count-latency}: explicaci\'on test a test con ejemplos,
gr\'aficas y resultados (11 unitarias PASS; HTTP 3 PDFs ok en 2{,}2--4{,}5\,s).
\begin{figure}[ht]
\centering
@@ -46,7 +42,7 @@ Medici\'on de documentos: \texttt{processor\_timing\_test.go} sobre
bar width=10pt,
legend style={at={(0.98,0.35)},anchor=east,font=\small}
]
\addplot[fill=passgreen!70] coordinates {(19,agent) (7,api-store) (3,count-api) (0,desktop)};
\addplot[fill=passgreen!70] coordinates {(19,agent) (7,api-store) (11,count-api) (0,desktop)};
\addlegendentry{PASS}
\addplot[fill=ipsgrey!40] coordinates {(0,agent) (0,api-store) (0,count-api) (1,desktop)};
\addlegendentry{N/E}
@@ -1,49 +1,244 @@
\chapter{Resultados --- latencia count-api (PDFs reales)}
\chapter{Count-api: qu\'e eval\'ua cada prueba}
\label{ch:count-latency}
\section{Fixtures}
Tres PDFs en \texttt{docs/plan\_pruebas/data/}:
Este cap\'itulo explica, con ejemplos, las pruebas del microservicio \textbf{count-api}
(conteo de servicios en facturas PDF) y resume los \textbf{resultados} obtenidos
en el host Ubuntu el 13 de julio de 2026.
\section{Pipeline bajo prueba}
\begin{center}
\begin{tikzpicture}[
font=\small,
box/.style={draw=ipsblue, rounded corners=2pt, align=center, inner sep=5pt, minimum height=0.75cm},
arr/.style={-{Latex}, thick, ipsblue}
]
\node[box, fill=codebg] (pdf) {PDF};
\node[box, right=0.45cm of pdf] (ren) {Render\\DPI};
\node[box, right=0.45cm of ren] (ocr) {OCR\\Tesseract};
\node[box, right=0.45cm of ocr] (clu) {Cluster\\Y (DBSCAN)};
\node[box, right=0.45cm of clu] (fea) {14\\features};
\node[box, right=0.45cm of fea] (ml) {ONNX /\\heur\'istica};
\draw[arr] (pdf) -- (ren);
\draw[arr] (ren) -- (ocr);
\draw[arr] (ocr) -- (clu);
\draw[arr] (clu) -- (fea);
\draw[arr] (fea) -- (ml);
\end{tikzpicture}
\end{center}
Las unitarias de \texttt{features} y \texttt{clustering} \textbf{no} abren el PDF:
simulan ``cajas'' OCR \texttt{\{texto, X, Y\}}. Timing y HTTP s\'i usan los 3 PDFs reales.
\section{Resultado global count-api}
\begin{table}[ht]
\centering
\begin{tabular}{@{}llrl@{}}
\toprule
\textbf{Bloque} & \textbf{Resultado} & \textbf{Casos} & \textbf{Notas} \\
\midrule
Features + clustering & \pass & 11/11 & Ubuntu, \texttt{go test -v} \\
HTTP 3 PDFs reales & \pass & 3/3 & 200, status ok, $\sim$2--4{,}5\,s \\
Timing Go por etapa & pendiente / skip path & --- & re-ejecutar \texttt{-run Timing -count=1} \\
\bottomrule
\end{tabular}
\caption{Scorecard count-api en esta campa\~na.}
\end{table}
\begin{figure}[ht]
\centering
\begin{tikzpicture}
\begin{axis}[
ybar,
width=0.85\textwidth,
height=5cm,
ylabel={Casos},
symbolic x coords={Features,Clustering,HTTP-PDF,Timing-Go},
xtick=data,
nodes near coords,
ymin=0, ymax=12,
bar width=14pt,
enlarge x limits=0.15,
legend style={at={(0.98,0.98)},anchor=north east,font=\small}
]
\addplot[fill=passgreen!75] coordinates {(Features,7) (Clustering,4) (HTTP-PDF,3) (Timing-Go,0)};
\addlegendentry{PASS}
\addplot[fill=ipsgrey!45] coordinates {(Features,0) (Clustering,0) (HTTP-PDF,0) (Timing-Go,1)};
\addlegendentry{Pendiente}
\end{axis}
\end{tikzpicture}
\caption{Cobertura count-api por bloque.}
\label{fig:count-score}
\end{figure}
\section{Features: qu\'e se eval\'ua (con ejemplo)}
El extractor construye un vector de \textbf{14 features} por fila (compatible con el modelo ONNX).
\'Indices relevantes en las pruebas:
\begin{center}
\small
\begin{tabular}{@{}clp{7.5cm}@{}}
\toprule
\textbf{\#} & \textbf{Nombre} & \textbf{Significado} \\
\midrule
1 & service\_code & Primer token parece c\'odigo de servicio \\
2 & table\_pattern & Fila tipo tabla (montos + enteros) \\
3 & header\_keyword & Palabras de cabecera (FACTURA, NIT, \ldots) \\
4 & currency\_at\_end & Monto al final de la fila \\
6 & continuation & Continuaci\'on de la fila de servicio anterior \\
\bottomrule
\end{tabular}
\end{center}
\subsection{TestExtractRowFeaturesServiceTablePattern --- \pass}
\textbf{Eval\'ua:} detectar una l\'inea de servicio ``de verdad'' (c\'odigo + descripci\'on + valores).
\textbf{Ejemplo de entrada (cajas simuladas):}
\begin{lstlisting}[language={}]
890701 | CONSULTA | 16,277.00 | 1 | 16,277.00
\end{lstlisting}
\textbf{Esperado:} feature[2]=1 (patr\'on tabla) y feature[4]=1 (moneda al final).
\subsection{TestBuildFeaturesContinuation --- \pass}
\textbf{Eval\'ua:} la segunda l\'inea es continuaci\'on del servicio, no un servicio nuevo.
\textbf{Ejemplo:}
\begin{lstlisting}[language={}]
Fila 1: 890701 CONSULTA 16,277.00 1 16,277.00
Fila 2: DE SEGUIMIENTO
\end{lstlisting}
\textbf{Esperado:} 2 filas; feature[6]=1 en la fila 2 (\texttt{is\_likely\_continuation}).
\subsection{TestExtractRowFeaturesHeaderKeyword --- \pass}
\textbf{Eval\'ua:} no confundir cabecera de factura con servicio.
\textbf{Ejemplo:} \texttt{FACTURA NIT 123} $\rightarrow$ feature[3]=1 (header).
\subsection{TestExtractRowFeaturesServiceCode --- \pass}
\textbf{Eval\'ua:} el primer token tipo c\'odigo alfanum\'erico (\texttt{AB12}) activa feature[1].
\subsection{TestExtractRowFeaturesNoTablePattern --- \pass}
\textbf{Eval\'ua:} texto libre (\texttt{TEXTO LIBRE}) \textbf{no} marca patr\'on de tabla (feature[2]=0).
\subsection{TestBuildFeatureRowsEmpty --- \pass}
\textbf{Eval\'ua:} sin cajas OCR $\rightarrow$ 0 filas (comportamiento seguro).
\subsection{TestFeatureCount --- \pass}
\textbf{Eval\'ua:} \texttt{FeatureCount == 14} (rompe el build si el modelo ML y el c\'odigo divergen).
\section{Clustering: qu\'e se eval\'ua (con ejemplo)}
Tras el OCR, las palabras se agrupan en \textbf{filas} con DBSCAN 1D sobre la coordenada $Y$.
\subsection{TestClusterRowsTwoBands --- \pass}
\textbf{Ejemplo:} palabras en $Y\approx 100$ y $Y\approx 300$ $\rightarrow$ \textbf{dos} clusters distintos
(dos renglones de la factura).
\subsection{TestClusterRowsSameBand --- \pass}
\textbf{Ejemplo:} $Y=50,52,54$ $\rightarrow$ \textbf{un} solo cluster (misma l\'inea visual).
\subsection{TestClusterRowsEmpty --- \pass}
\textbf{Eval\'ua:} \texttt{nil} o slice vac\'io no provoca panic.
\subsection{TestClusterRowsNoiseMinSamples --- \pass}
\textbf{Ejemplo:} con \texttt{minSamples=2}, un punto solo queda como ruido (\texttt{cluster=-1});
un par cercano forma cluster.
\begin{figure}[ht]
\centering
\begin{tikzpicture}
\begin{axis}[
width=0.9\textwidth,
height=5.2cm,
xlabel={X (simulado)},
ylabel={Y (simulado)},
title={Idea de clustering: dos bandas Y},
xmin=0, xmax=120,
ymin=0, ymax=350,
legend style={at={(0.98,0.98)},anchor=north east,font=\small},
grid=major
]
\addplot[only marks, mark=*, blue] coordinates {(10,100) (40,102) (70,101)};
\addlegendentry{Fila 1 ($Y\sim 100$)}
\addplot[only marks, mark=square*, red] coordinates {(10,300) (50,301) (80,298)};
\addlegendentry{Fila 2 ($Y\sim 300$)}
\end{axis}
\end{tikzpicture}
\caption{Ilustraci\'on del test de dos bandas (no son coordenadas OCR reales).}
\label{fig:cluster-idea}
\end{figure}
\section{Pruebas con PDFs reales}
\subsection{Fixtures}
\begin{itemize}
\item \texttt{500000284335937.pdf}
\item \texttt{500000284335940.pdf}
\item \texttt{500000284335954.pdf}
\end{itemize}
Ubicaci\'on: \texttt{docs/plan\_pruebas/data/}.
\section{Unitarias pipeline ampliadas}
Adem\'as de los 3 tests originales de features:
\begin{itemize}
\item Header keyword, service code, empty rows, no table pattern.
\item Clustering: dos bandas Y, misma banda, vac\'io, ruido \texttt{minSamples}.
\end{itemize}
Total esperado en \texttt{go test ./internal/pipeline/ -run 'TestExtract|TestBuild|TestFeature|TestCluster'}: \textbf{11} casos.
\subsection{TestProcessPDFTimingFixtures}
\textbf{Eval\'ua:} pipeline completo (render$\rightarrow$OCR$\rightarrow$cluster$\rightarrow$conteo) y que
\texttt{total\_ms $> 0$} con status ok (o reporta error). Expone ms por etapa en \texttt{PDFResult}.
\section{Timings por etapa}
El procesador expone \texttt{render\_ms}, \texttt{ocr\_ms}, \texttt{cluster\_ms}, \texttt{infer\_ms}, \texttt{total\_ms} en \texttt{PDFResult}.
\subsection{Script HTTP \texttt{measure\_count\_latency}}
\textbf{Eval\'ua:} el camino real del usuario/Desktop: gateway \texttt{POST /count/v1/count}.
\begin{lstlisting}[language=bash,caption={Medici\'on en Ubuntu}]
cd services/services-count-facturas-medicas-serving
go test ./internal/pipeline/ -run Timing -v
# HTTP v\'ia gateway:
bash docs/plan_pruebas/scripts/measure_count_latency.sh
# o PowerShell:
# .\docs\plan_pruebas\scripts\measure_count_latency.ps1
\end{lstlisting}
Los resultados de la corrida Timing/HTTP deben pegarse en
\texttt{docs/plan\_pruebas/informes/count\_latency\_YYYYMMDD.csv} y actualizar esta tabla.
\section{Resultados de latencia HTTP (medidos)}
Host \texttt{ubuntu}, gateway \texttt{127.0.0.1:8189}, 13 jul 2026:
\begin{table}[ht]
\centering
\begin{tabular}{@{}lrrrrrl@{}}
\begin{tabular}{@{}lrrll@{}}
\toprule
\textbf{PDF} & \textbf{render} & \textbf{ocr} & \textbf{cluster} & \textbf{infer} & \textbf{total} & \textbf{status} \\
\textbf{PDF} & \textbf{t (s)} & \textbf{HTTP} & \textbf{servicios} & \textbf{status} \\
\midrule
500000284335937 & --- & --- & --- & --- & --- & pendiente Ubuntu \\
500000284335940 & --- & --- & --- & --- & --- & pendiente Ubuntu \\
500000284335954 & --- & --- & --- & --- & --- & pendiente Ubuntu \\
500000284335937.pdf & 4{,}45 & 200 & 1 & ok \\
500000284335940.pdf & 2{,}29 & 200 & 1 & ok \\
500000284335954.pdf & 2{,}19 & 200 & 1 & ok \\
\midrule
Promedio & 2{,}98 & --- & --- & --- \\
M\'in / M\'ax & 2{,}19 / 4{,}45 & --- & --- & --- \\
\bottomrule
\end{tabular}
\caption{Latencia por etapa (ms). Completar tras \texttt{-run Timing} en el host con Tesseract.}
\label{tab:count-timing}
\caption{Wall-clock HTTP. Fuente: \texttt{informes/count\_latency\_20260713.csv}.}
\label{tab:count-http}
\end{table}
\begin{figure}[ht]
\centering
\begin{tikzpicture}
\begin{axis}[
ybar,
width=0.95\textwidth,
height=6cm,
ylabel={Segundos (HTTP)},
symbolic x coords={...937,...940,...954},
xtick=data,
nodes near coords,
nodes near coords style={font=\small},
ymin=0, ymax=5.5,
bar width=22pt,
enlarge x limits=0.2,
title={Tiempo de conteo por PDF (gateway)}
]
\addplot[fill=ipsblue!80] coordinates {(...937,4.45) (...940,2.29) (...954,2.19)};
\addplot[warnorange, ultra thick, sharp plot, update limits=false] coordinates {(...937,2.98) (...954,2.98)};
\end{axis}
\end{tikzpicture}
\caption{Barras: tiempo por PDF. L\'inea naranja: promedio 2{,}98\,s.}
\label{fig:count-http-bars}
\end{figure}
\textbf{Lectura:} en este host, contar \emph{una} factura tarda del orden de \textbf{2--5 segundos}
(OCR suele dominar). Extrapolaci\'on ingenua a 3\,s/PDF $\approx$ 1\,200 facturas/hora de conteo
si el nodo estuviera dedicado y sin colas --- ver cap\'itulo de capacidad 100k/mes para el contexto completo.
\section{C\'omo reproducir}
\begin{lstlisting}[language=bash]
cd services/services-count-facturas-medicas-serving
go test ./internal/pipeline/ -v -count=1
go test ./internal/pipeline/ -run Timing -v -count=1
# opcional:
export COUNT_TEST_PDF_DIR=$PWD/../../docs/plan_pruebas/data
bash docs/plan_pruebas/scripts/measure_count_latency.sh
\end{lstlisting}