vez unitarias unit una tipos test son software sistema realizan que pruebas los las ist integrados funcionales ejemplo desarrolladores componentes aquellas unit-testing concurrency junit

unit testing - unitarias - ¿Cómo se ejecuta la prueba de unidad de concurrencia?



tipos de pruebas de software (13)

Lamentablemente, no creo que pueda probar definitivamente que su código es seguro para subprocesos mediante el uso de pruebas en tiempo de ejecución. Puede lanzar tantos hilos como desee contra él, y puede que no lo apruebe dependiendo de la programación.

Tal vez debería ver algunas herramientas de análisis estático, como PMD , que pueden determinar cómo está usando la sincronización e identificar problemas de uso.

¿Cómo usar junit para ejecutar la prueba de concurrencia?

Digamos que tengo una clase

public class MessageBoard { public synchronized void postMessage(String message) { .... } public void updateMessage(Long id, String message) { .... } }

Quiero probar el acceso múltiple a este postMessage al mismo tiempo. Algún consejo sobre esto? Deseo ejecutar este tipo de prueba de concurrencia contra todas mis funciones de configuración (o cualquier método que implique la operación de creación / actualización / eliminación).


TestNG tiene soporte para pruebas de concurrencia en Java. Este artículo describe cómo se puede usar y hay documentos en el sitio de prueba.

No estoy seguro de si puede hacer la misma prueba al mismo tiempo, aunque


Solo puede probar la presencia de errores simultáneos, no su ausencia .

Sin embargo, puede escribir un corredor de prueba especializado que engendra varios hilos concurrentes y luego llama a sus métodos anotados @Test.


El mejor enfoque aquí es usar pruebas del sistema para enviar su código con solicitudes para ver si se cae. Luego use la prueba unitaria para verificar la corrección lógica. La forma en que abordaría esto es crear un proxy para la llamada asincrónica y hacer que se realice sincrónicamente bajo prueba.

Sin embargo, si desea hacer esto en un nivel que no sea una instalación completa y un entorno completo, puede hacer esto en junio creando su objeto en un hilo separado, luego cree muchos hilos que disparen las solicitudes a su objeto y bloqueen el hilo principal hasta que se complete. Este enfoque puede hacer que las pruebas fallen intermitentemente si no lo hace bien.


En .NET, hay herramientas como TypeMock Racer o Microsoft CHESS que están diseñadas específicamente para la concurrencia de pruebas unitarias. Estas herramientas no solo encuentran errores de subprocesamiento múltiple, como interbloqueos, sino que también le proporcionan el conjunto de intercalaciones de subprocesos que reproducen los errores.

Me imagino que hay algo similar para el mundo de Java.


En su ejemplo, el método postMessage () está sincronizado , por lo que no verá ningún efecto de concurrencia desde una sola máquina virtual, pero es posible que pueda evaluar el rendimiento de la versión sincronizada.

Tendrá que ejecutar varias copias del programa de prueba al mismo tiempo en diferentes máquinas virtuales. Puedes usar

Si no puede lograr que su marco de prueba lo haga, puede iniciar algunas VMs usted mismo. El proceso de creación de cosas es un dolor con los caminos y otras cosas, pero aquí está el boceto general:

Process running[] = new Process[5]; for (int i = 0; i < 5; i++) { ProcessBuilder b = new ProcessBuilder("java -cp " + getCP() + " MyTestRunner"); running[i] = b.start(); } for(int i = 0; i < 5; i++) { running[i].waitFor(); }

Usualmente hago algo como esto para las pruebas sencillas y simples, como han publicado otros, las pruebas no son una prueba de corrección, pero generalmente sacuden errores en la práctica. Ayuda probar durante mucho tiempo bajo una variedad de condiciones diferentes: a veces los errores de concurrencia demoran un tiempo en manifestarse en una prueba.

