SQL para QA

Los conocimientos de SQL que realmente necesita QA y cómo las consultas básicas mejoran la investigación de defectos y la verificación de datos.

Actualizado:

Contenido

SQL para QA se centra en descubrir qué ocurrió realmente con los datos, no en optimizar consultas en profundidad ni en realizar tareas de administración de bases de datos. Cuando la interfaz y la API no coinciden, la base de datos suele proporcionar la evidencia más directa.

Incluso un conocimiento básico de SQL mejora considerablemente las pruebas. Permite verificar si se crearon registros, se conservaron estados, aparecieron duplicados, las relaciones son correctas, los informes cuadran o los datos desaparecieron después de una acción.

Por qué QA necesita SQL

En el trabajo diario, SQL suele cumplir tres objetivos:

  • →Comprobar el estado real de los datos después de un escenario
  • →Investigar los defectos con mayor rapidez
  • →Identificar si el problema está en la interfaz, la API, la lógica o los datos

Muchos aparentes defectos de botones son en realidad problemas del estado de los datos.

  • →Un registro aparece en la interfaz, pero faltan filas relacionadas
  • →La API informa de un éxito, pero una actualización no se guardó
  • →Un informe utiliza datos incorrectos
  • →Los reintentos crean duplicados
  • →Un filtro parece fallar porque los datos guardados ya difieren de lo que espera el producto

Sin SQL, estas investigaciones pueden ser lentas y carecer de información suficiente.

Qué aprender primero

QA no necesita dominar todo el lenguaje desde el principio. Empieza por manejar con confianza algunos elementos fundamentales.

  • →SELECT recupera datos
  • →WHERE filtra filas
  • →ORDER BY controla el orden
  • →LIMIT evita recuperar filas innecesarias
  • →COUNT mide cantidades
  • →JOIN relaciona datos de varias tablas
  • →GROUP BY permite obtener agregados y detectar duplicados
  • →IS NULL e IS NOT NULL comprueban valores nulos

Estos elementos cubren gran parte de las tareas diarias de prueba.

Comprende la finalidad de cada construcción además de su sintaxis. Con tablas de pedidos, usuarios y pagos, SQL puede verificar el escenario completo, no solo mostrar filas.

Qué aporta SQL a QA

La mayor fortaleza de SQL es la precisión.

La interfaz muestra información seleccionada; una API expone la respuesta de una llamada. La inspección directa de datos permite responder:

  • →¿Se llegó a crear el registro?
  • →¿Cuántos registros de ese tipo existen realmente?
  • →¿Hay duplicados?
  • →¿A qué usuario pertenece la entidad?
  • →¿Se guardó el estado correcto?
  • →¿Hay registros huérfanos?
  • →¿El importe coincide con el de la interfaz?
  • →¿La operación realmente modificó el registro o solo dio esa impresión?

Esto resulta especialmente útil para integraciones, colas, reintentos, tareas en segundo plano, actualizaciones masivas y relaciones complejas entre entidades.

JOIN para QA

JOIN es especialmente valioso porque muestra cómo se relacionan las entidades, más allá de inspeccionar las tablas por separado.

  • →Cada pedido tiene un propietario
  • →Un pedido contiene los artículos requeridos
  • →Un pago pertenece al pedido correcto
  • →Un usuario tiene el rol correcto
  • →Ningún registro hace referencia a objetos inexistentes

A menudo, un registro existe pero está relacionado incorrectamente o tiene rota parte de su cadena de relaciones. JOIN facilita la detección de estos defectos.

Errores frecuentes de SQL en QA

  • →Confundir NULL con un valor vacío
  • →No detectar filas duplicadas introducidas por JOIN
  • →Inspeccionar solo la primera fila que resulte conveniente
  • →Realizar escrituras innecesarias

Lo habitual más seguro es leer primero y efectuar cambios deliberados únicamente en un entorno apropiado. SELECT basta para la mayoría de las investigaciones.

Ejemplo práctico

Supongamos que un usuario informa de dos pedidos idénticos.

La interfaz proporciona una vista parcial y un endpoint de la API muestra una parte. SQL permite establecer mucho más:

  • →Si realmente existen dos filas de pedidos
  • →Si coinciden sus claves de negocio
  • →Si se crearon al mismo tiempo
  • →Si ambos tienen los mismos artículos de pedido
  • →Si un reintento generó el duplicado
  • →Si hay dos pagos o solo uno
  • →Si la duplicación es real o la interfaz muestra dos veces el mismo registro

Aquí SQL se convierte en una herramienta práctica de QA, no en un complemento técnico opcional.

Hábitos prácticos para QA

  • →Empieza por un SELECT sencillo
  • →Inspecciona primero una entidad y después sus relaciones
  • →Determina siempre qué clave identifica los datos
  • →Evita sacar conclusiones de una sola fila cuando importa un patrón más amplio
  • →Trata con cuidado las consultas que escriben datos
  • →Si tienes dudas, compara la evidencia de SQL con el comportamiento de la API y la interfaz

SQL es especialmente potente como puente entre las capas del sistema.

