¿Qué son las pruebas de concurrencia en las pruebas de software?

⚡ Resumen inteligente

Las pruebas de concurrencia detectan defectos que solo aparecen cuando varios usuarios actúan sobre la misma aplicación al mismo tiempo, lo que expone interbloqueos, actualizaciones perdidas y problemas de bloqueo que las comprobaciones funcionales secuenciales nunca revelan.

  • 👥 También llamado: Pruebas multiusuario, ya que el factor desencadenante es el acceso simultáneo y no solo un alto volumen de usuarios.
  • 🎯 A qué apunta: Registros de bases de datos compartidos, módulos compartidos y código de aplicación compartido al que se accede desde más de una sesión.
  • 🔒 Qué mide: Niveles de interbloqueo, bloqueo, código de un solo hilo y acceso restringido a recursos compartidos.
  • 🧭 Cómo funciona: Identifique los flujos propensos a la concurrencia, establezca un objetivo de concurrencia, programe acciones reales y, a continuación, aumente gradualmente el número de usuarios.
  • ???? Clases de defectos: Condiciones de carrera, interbloqueos, actualizaciones perdidas, corrupción de datos y falta de recursos en los subprocesos.
  • ⚠️ Límites honestos: El no determinismo, las devoluciones de llamada asíncronas y una pila de llamadas poco informativa dificultan la reproducción de los fallos.

¿Qué son las pruebas de concurrencia en las pruebas de software con múltiples usuarios simultáneos?

¿Qué son las pruebas de concurrencia?

Pruebas de concurrencia Es una técnica de prueba que se utiliza para detectar defectos en una aplicación cuando varios usuarios están conectados simultáneamente. En otras palabras, monitoriza el efecto cuando varios usuarios realizan la misma acción al mismo tiempo.

Las pruebas de concurrencia también se conocen como pruebas multiusuarioProbar un programa concurrente es más difícil que probar un programa secuencial, debido a la falta de determinismo y a los problemas de sincronización: la misma prueba puede pasar en una ejecución y fallar en la siguiente sin que cambie ni una sola línea de código.

El siguiente diagrama ilustra la idea: varios usuarios acceden al mismo recurso de la aplicación en el mismo instante, y la prueba observa qué hace la aplicación con la superposición.

Diagrama de pruebas de concurrencia que muestra a varios usuarios accediendo simultáneamente al mismo recurso de la aplicación.

¿Por qué realizar pruebas de concurrencia?

Dos preguntas justifican el esfuerzo, y ambas son invisibles para las ejecuciones funcionales de un solo usuario.

  • Este método identifica los efectos de acceder simultáneamente a los mismos registros de base de datos, módulos o código de aplicación.
  • Identifica y mide el nivel de interbloqueo, bloqueo, uso de código de un solo hilo y acceso restringido a recursos compartidos.

Una función puede ser completamente correcta para un usuario y aun así perder datos para el segundo usuario que llega un milisegundo después, razón por la cual esta técnica se encuentra junto a pruebas de rendimiento en lugar de dentro de las pruebas funcionales.

Cómo realizar pruebas de concurrencia

Las pruebas de concurrencia siguen una secuencia repetible. Los pasos a continuación van desde scoping a la resolución.

  • Paso 1) Identificar los flujos propensos a la concurrencia. Busque estados compartidos: inicios de sesión simultáneos, reservas de asientos o acciones, actualizaciones de saldo, trabajos por lotes que escriben en la misma tabla y cualquier componente de un solo hilo en la ruta.
  • Paso 2) Establezca un objetivo de concurrencia. Decida cuántos usuarios deben actuar al mismo tiempo, basándose en los picos de uso reales en lugar de un número redondo.
  • Paso 3) Diseñar los casos de prueba. Cada caso de prueba empareja el recurso compartido, las acciones en competencia y el estado final esperado; por ejemplo, dos sesiones que retiran fondos de una misma cuenta no deben tener éxito simultáneamente.
  • Paso 4) Cree el script y seleccione la herramienta. Se requiere un generador de carga que cree usuarios virtuales configurables; JMeter Es la opción de código abierto más común, y la configuración de sus grupos de subprocesos se corresponde directamente con los escenarios de concurrencia.
  • Paso 5) Ramp incrementalmente Aumentar los usuarios simultáneos por etapas en lugar de saltarping hacia el objetivo, de modo que se pueda ver el nivel en el que comienza la contención.
  • Paso 6) Monitorear y analizar. Observe conjuntamente los tiempos de espera de bloqueo, la dispersión del tiempo de respuesta, las tasas de error y el bloqueo de la base de datos: un defecto de concurrencia a menudo se manifiesta como una anomalía de tiempo antes de que se muestre como un error.
  • Paso 7) Resuelva y vuelva a ejecutar. Solucione el problema de sincronización, indexación o bloqueo, y luego repita la misma ejecución para confirmar que el comportamiento cambió en lugar de simplemente moverse.

Defectos comunes de concurrencia

Los defectos de concurrencia se dividen en un pequeño número de clases reconocibles, y nombrar correctamente la clase suele indicar directamente la solución.

