12

Como el software se vuelve más y más concurrente, ¿cómo maneja la prueba el comportamiento del núcleo del tipo con las pruebas de su unidad (no el comportamiento paralelo, solo el comportamiento del núcleo)?Prueba de unidad de software concurrente: ¿qué haces?

En los viejos tiempos, tenías un tipo, lo llamabas, y revisabas qué devolvía y/o qué otras cosas llamaba.

Hoy en día, llamas a un método y el trabajo real se programa para ejecutarse en el siguiente hilo disponible; no sabes cuándo realmente comenzará y llama a las otras cosas, y lo que es más, esas otras cosas también pueden ser concurrentes.

¿Cómo lidiar con esto? ¿Extrae/inyecta el programador simultáneo (por ejemplo, abstrae la Biblioteca paralela de tareas y proporciona un falso/simulacro en las pruebas unitarias)?

¿Qué recursos ha encontrado que lo ayudaron?


Editar

He editado la cuestión a destacar probar el comportamiento normal del tipo (ignorando cualquier mecanismo paralelo se utiliza para tomar ventaja de varios núcleos, por ejemplo, el TPL)


Respuesta

3

El campo de Pruebas unitarias para condiciones de carrera y puntos muertos es relativamente nuevo y carece de buenas herramientas.

sé de dos de estas herramientas, tanto en las fases alfa/beta tempranas:

Otra opción es tratar de escribir una "prueba de estrés" que causaría condiciones de deadlocks/race a la superficie, crear instancias/hilos multinivel y ejecutarlos uno al lado del otro. La desventaja de este enfoque es que si la prueba falla, sería muy difícil reproducirla. Sugiero usar registros tanto en el código de prueba como de producción para que pueda entender lo que sucedió.

+0

Gracias por los enlaces +1 - Estoy seguro de que serán útiles para cualquiera que lea esta pregunta. He editado mi pregunta porque realmente quería preguntar más sobre el comportamiento normal del tipo en lugar del comportamiento simultáneo. –

0

Las pruebas unitarias realmente no deben probar la simultaneidad/comportamiento asincrónico, debe usar simulaciones allí y verificar que los simulacros reciban la entrada esperada.

Para las pruebas de integración, llamo explícitamente a la tarea en segundo plano, luego verifico las expectativas después de eso.

En pepino se ve así:

When I press "Register" 
And the email sending script is run 
Then I should have an email 
+0

Buen punto - No estaba claro en mi pregunta que me estaba refiriendo a probar el comportamiento central y el comportamiento no paralelo. He editado la pregunta. –

1

Una técnica que he encontrado útil es para ejecutar las pruebas dentro de una herramienta que detecta las condiciones de carrera como inspector paralelo Intel. La prueba se ejecuta mucho más despacio de lo normal, porque las dependencias de tiempo tienen que verificarse, pero una sola ejecución puede encontrar errores que de lo contrario requerirían millones de ejecuciones ordinarias repetidas.

He encontrado esto muy útil al convertir sistemas existentes para el paralelismo de grano fino a través de multi-core.

5

Descargo de responsabilidad: Trabajo para Corensic, una pequeña empresa emergente en Seattle.Tenemos una herramienta llamada Jinx que está diseñada para detectar errores de concurrencia en su código. Es gratis por ahora mientras estamos en Beta, por lo que es posible que desee comprobarlo. (http://www.corensic.com/)

En pocas palabras, Jinx es un hipervisor muy delgado que, cuando se activa, se desliza entre el procesador y el sistema operativo. Entonces, Jinx toma medidas de ejecución de forma inteligente y ejecuta simulaciones de varios tiempos de hilo para buscar errores. Cuando descubrimos un momento específico del hilo que hará que ocurra un error, hacemos que el tiempo sea "real" en su máquina (por ejemplo, si está usando Visual Studio, el depurador se detendrá en ese punto). Luego señalamos el área en su código donde el error fue causado. No hay falsos positivos con Jinx. Cuando detecta un error, definitivamente es un error.

Jinx funciona en Linux y Windows, y en código nativo y administrado. Es independiente del lenguaje y la plataforma de aplicación y puede trabajar con todas sus herramientas existentes.

Si lo comprueba, envíenos comentarios sobre lo que funciona y no funciona. Hemos estado ejecutando Jinx en algunos grandes proyectos de código abierto y ya estamos viendo situaciones en las que Jinx puede encontrar errores 50-100 veces más rápido que simplemente el código de prueba de estrés.

+0

Esto se ve realmente interesante. Los problemas de simultaneidad pueden tardar días o semanas, incluso meses, y un mecanismo como este para detectarlos analíticamente puede ser muy valioso. – Cobusve

0

Dado que su TPL tendrá su propia prueba de unidad independiente, no necesita verificarlo.

Dado que escribo dos pruebas para cada módulo:
1) Una sola prueba de unidad roscada que utiliza alguna variable de entorno o # define a su vez de la TPL para que pueda probar mi módulo para la corrección funcional.
2) Una prueba de esfuerzo que ejecuta el módulo en su modo de despliegue con rosca. Esta prueba intenta encontrar problemas de concurrencia y debe usar muchos datos aleatorios.

La segunda prueba a menudo incluye muchos módulos, por lo que probablemente sea más una prueba de integración/sistema.

4

Recomiendo recoger una copia de Growing Object Oriented Software by Freeman and Pryce. Los últimos dos capítulos son muy esclarecedores y abordan este tema específico. También introduce cierta terminología que ayuda a precisar la notación para la discusión.

Para resumir .... Su idea principal es dividir la funcionalidad y aspectos concurrentes/sincronización.

  • Primera prueba de manejo de la parte funcional en un solo hilo síncrona como un objeto normal.
  • Una vez que tiene la parte funcional inmovilizada. Puede pasar al aspecto concurrente. Para hacer eso, tendría que pensar y proponer "invariables observables w.r.t concurrencia" para su objeto, p. el recuento debe ser igual a las veces que se llama el método. Una vez que haya identificado las invariantes, puede escribir pruebas de estrés que ejecuten varios hilos et.all para intentar romper sus invariantes. Las pruebas de estrés afirman tus invariantes.
  • Finalmente como defensa adicional, ejecute herramientas o análisis estático para encontrar errores.

Para objetos pasivos, es decir, código que se llamaría desde clientes en diferentes subprocesos: la prueba debe imitar a los clientes iniciando sus propios subprocesos. Luego, deberá elegir entre un método de escucha de notificación o muestreo/encuesta para sincronizar sus pruebas con el SUT.

  • Usted podría bloque hasta que reciba una notificación esperada
  • encuesta ciertos efectos secundarios observables con un tiempo de espera razonable.