public void testMesageBoard() { final MessageBoard b = new MessageBoard(); int n = 5; Thread T[] = new Thread[n]; for (int i = 0; i < n; i++) { T[i] = new Thread(new Runnable() { public void run() { for (int j = 0; j < maxIterations; j++) { Thread.sleep( random.nextInt(50) ); b.postMessage(generateMessage(j)); verifyContent(j); // put some assertions here } } }); PerfTimer.start(); for (Thread t : T) { t.start(); } for (Thread t : T) { t.join(); } PerfTimer.stop(); log("took: " + PerfTimer.elapsed()); } }**strong text**


Probar errores de concurrencia es imposible; no solo tiene que validar pares de entrada / salida, sino que debe validar el estado en situaciones que pueden ocurrir o no durante sus pruebas. Desafortunadamente JUnit no está equipado para hacer esto.


Recomendaría usar MultithreadedTC - Escrito por el mismo maestro de concurrencia Bill Pugh (y Nat Ayewah ). Cita de su descripción :

MultithreadedTC es un marco para probar aplicaciones concurrentes. Cuenta con un metrónomo que se utiliza para proporcionar un control preciso sobre la secuencia de actividades en múltiples hilos.

Este marco le permite probar determinísticamente cada entrelazado de hilos en pruebas separadas


Intente mirar ActiveTestSuite que se envía con JUnit. Puede lanzar simultáneamente múltiples pruebas JUnit:

public static Test suite() { TestSuite suite = new ActiveTestSuite(); suite.addTestSuite(PostMessageTest.class); suite.addTestSuite(PostMessageTest.class); suite.addTestSuite(PostMessageTest.class); suite.addTestSuite(PostMessageTest.class); suite.addTestSuite(PostMessageTest.class); return suite; }

Lo anterior ejecutará la misma clase de prueba JUnit 5 veces en paralelo. Si desea una variación en sus pruebas paralelas, simplemente cree una clase diferente.


Correr concurrentemente puede conducir a resultados inesperados. Por ejemplo, acabo de descubrir que, mientras mi Test Suite con 200 pruebas pasa cuando se ejecuta una por una, falla para la ejecución simultánea, lo cavé y no era un problema de seguridad de hilos, sino una prueba que dependía de otra, que es algo malo y podría resolver el problema

Mycila trabaja en JUnit ConcurrentJunitRunner y ConcurrentSuite es muy interesante. El artículo parece un poco desactualizado en comparación con el último lanzamiento de GA, en mis ejemplos mostraré el uso actualizado.

Anotar una clase de prueba como la siguiente hará que se ejecuten métodos de prueba al mismo tiempo, con un nivel de concurrencia de 6:

import com.mycila.junit.concurrent.ConcurrentJunitRunner; import com.mycila.junit.concurrent.Concurrency; @RunWith(ConcurrentJunitRunner.class) @Concurrency(6) public final class ATest { ...

También puede ejecutar todas las clases de prueba al mismo tiempo:

import com.mycila.junit.concurrent.ConcurrentSuiteRunner; @RunWith(ConcurrentSuiteRunner.class) @Suite.SuiteClasses({ATest.class, ATest2.class, ATest3.class}) public class MySuite { }

La dependencia de Maven es:

<dependency> <groupId>com.mycila</groupId> <artifactId>mycila-junit</artifactId> <version>1.4.ga</version> </dependency>

Actualmente estoy investigando cómo ejecutar métodos varias veces y al mismo tiempo con este paquete. Ya puede ser posible, si alguien tiene un ejemplo, hágamelo saber, debajo de mi solución hecha en casa.

@Test public final void runConcurrentMethod() throws InterruptedException { ExecutorService exec = Executors.newFixedThreadPool(16); for (int i = 0; i < 10000; i++) { exec.execute(new Runnable() { @Override public void run() { concurrentMethod(); } }); } exec.shutdown(); exec.awaitTermination(50, TimeUnit.SECONDS); } private void concurrentMethod() { //do and assert something }

Como otros señalaron, es cierto que nunca se puede estar seguro de si se mostraría o no un error de concurrencia, pero con decenas de miles, o cientos de miles de ejecuciones con una concurrencia de, digamos 16, las estadísticas están de su lado.


También puedes probar HavaRunner . Ejecuta pruebas en paralelo de forma predeterminada.


Puede usar la biblioteca tempus-fugit para ejecutar métodos de prueba en paralelo y varias veces para simular un entorno de tipo prueba de carga. Aunque un comentario anterior señala que el método de publicación está sincrónico y, por lo tanto, protegido, pueden estar involucrados miembros o métodos asociados que, por sí mismos, no están protegidos, por lo que es posible que una prueba de tipo carga / remojo pueda detectarlos. Te sugiero que configures una prueba parecida a la de un grano grueso / extremo a extremo para darte la mejor oportunidad de atrapar cualquier agujero en el asa.

Ver la sección de integración JUnit de la documentación .

Por cierto, soy un desarrollador en dicho proyecto :)


Usted puede verificar IMUnit . Es compatible con JUnit.