Resumen Ejecutivo: Cuando los errores de aserción se tiran en los hilos, la prueba de la unidad no muere. Esto tiene sentido, ya que no se debe permitir que un subproceso bloquee otro subproceso. La pregunta es ¿cómo puedo 1) hacer que toda la prueba falle cuando el primero de los subprocesos auxiliares falla o 2) recorrer y determinar el estado de cada subproceso después de que se hayan completado (ver código a continuación). Una forma de hacer esto último es tener una variable de estado por subproceso, por ejemplo, "boolean [] estados" y tener "estados [i] == falso" significa que el subproceso falló (esto podría ampliarse para capturar más información). Sin embargo, eso no es lo que quiero: quiero que falle como cualquier otra prueba unitaria cuando se lanzan los errores de afirmación. ¿Esto es posible? ¿Es deseable?¿Cómo realizo una prueba unitaria usando hilos?
Me aburrí y decidí engendrar un montón de hilos en mi prueba de unidad y luego hacer que llamaran a un método de servicio, por el gusto de hacerlo. El código es aproximadamente como:
Thread[] threads = new Thread[MAX_THREADS];
for(int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
private final int ID = threadIdSequenceNumber++;
public void run() {
try {
resultRefs[ID] = runTest(Integer.toString(ID)); // returns an object
}
catch(Throwable t) {
// this code is EVIL - it catches even
// Errors - don't copy it - more on this below
final String message = "error testing thread with id => "
+ ID;
logger.debug(message, t);
throw new IllegalStateException(message, t);
// need to wrap throwable in a
// run time exception so it will compile
}
}
});
}
Después de esto, vamos a recorrer la matriz de hilos e iniciar cada uno. Después de eso, esperaremos a que todos terminen. Finalmente, realizaremos algunos controles en las referencias de resultados.
for(Thread thread : threads)
thread.start();
logger.debug("waiting for threads to finish ...");
boolean done = false;
while(!done) {
done = true;
for(Thread thread : threads)
if(thread.isAlive())
done = false;
}
for(int i = 0; i < resultRefs.length; i++) {
assertTrue("you've got the world messed, dawg!",
myCondition(resultRefs[i]));
Aquí está el problema. ¿Has notado ese desagradable bloqueo try-catch-throwable? Acabo de agregar eso como un hack temporal para poder ver lo que estaba pasando. En runTest (String) se hacen algunas afirmaciones, por ejemplo, assertNotNull (null), pero dado que está en un hilo diferente, ¡¡no hace que la prueba de unidad falle !!!!
Mi conjetura es que tendremos que recorrer alguna manera sobre la matriz hilos, verificar el estado de cada uno, y de forma manual causar un error de aserción si el hilo terminado de una manera desagradable. ¿Cuál es el nombre del método que proporciona esta información (el seguimiento de la pila del hilo muerto)?
buen punto. Yo era principalmente interesante al escribir la prueba por curiosidad. Veo que no es una cosa trivial de hacer. :( – les2
Es interesante que la programación esté empujando hacia más multihilo y más pruebas unitarias al mismo tiempo. Los dos parecen objetivos incompatibles, a menos que avancemos hacia lenguajes funcionales puros donde los problemas de simultaneidad disminuyen ... –