Agrupación de pruebas JUnit

¿Hay alguna forma de agrupar las pruebas en JUnit, para poder ejecutar solo algunos grupos?

¿O es posible anotar algunas pruebas y luego deshabilitarlas globalmente?

Estoy usando JUnit 4 , no puedo usar TestNG.

editar: @RunWith y @SuiteClasses funciona muy bien. ¿Pero es posible anotar así solo algunas pruebas en la clase de prueba? ¿O tengo que anotar toda la clase de prueba?

¿Desea agrupar las pruebas dentro de una clase de prueba o desea agrupar las clases de prueba? Voy a suponer lo último.

Depende de cómo está ejecutando sus pruebas. Si Maven lo ejecuta, es posible especificar exactamente qué pruebas desea incluir. Consulte la documentación de Maven surefire para esto.

En términos más generales, sin embargo, lo que hago es que tengo un árbol de suites de prueba. Un conjunto de pruebas en JUnit 4 se ve algo así como:

  @RunWith(Suite.class) @SuiteClasses(SomeUnitTest1.class, SomeUnitTest2.class) public class UnitTestsSuite { } 

Entonces, tal vez tengo un FunctionTestsSuite y un UnitTestsSuite, y luego un AllTestsSuite que incluye los otros dos. Si los ejecuta en Eclipse obtiene una muy buena vista jerárquica.

El problema con este enfoque es que es un poco tedioso si quieres dividir las pruebas en más de una forma diferente. Pero aún es posible (por ejemplo, puede tener un conjunto de suites que segmentan en función del módulo, y luego otro corte en el tipo de prueba).

JUnit 4.8 admite la agrupación:

 public interface SlowTests {} public interface IntegrationTests extends SlowTests {} public interface PerformanceTests extends SlowTests {} 

Y entonces…

 public class AccountTest { @Test @Category(IntegrationTests.class) public void thisTestWillTakeSomeTime() { ... } @Test @Category(IntegrationTests.class) public void thisTestWillTakeEvenLonger() { ... } @Test public void thisOneIsRealFast() { ... } } 

Y por último,

 @RunWith(Categories.class) @ExcludeCategory(SlowTests.class) @SuiteClasses( { AccountTest.class, ClientTest.class }) public class UnitTestSuite {} 

Tomado de aquí: http://weblogs.java.net/blog/johnsmart/archive/2010/04/25/grouping-tests-using-junit-categories-0

Además, Arquillian admite la agrupación en sí: https://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/Categories.java

Para manejar la desactivación global de ellos, JUnit (4.5+) tiene dos formas: Una es usar el nuevo método assumeThat. Si coloca eso en @BeforeClass (o @Before) de una clase de prueba, y si la condición falla, ignorará la prueba. En la condición puede poner una propiedad del sistema u otra cosa que se pueda activar o desactivar globalmente.

La otra alternativa es crear un corredor personalizado que comprenda la propiedad global y delegue en el corredor apropiado. Este enfoque es mucho más frágil (ya que los corredores internos JUnit4 son inestables y se pueden cambiar de versión a versión), pero tiene la ventaja de poder heredarse en una jerarquía de clases y anularse en una subclase. También es la única forma realista de hacerlo si tiene que admitir clases heredadas de JUnit38.

Aquí hay un código para hacer el Runner personalizado. En cuanto a lo que getAppropriateRunnerForClass podría hacer, la forma en que lo implementé fue tener una anotación separada que le diga al corredor personalizado con qué ejecutar. La única alternativa era una copia muy frágil del código JUnit.

 private class CustomRunner implements Runner private Runner runner; public CustomRunner(Class< ?> klass, RunnerBuilder builder) throws Throwable { if (!isRunCustomTests()) { runner = new IgnoredClassRunner(klass); } else { runner = getAppropriateRunnerForClass(klass, builder); } public Description getDescription() { return runner.getDescription(); } public void run(RunNotifier notifier) { runner.run(notifier); } } 

EDITAR: la etiqueta @RunWith solo funciona para una clase completa. Una forma de evitar esa limitación es mover los métodos de prueba a una clase interna estática y anotar eso. De esta forma, tiene la ventaja de la anotación con la organización de la clase. Pero, hacer eso no ayudará con ninguna etiqueta @Before o @BeforeClass, tendrá que recrear aquellas en la clase interna. Puede llamar al método de la clase externa, pero debería tener su propio método como un gancho.

Pruebe JUnit Test Groups . De la documentación:

 @TestGroup("integration") public class MyIntegrationTest { @ClassRule public static TestGroupRule rule = new TestGroupRule(); ... } 
  • Ejecute un grupo de prueba simple: -Dtestgroup = integración
  • Ejecute múltiples grupos de prueba: -Dtestgroup = group1, group2
  • Ejecute todos los grupos de prueba: -Dtestgroup = all

Puede crear objetos Suite de prueba que contienen grupos de pruebas. Alternativamente, su IDE (como Eclipse) puede tener soporte para ejecutar todas las pruebas contenidas en un paquete determinado.

Puede usar Test Suite ( http://qaautomated.blogspot.in/2016/09/junit-test-suits-and-test-execution.html ) o puede Junit Categories ( http://qaautomated.blogspot.in/ 2016/09 / junit-categories.html ) para agrupar sus casos de prueba de manera efectiva.

En JUnit 5 puede declarar @Tag para las pruebas de filtrado, ya sea a nivel de clase o método; análogo a grupos de prueba en TestNG o Categorías en JUnit 4

Desde el javadoc :

las tags se usan para filtrar qué pruebas se ejecutan para un plan de prueba determinado. Por ejemplo, un equipo de desarrollo puede etiquetar las pruebas con valores como “rápido”, “lento”, “ci-servidor”, etc. y luego proporcionar una lista de tags que se utilizarán para el plan de prueba actual, potencialmente dependiente de la stream ambiente.

Por ejemplo, puede declarar una clase de prueba con un @Tag "slow" que se heredará para todos los métodos y anularla para algunos métodos, si es necesario:

 import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @Tag("slow") public class FooTest{ // @Test void loadManyThings(){ ... } @Test void loadManyManyThings(){ ... } @Test @Tag("fast") void loadFewThings(){ ... } } 

Puede aplicar la misma lógica para otras clases de prueba.
De esta forma, las clases de prueba (y también los métodos) pertenecen a una etiqueta específica.

Como una buena práctica, en lugar de copiar y pegar @Tag("fast") y @Tag("slow") todas las clases de prueba, puede crear anotaciones compuestas personalizadas.
Por ejemplo :

 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.Tag; @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Tag("slow") public @interface Fast { } 

y usarlo como:

 @Test @Slow void slowProcessing(){ ... } 

Para habilitar o deshabilitar la prueba marcada con una etiqueta específica durante la ejecución del texto, puede confiar en la documentación de maven-surefire-plugin :

Para incluir tags o expresiones de tags, use groups .

Para excluir tags o expresiones de tags, use excludedGroups .

Simplemente configure en su pom.xml el complemento de acuerdo con sus requisitos (ejemplo del documento):

    ...  org.apache.maven.plugins maven-surefire-plugin 2.22.0  acceptance | !feature-a integration, regression     

Para información, la documentación del objective de la prueba no se actualiza.