¿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.
¿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.
¿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.

