test que pruebas por metodologia guiado ejemplo desarrollo comportamiento caracteristicas multithreading tdd

multithreading - que - tdd pdf



Usar TDD para expulsar el código de seguridad de subprocesos (6)

¿Cuál es una buena forma de aprovechar TDD para eliminar el código seguro para subprocesos? Por ejemplo, supongamos que tengo un método de fábrica que utiliza la inicialización diferida para crear solo una instancia de una clase, y luego la devuelve:

private TextLineEncoder textLineEncoder; ... public ProtocolEncoder getEncoder() throws Exception { if(textLineEncoder == null) textLineEncoder = new TextLineEncoder(); return textLineEncoder; }

Ahora, quiero escribir una prueba en buena forma TDD que me obligue a hacer este código seguro para subprocesos. Específicamente, cuando dos hilos llaman a este método al mismo tiempo, no quiero crear dos instancias y descartar uno. Esto se hace fácilmente, pero ¿cómo puedo escribir una prueba que me obligue a hacerlo?

Estoy preguntando esto en Java, pero la respuesta debería ser más ampliamente aplicable.


El Capítulo 12 de Concurrencia en Práctica de Java se llama "Prueba de Programas Simultáneos". Documenta las pruebas de seguridad y vitalidad, pero dice que este es un tema difícil. No estoy seguro de que este problema se pueda resolver con las herramientas de ese capítulo.


Es difícil, aunque posible, posiblemente más difícil de lo que vale. Las soluciones conocidas implican instrumentar el código bajo prueba. La discusión aquí, "Extreme Programming Challenge Catorce" vale la pena examinarla.


Justo fuera de mi cabeza, ¿podrías comparar las instancias devueltas para ver si realmente son la misma instancia o si son diferentes? Probablemente sea donde comenzaría con C #, me imagino que puedes hacer lo mismo en Java


Puede inyectar un "proveedor" (una fábrica realmente simple) que es responsable de solo esta línea:

textLineEncoder = new TextLineEncoder();

Entonces su prueba inyectaría una implementación realmente lenta del proveedor. De esa forma, los dos hilos en la prueba podrían colisionar más fácilmente. Podrías llegar hasta el primer hilo esperando en un semáforo que sería liberado por el segundo hilo. Entonces, el éxito de la prueba aseguraría que el hilo de espera caduque. Al darle al primer hilo una ventaja, puede asegurarse de que está esperando antes de que se publique el segundo hilo.


En el libro Código limpio, hay algunos consejos sobre cómo probar el código simultáneo. Un consejo que me ha ayudado a encontrar errores de concurrencia, se está ejecutando al mismo tiempo más pruebas que la CPU tiene núcleos.

En mi proyecto , ejecutar las pruebas lleva aproximadamente 2 segundos en mi máquina de cuatro núcleos. Cuando quiero probar las partes concurrentes (hay algunas pruebas para eso), mantengo apretado en IntelliJ IDEA la tecla rápida para ejecutar todas las pruebas, hasta que veo en la barra de estado que 20, 50 o 100 ejecuciones de prueba están en ejecución. Sigo en el Administrador de tareas de Windows la CPU y el uso de la memoria, para ver cuándo terminaron todas las ejecuciones de prueba (el uso de la memoria aumenta en 1-2 GB cuando se están ejecutando y luego vuelve a bajar lentamente).

Luego cierro uno por uno todos los diálogos de salida de ejecución de prueba y compruebo que no hubo fallas. A veces hay pruebas o pruebas fallidas que están en punto muerto, y luego las investigo hasta que encuentre el error y lo haya arreglado. Eso me ha ayudado a encontrar un par de desagradables errores de concurrencia. Lo más importante, cuando se enfrenta a una excepción / interbloqueo que no debería haber sucedido, siempre es asumir que el código está roto, e investigar la razón sin piedad y solucionarlo. No hay rayos cósmicos que provoquen que los programas se bloqueen aleatoriamente: los errores en el código hacen que los programas fallen.

También hay marcos como http://www.alphaworks.ibm.com/tech/contest que utilizan la manipulación de bytecode para obligar al código a realizar más cambios de subprocesos, lo que aumenta la probabilidad de que aparezcan errores de simultaneidad.


Cuando realicé una implementación que necesitaba ser segura para subprocesos recientemente, se me ocurrió la solución que proporcioné como respuesta a esta pregunta . Espero que ayude a pesar de que no hay pruebas allí. Espero que el enlace esté bien antes que duplicar la respuesta ...