Paginación, filtrado y ordenación

Defectos habituales en las API de listados y cómo probar a fondo la paginación, los filtros y la ordenación.

Actualizado:

Contenido

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.

plain text
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	6

Concatena 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)

Inspeccionar la ordenación y el filtrado con SQL

Rechazar parámetros de consulta no válidos