Ideas clave para QA

  • →QA utiliza SQL para verificar la realidad de los datos, no para programar una base de datos.
  • →SELECT, WHERE, JOIN, COUNT y GROUP BY básicos permiten investigar defectos con solidez.
  • →Muchos defectos del producto son problemas del estado de los datos.
  • →Conectar las evidencias de la interfaz, la API y la base de datos es una capacidad valiosa para las pruebas.
  • →SQL hace que el diagnóstico sea más preciso, rápido y metódico.

Lecturas adicionales

  • →En esta base de conocimientos: pruebas de bases de datos
  • →En esta base de conocimientos: JSON y XML
  • →Recurso externo: Tutorial de JOIN de PostgreSQL

Practicar con un único conjunto de datos: ocho ejercicios verificados

Utiliza la hoja de ejercicios de QA Hub enlazada y sql-for-qa-fixture.sql en lugar de crear un segundo conjunto de datos. Contiene cuatro clientes ficticios y cinco pedidos, con importes en céntimos enteros. Este recorrido utiliza SQLite 3; el recurso también describe SQL portable, pero estas instrucciones no afirman que se haya ejecutado en PostgreSQL. Descarga ambos archivos, abre un terminal en esa carpeta y mantén abierta una sola sesión.

plain text
sqlite3 :memory:
-- At the SQLite prompt:
.read sql-for-qa-fixture.sql
SELECT COUNT(*) FROM qa_customers;
-- Expected: 4
SELECT COUNT(*) FROM qa_orders;
-- Expected: 5

El fixture crea tablas temporales en la sesión actual. Una nueva sesión :memory: comienza vacía; volver a ejecutar CREATE en la misma sesión sin restablecerla falla porque las tablas ya existen. Para restablecer los datos, cierra la sesión desechable e inicia otra. No necesitas conexión a producción ni credenciales.

Predecir las filas antes de abrir las respuestas

plain text
Ejercicio del recurso	Resultado esperado
1 Pedidos pagados	(101, 1, 1200), (103, 2, 700), (105, 3, 0)
2 Pedidos por cliente, incluido cero	(1, Ada, 2), (2, Boris, 2), (3, Chen, 1), (4, Dina, 0)
3 Ingresos pagados por cliente	(1, 1200), (2, 700), (3, 0), (4, 0)
4 Clientes sin pedidos	(4, Dina)
5 Correos duplicados no nulos	(ada@example.invalid, 2)
6 Importe pagado inválido según la regla del ejercicio	(105, 0)
7 Al menos dos pedidos	(1, 2), (2, 2)
8 Correo ausente	(4, Dina)

Los números de los ejercicios y sus resultados son los mismos que en la hoja descargable. El correo electrónico duplicado y el pedido pagado de importe cero son ejemplos incorporados deliberadamente. Que constituyan un defecto en un producto real depende de sus requisitos. No deduzcas reglas de unicidad, importes positivos o normalización simplemente a partir de una consulta.

La trampa de LEFT JOIN: un total correcto con un cliente ausente

Compara estas dos consultas después de cargar el fixture compartido. La regla del informe es mostrar los cuatro clientes, incluidos los que no tienen pedidos pagados. La primera consulta sitúa el filtro paid en WHERE:

plain text
SELECT c.customer_id, COALESCE(SUM(o.amount_cents), 0) AS paid_cents
FROM qa_customers c
LEFT JOIN qa_orders o ON o.customer_id = c.customer_id
WHERE o.status = 'paid'
GROUP BY c.customer_id ORDER BY c.customer_id;

Devuelve (1,1200), (2,700), (3,0): Dina desaparece. Su fila sin coincidencia tiene NULL en los campos del pedido, por lo que la condición WHERE no la conserva. La suma sigue siendo 1900 céntimos; por eso comprobar únicamente el total general no detecta el defecto.

Coloca el filtro en la condición del JOIN para conservar los clientes sin coincidencias:

plain text
SELECT c.customer_id, COALESCE(SUM(o.amount_cents), 0) AS paid_cents
FROM qa_customers c
LEFT JOIN qa_orders o
  ON o.customer_id = c.customer_id AND o.status = 'paid'
GROUP BY c.customer_id ORDER BY c.customer_id;

Resultado esperado: (1,1200), (2,700), (3,0), (4,0). Comprueba tanto los identificadores exactos de los clientes como los importes. Para contar pedidos se necesita COUNT(o.order_id); COUNT(*) también cuenta una fila sin coincidencia del JOIN externo. Comprueba NULL con IS NULL, no con = NULL. La hoja de respuestas incluye estos casos con consultas ejecutables.

Convertir una discrepancia en evidencia útil

Registra el fixture o la versión de datos, el dialecto SQL, la consulta, la regla del producto, las filas esperadas y las obtenidas. Ordena explícitamente antes de comparar resultados ordenados. Si el orden no importa, compara conjuntos o multiconjuntos según si los duplicados son significativos. Que una consulta se ejecute correctamente no demuestra que su resultado de negocio sea correcto.

Seguir aprendiendo

Ampliar las comprobaciones al comportamiento de la base de datos

Informar de una discrepancia de datos con evidencias

Descargar el fixture SQL compartido

Descargar los ocho ejercicios de SQL con respuestas

Documentación de SQLite: SELECT, JOIN externos y filtrado