java - example - no test found with test runner junit 4 eclipse
¿Puedo evitar ejecutar las pruebas Junit dos veces en eclipse al usar un TestSuite? (5)
¿Necesitas la suite en primer lugar? Dependiendo de cuándo haga clic para ejecutar todos (clase, paquete o src / test / java), se ejecutarán todas las pruebas subyacentes. Entonces, ¿cuál es el punto de tener una suite?
Necesito hacer una inicialización por suite (iniciando un servidor web). Funciona bien, excepto que cuando ejecuto todas las pruebas en mi proyecto en eclipse, mis pruebas se ejecutan dos veces. Mi suite de pruebas se parece un poco a esto:
@RunWith(Suite.class)
@Suite.SuiteClasses({
SubtestOne.class,
SubtestTwo.class
})
public class TestSuite
{
[...]
}
public class SubtestOne
{
@Test public void testOne() { [...] }
}
public class SubtestTwo
{
@Test public void testTwo() { [...] }
}
Cuando ejecuto todas las pruebas en el proyecto en eclipse, esto hace que el complemento junit ejecute las pruebas dos veces de la siguiente manera:
- SubtestOne
- Subprueba dos
- Banco de pruebas
- SubtestOne
- Subprueba dos
¿Es posible hacer que "ejecutar todas las pruebas en el proyecto" no ejecute las subpruebas dos veces? Quiero que mis subpruebas solo se ejecuten como parte de la suite.
Hay una solución, es un poco difícil, pero puede resolver fácilmente su problema: cree una clase de suite e incluya todas las clases de su suite en ella. Luego puedes usar esta clase de suite para ejecutar todas tus pruebas.
@RunWith(Suite.class)
@Suite.SuiteClasses({
AXXSuite.class,
BXXSuite.class,
CXXSuite.class
})
public class AllSuites {
}
Me doy cuenta de que esto se hizo hace más de 5 años, pero como un buen número de personas votaron la pregunta, pensé que todavía estaría de acuerdo con una solución. Salta hasta el final si solo quieres la solución; lee el texto completo si también quieres entenderlo ;-)
En primer lugar, es posible garantizar que una clase de prueba JUnit en particular solo se ejecute dentro de un conjunto de pruebas. Además, es irrelevante si desea ejecutar ese conjunto de pruebas dentro de Eclipse (como se solicita aquí) o cualquier otra herramienta o entorno; Esto es realmente un problema de JUnit puro en su mayor parte.
Antes de esbozar la solución, podría ser una buena idea revisar cuál es el problema exacto aquí. Todas las pruebas de JUnit deben ser visibles e instantáneas para que sean recogidas por el marco de JUnit y sus diversos corredores. Esto también se aplica a las suites de prueba y las pruebas individuales que forman parte de una suite de prueba. Como consecuencia, si JUnit recoge el conjunto de pruebas, también lo hará con las pruebas individuales, y todas las pruebas se ejecutarán dos veces, una individualmente y una vez como parte de la suite.
Por lo tanto, el truco, si lo desea, es evitar que JUnit retome las pruebas individuales y, al mismo tiempo, pueda instanciarlas y ejecutarlas como parte de la suite.
Una cosa que viene a la mente es hacer que las clases de prueba sean clases internas estáticas anidadas dentro del conjunto de pruebas. Sin embargo, las clases anidadas aún deben ser públicas (de lo contrario, tampoco se pueden ejecutar en la suite), y si son clases públicas, también se seleccionarán de forma individual, a pesar de estar anidadas dentro de la clase pública de la suite. Sin embargo, JUnit no intentará ejecutar clases de prueba que no se consideren visibles. Por lo tanto, anidar las clases de prueba dentro de una clase no pública probablemente sería suficiente para ocultarlas, pero no podemos hacer que la clase de suite no sea pública porque entonces JUnit no la ejecutaría. Sin embargo, lo que podemos hacer es anidar las pruebas individuales dentro de otra clase no pública que está anidada dentro del conjunto de pruebas, lo que nos lleva a la solución de este enigma:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({AllTests.InSuiteOnly.Test1.class, AllTests.InSuiteOnly.Test2.class})
public class AllTests
{
static class InSuiteOnly
{
public static class Test1
{
@Test
public void test1()
{
//...
}
}
public static class Test2
{
@Test
public void test2()
{
//...
}
}
}
}
Es probable que mucha gente se oponga a todas las pruebas que necesitan estar dentro de un solo archivo fuente ahora. ¿Qué sucede si deseo mantener clases de prueba JUnit separadas que no se ejecutan por sí mismas pero que se ejecutan dentro del conjunto de pruebas? Una solución simple es hacer que las clases de prueba individuales sean abstractas (público / no público no importa) para que JUnit no las ejecute, y dentro de la serie de pruebas simplemente usamos subclases concretas de las clases de prueba abstractas originales:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({AllTests.InSuiteOnly.SuiteTest1.class, AllTests.InSuiteOnly.SuiteTest2.class})
public class AllTests
{
static class InSuiteOnly
{
public static class SuiteTest1 extends Test1 {}
public static class SuiteTest2 extends Test2 {}
}
}
abstract class Test1
{
@Test
public void test1()
{
//...
}
}
abstract class Test2
{
@Test
public void test2()
{
//...
}
}
Este esquema funciona con Maven, Eclipse y todos los demás entornos que aprovechan directamente los corredores de JUnit o implementan sus propios corredores que siguen de cerca el comportamiento y la semántica originales de JUnit.
No, la clase de prueba siempre se iniciará directamente y luego a través del "enlace" en la suite. Esto es lo esperado.
Una solución alternativa podría ser establecer en la configuración de ejecución para ejecutar solo las pruebas del paquete que contiene sus suites. Abra la configuración de ejecución y seleccione Run all tests in the selected project, package or source folder
luego haga clic en Search...
y seleccione el paquete.
Tengo una idea para ti. En realidad, no desea ejecutar estos casos de prueba como casos de prueba independientes. Puedes hacer lo siguiente.
Marque los casos de prueba con la anotación @RunWith(DoNothingRunner.class)
Implemente DoNothingRunner como sigue:
public class DoNothingRunner extends Runner {
public Description getDescription() {
return "do nothing";
}
public void run(RunNotifier notifier) {
// indeed do nothing
}
}
No lo he intentado personalmente, pero espero que esto funcione.