Las API de listados parecen sencillas, pero contienen muchos defectos problemáticos. Comprobar únicamente que se abre una lista puede dejar sin detectar registros duplicados o ausentes, orden inestable, recuentos totales incorrectos, filtros defectuosos e incoherencias entre páginas.
Los listados aparecen casi en todas partes: usuarios, pedidos, pagos, registros, eventos, productos, tareas y comentarios. Una paginación, un filtrado o una ordenación deficientes hacen que el producto parezca caótico: los registros desaparecen o aparecen dos veces, los filtros se comportan de forma inesperada, el orden cambia y la siguiente página presenta datos incoherentes.
Por qué las API necesitan estas funciones
Un servidor puede devolver todos los registros cuando son pocos. A medida que aumentan los datos, las respuestas pesan más, el cliente tiene dificultades para mostrarlas y el backend consume recursos innecesarios.
- →La paginación devuelve los datos por partes
- →El filtrado devuelve el subconjunto necesario
- →La ordenación define el orden de los elementos
Estos mecanismos casi siempre funcionan juntos. Un usuario abre una lista de pedidos, filtra por estado, ordena por fecha y cambia de página. La inestabilidad de cualquiera de las capas altera toda la experiencia.
Paginación
La paginación divide un conjunto de datos grande en páginas o lotes.
- →Paginación por desplazamiento: page=2, limit=20 u offset=20&limit=20
- →Paginación por cursor: cursor=..., starting_after=..., next_page_token=...
QA debe comprender la diferencia.
La paginación por desplazamiento es fácil de leer y habitual en interfaces de administración y API CRUD convencionales. Su debilidad es que el contenido de las páginas puede desplazarse cuando cambian los datos entre solicitudes. Un usuario ve 20 registros en la primera página; alguien añade uno; después, la segunda página contiene duplicados o se salta registros.
La paginación por cursor suele resistir mejor los cambios de datos. Es adecuada para listados grandes que se actualizan con frecuencia, feeds de eventos, transacciones y sistemas con mucha carga. La comprobación visual es más difícil porque QA debe seguir un cursor y el orden de los elementos, en lugar de un número de página conocido.
La principal consecuencia para QA es probar la paginación tanto con datos cambiantes como con un conjunto estático.
Filtrado
El filtrado limita un conjunto de datos según determinadas condiciones.
- →status = active
- →created_at >= date
- →price entre X e Y
- →owner_id = current user
- →Búsqueda por nombre o correo electrónico
- →Varios filtros aplicados conjuntamente
Esta función útil también es una fuente frecuente de defectos lógicos.
- →Un filtro se ignora parcialmente
- →Dos filtros se comportan de manera distinta juntos que por separado
- →Un filtro vacío y uno omitido se tratan de forma diferente
- →La distinción entre mayúsculas y minúsculas es inesperada
- →El filtrado por fecha falla debido a las zonas horarias
- →El filtrado del backend difiere de lo que espera la interfaz
- →Los permisos ocultan algunos registros y hacen pensar al usuario que el filtro falla
Probar el filtrado va más allá de comprobar una condición SQL o un parámetro de consulta. Consiste en establecer si el sistema devuelve exactamente el subconjunto que promete su contrato.
Ordenación
La ordenación define el orden de los resultados, normalmente por fecha, nombre, estado, prioridad, precio u otro campo.
El error más habitual es comprobar superficialmente que el orden parece aproximadamente correcto. En la práctica, la ordenación debe ser:
- →Correcta
- →Estable
- →Predecible
- →Compatible con la paginación
La estabilidad del orden es especialmente importante. Ordenar únicamente por un campo con valores repetidos, como marcas de tiempo created_at o estados idénticos, puede hacer que el orden de los registros empatados sea incoherente. Con paginación, los usuarios pueden entonces encontrar registros duplicados o ausentes entre páginas.
QA debe probar los empates además de la ordenación habitual por un solo campo.
Qué importa para QA
Varias comprobaciones resultan útiles en casi todos los casos.
Para la paginación:
- →La primera página
- →La última página
- →Una página vacía
- →Tamaño de página = 1
- →Tamaño de página en el máximo permitido
- →Tamaño de página superior al límite permitido
- →Movimiento entre páginas adyacentes
- →Ausencia de duplicados y omisiones entre páginas
- →Valores correctos de has_more, next_cursor y total_count, cuando se proporcionan
Para el filtrado:
- →Un filtro
- →Varios filtros juntos
- →Valores límite
- →Un valor vacío
- →Un filtro omitido
- →Un valor de filtro no válido
- →Filtrado de campos sujetos a controles de acceso
- →Filtrado por fecha y hora
Para la ordenación:
- →Orden ascendente y descendente
- →Ordenación por campos diferentes
- →Varios registros con valores iguales
- →Ordenación combinada con filtros
- →Ordenación combinada con paginación
- →Un campo de ordenación no admitido
Patrones de fallo frecuentes
- →Un elemento aparece tanto en la primera como en la segunda página
- →Un elemento desaparece entre páginas
- →total_count difiere del recuento real
- →Un filtro se aplica a los registros, pero no al recuento
- →El orden visible cambia entre solicitudes idénticas
- →Un registro nuevo desplaza posiciones y altera la navegación por desplazamiento
- →El backend ignora silenciosamente un filtro o una opción de ordenación desconocidos
- →La interfaz espera un orden y la API devuelve otro
- →Los filtros de fecha producen resultados distintos debido a las zonas horarias
- →Los filtros y los controles de acceso interactúan de forma inesperada
Esto es especialmente importante cuando los listados constituyen la principal interfaz de trabajo del producto. Incluso una pequeña inestabilidad puede deteriorar rápidamente la confianza del usuario.
Ejemplo práctico
Considera una API de listado de pedidos:
- →GET /orders?status=paid&sort=created_at_desc&limit=20
QA debe comprobar lo siguiente:
- →Solo se devuelven pedidos pagados
- →Los pedidos se ordenan por fecha en la dirección solicitada
- →Dos pedidos con el mismo created_at mantienen un orden relativo estable
- →La siguiente página no contiene duplicados ni omisiones
- →total_count, si existe, corresponde al conjunto de datos filtrado
- →La paginación se comporta de forma predecible si aparece un pedido nuevo durante la navegación
- →Los valores no válidos de sort o status se tratan claramente sin romper el servicio
Una lista puede parecer casi funcional y, sin embargo, estos detalles la hacen poco fiable en la práctica.
Ideas clave para QA
- →Prueba la paginación, el filtrado y la ordenación tanto juntos como por separado.
- →Las API de listados suelen fallar en los límites y las combinaciones de condiciones, más allá del recorrido correcto.
- →La paginación por desplazamiento es sencilla, pero sensible a los cambios de datos entre solicitudes.
- →La paginación por cursor resiste mejor los cambios de datos, pero requiere otro enfoque de prueba.
- →Una ordenación estable es esencial para una paginación correcta.
- →Comprueba total_count, has_more, los cursores y los límites de página con tanto cuidado como los propios registros.
Lecturas adicionales
- →En esta base de conocimientos: pruebas negativas de API
- →En esta base de conocimientos: métodos, códigos de estado y cabeceras
- →Recurso externo: Paginación de Stripe
Un conjunto de 12 registros con páginas esperadas conocidas
El fixture local comienza con los ID del 1 al 12. Score es floor((id−1)/3), de modo que tres registros consecutivos comparten puntuación. Los ID pares tienen estado open y los impares closed. La ordenación por score utiliza ID como clave secundaria, lo que resuelve los empates de forma determinista. Ejecuta las comprobaciones siguientes sobre un fixture nuevo, sin escrituras entre las solicitudes de páginas.
Consulta IDs esperados Total
?sort=score&limit=5&offset=0 1,2,3,4,5 12
?sort=score&limit=5&offset=5 6,7,8,9,10 12
?sort=score&limit=5&offset=10 11,12 12
?sort=score&limit=5&offset=12 (vacío) 12
?status=open&sort=score&limit=5&offset=0 2,4,6,8,10 6
?status=open&sort=score&limit=5&offset=5 12 6Concatena las tres primeras páginas y exige exactamente los ID del 1 al 12, sin duplicados ni huecos. Comprueba que total describa el conjunto filtrado antes de paginar, no la longitud de la página actual. En este contrato, limit debe estar entre 1 y 5, offset es un entero no negativo y los valores de ordenación o filtrado no admitidos devuelven 400.
Resolver los empates de forma estable no crea una instantánea. Si los datos cambian entre solicitudes por desplazamiento, los registros pueden cruzar los límites de página. Un experimento independiente debería definir el contrato de coherencia e insertar o eliminar entre solicitudes; la paginación por cursor también necesita un orden definido y una política de validez del cursor. El fixture proporcionado comprueba el comportamiento estático por desplazamiento, no esas garantías adicionales.
Seguir aprendiendo
Descargar el laboratorio de práctica local (ZIP)