Defecto Lo que sucede Síntoma típico
Condición de carrera El resultado depende de qué sesión haya terminado primero. Totales correctos en algunas carreras, incorrectos en otras.
Deadlock Dos sesiones, cada una mantiene un bloqueo que la otra necesita Las transacciones se quedan bloqueadas en lugar de devolver un error.
Actualización perdida Una segunda escritura sobrescribe la primera sin leerla. Un cambio guardado desaparece silenciosamente.
Corrupción de datos Una estructura compartida se escribe solo parcialmente. Registros en un estado donde no se pudo crear ninguna transacción válida
Hambre Una sesión nunca obtiene el recurso que espera. Una única ruta de usuario agota el tiempo de espera mientras el sistema parece estar en buen estado.

Debido a que estas fallas son intermitentes, cada ejecución necesita que se capturen registros y marcas de tiempo; de lo contrario, el defecto no se puede reportar de manera creíble a través de la proceso de gestión de defectos.

Ejemplo de prueba de concurrencia

Consideremos una tienda en línea que tiene la última unidad de un producto en stock. Dos compradores abren el artículo al mismo tiempo y ambos presionan Comprar.

  • Escenario: Dos sesiones leen stock = 1, ambas pasan la comprobación de disponibilidad y ambas escriben stock = 0.
  • Resultado Esperado: Se confirma un pedido, el otro recibe un mensaje de falta de existencias y el stock nunca llega a ser negativo.
  • Indicador de defecto: Ambas órdenes se confirman, o el stock se sitúa en -1, lo que demuestra que la comprobación de disponibilidad y el decremento no se ejecutan como un único paso atómico.
  • Variantes que vale la pena probar: Las mismas dos sesiones editando un registro de perfil, dos aprobaciones de la misma solicitud y un trabajo por lotes actualizando la tabla mientras un usuario guarda.

El mismo patrón se generaliza: encontrar un recurso, dos escritores y ninguna garantía de ordenación. Ejecutando el escenario durante prueba del sistema, antes de que se agregue la carga, mantiene el diagnóstico limpio.

Ventajas de las pruebas de concurrencia

  • Reduce relativamente el esfuerzo necesario para probar una aplicación al restringir el alcance de las interacciones concurrentes a unos pocos componentes ampliamente utilizados y bien probados.
  • La encapsulación permite analizar el comportamiento de una parte de un programa sin necesidad de revisar todo el código fuente.
  • Ayuda a mejorar la fiabilidad y la robustez de los programas concurrentes.
  • Esto permite detectar con antelación los límites de bloqueo y retención, de modo que las decisiones sobre la capacidad se basan en la contención medida en lugar de en estimaciones.

Desventajas de las pruebas de concurrencia

Los siguientes inconvenientes son los que suelen encontrar los evaluadores al realizar pruebas de concurrencia.

  • La aplicación debe probarse en múltiples plataformas.
  • Los escenarios de concurrencia requieren pruebas más exhaustivas que los secuenciales.
  • Las funciones no devuelven su resultado a quien las llama de inmediato; en cambio, el resultado puede entregarse más tarde a través de notificaciones, bloques, funciones de devolución de llamada o mecanismos similares, lo que dificulta las pruebas.
  • La información o el flujo del programa no se refleja en la pila de llamadas.
  • El número de rutas de ejecución en el sistema puede ser extremadamente grande, ya que los procesos en un sistema concurrente interactúan entre sí mientras se ejecutan.
  • Los programas concurrentes tienen una tasa de fallos mayor que los secuenciales.
  • Depurar programas concurrentes es difícil, porque al conectar un depurador se modifica el momento en que se produjo el fallo.

Preguntas Frecuentes

No. Prueba de carga Mide el comportamiento bajo el volumen esperado a lo largo del tiempo. Las pruebas de concurrencia se centran en el mismo instante, por lo que un defecto puede aparecer con solo dos usuarios si ambos acceden a un registro compartido.

La mitad multihilo de prueba de subprocesos Se superpone con ello. Las pruebas de subprocesos preguntan si una ruta de negocio sobrevive a la integración; las pruebas de concurrencia preguntan qué sucede con el acceso simultáneo una vez que esa ruta ya funciona.

Obtenga el número a partir del pico de uso observado, no de una cifra redonda. Comience con dos sesiones para demostrar que la lógica es atómica, luego aumente gradualmente hasta alcanzar el pico medido y un margen por encima de este.

Los modelos de aprendizaje automático clasifican los módulos según su historial de defectos y la complejidad de su estado compartido, lo que permite a los evaluadores identificar los flujos con mayor probabilidad de fallar debido a la superposición de patrones. Posteriormente, la agrupación de registros en ejecuciones repetidas aísla la intercalación que precedió a cada fallo.

Copiloto de GitHub Crea rápidamente scripts de usuario virtual, barreras y ayudantes de aserción. El evaluador aún define qué recurso se comparte y cuál es el estado final correcto, ya que las pruebas generadas rara vez fuerzan una superposición real.

El nivel de aislamiento, el tiempo de espera del bloqueo, el tamaño del grupo de conexiones y la indexación influyen en cómo se manifiesta la contención. Regístrelos en cada ejecución, ya que un resultado obtenido con un nivel de aislamiento no aporta información sobre otro.

Repita el mismo escenario muchas veces partiendo de datos limpios, conserve registros con marca de tiempo y reduzca el intervalo entre las dos acciones en competencia. Conectar un depurador suele ocultar el fallo al modificar la sincronización.

Sí, para la gestión de contención sensible al volumen. Las tablas pequeñas permiten que la base de datos mantenga todo en memoria y se bloquee brevemente, por lo que los bloqueos que aparecen en producción permanecen invisibles. Ajuste el número de filas y el tamaño de los índices lo más fielmente posible, según lo permita el entorno.

Resumir este post con: