¿Cómo ejecutar métodos de prueba en orden específico en JUnit4?


Quiero ejecutar métodos de prueba anotados por @Test en orden específico.

Por ejemplo:

public class MyTest {
    @Test public void test1(){}
    @Test public void test2(){}
}

Quiero asegurarme de ejecutar test1() antes de test2() cada vez que ejecute MyTest, pero no pude encontrar una anotación como @Test(order=xx).

Creo que es una característica bastante importante para JUnit, si el autor de JUnit no quiere la característica de orden , ¿por qué?

Author: ROMANIA_engineer, 2010-09-12

16 answers

Creo que es una característica bastante importante para JUnit, si el autor de JUnit no quiere la función de pedido, ¿por qué?

No estoy seguro de que haya una manera limpia de hacer esto con JUnit, que yo sepa JUnit asume que todas las pruebas se pueden realizar en un orden arbitrario. De las preguntas frecuentes:

¿Cómo uso un accesorio de prueba?

(...) El orden de las invocaciones del método de prueba no está garantizado , por lo que testOneItemCollection () podría ejecutarse antes testEmptyCollection(). (...)

¿por Qué es así? Bueno, creo que hacer que las pruebas dependan del orden es una práctica que los autores no quieren promover. Las pruebas deben ser independientes, no deben estar acopladas y violar esto hará que las cosas sean más difíciles de mantener, romperá la capacidad de ejecutar pruebas individualmente (obviamente), etc.

Dicho esto, si realmente quieres ir en esta dirección, considera usar TestNG ya que admite la ejecución de pruebas métodos en cualquier orden arbitrario de forma nativa (y cosas como especificar que los métodos dependen de grupos de métodos). Cedric Beust explica cómo hacer esto en orden de ejecución de las pruebas en testng.

 207
Author: Pascal Thivent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:29

Si se deshace de su instancia existente de Junit y descarga JUnit 4.11 o superior en la ruta de compilación, el siguiente código ejecutará los métodos de prueba en el orden de sus nombres, ordenados en orden ascendente:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {

    @Test
    public void testAcreate() {
        System.out.println("first");
    }
    @Test
    public void testBupdate() {
        System.out.println("second");
    }
    @Test
    public void testCdelete() {
        System.out.println("third");
    }
}
 60
Author: Aniket Kulkarni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-19 01:06:04

Si el pedido es importante, debe realizarlo usted mismo.

@Test public void test1() { ... }
@Test public void test2() { test1(); ... }

En particular, debe enumerar algunas o todas las permutaciones de orden posibles para probar, si es necesario.

Por ejemplo,

void test1(); 
void test2(); 
void test3(); 


@Test
public void testOrder1() { test1(); test3(); }

@Test(expected = Exception.class)
public void testOrder2() { test2(); test3(); test1(); }

@Test(expected = NullPointerException.class)
public void testOrder3() { test3(); test1(); test2(); }

O, una prueba completa de todas las permutaciones:

@Test
public void testAllOrders() {
    for (Object[] sample: permute(1, 2, 3)) {
        for (Object index: sample) {
            switch (((Integer) index).intValue()) {
                case 1: test1(); break; 
                case 2: test2(); break; 
                case 3: test3(); break; 
            }
        }
    }
}

Aquí, permute() es una función simple que itera todas las permuaciones posibles en una Colección de matriz.

 49
Author: Xiè Jìléi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-16 08:30:22

La migración a TestNG parece la mejor manera, pero no veo una solución clara aquí para JUnit. Aquí está la mayoría solución legible / formato que encontré para JUnit:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {
    @Test
    void stage1_prepareAndTest(){};

    @Test
    void stage2_checkSomething(){};

    @Test
    void stage2_checkSomethingElse(){};

    @Test
    void stage3_thisDependsOnStage2(){};

    @Test
    void callTimeDoesntMatter(){}
}

Esto asegura que los métodos stage2 se llamen después de los de stage1 y antes de los de stage3.

 32
Author: joro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-11 14:20:09

Es uno de los principales problemas que enfrenté cuando trabajé en Junit y se me ocurrió la siguiente solución que funciona bien para mí:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        List<FrameworkMethod> copy = new ArrayList<FrameworkMethod>(list);
        Collections.sort(copy, new Comparator<FrameworkMethod>() {

            @Override
            public int compare(FrameworkMethod f1, FrameworkMethod f2) {
                Order o1 = f1.getAnnotation(Order.class);
                Order o2 = f2.getAnnotation(Order.class);

                if (o1 == null || o2 == null) {
                    return -1;
                }

                return o1.order() - o2.order();
            }
        });
        return copy;
    }
}

También cree una interfaz como la siguiente:

 @Retention(RetentionPolicy.RUNTIME)


@Target({ ElementType.METHOD})

public @interface Order {
public int order();
}

Ahora supongamos que tiene clase A donde ha escrito varios casos de prueba como los siguientes:

(@runWith=OrderRunner.class)
Class A{
@Test
@Order(order = 1)

void method(){

//do something

}

}

Así que la ejecución comenzará desde el método llamado "method()". ¡Gracias!

 14
Author: Aman Goel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-27 04:21:47

El (todavía inédito) el cambio https://github.com/junit-team/junit/pull/386 introduce un @SortMethodsWith. https://github.com/junit-team/junit/pull/293 al menos hizo el orden predecible sin eso (en Java 7 puede ser bastante aleatorio).

 8
Author: Jesse Glick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-14 20:43:04

Mira un informe JUnit. JUnit ya está organizado por paquete. Cada paquete tiene (o puede tener) clases TestSuite, cada una de las cuales a su vez ejecuta varios casos de prueba. Cada TestCase puede tener múltiples métodos de prueba de la forma public void test*(), cada uno de los cuales se convertirá en una instancia de la clase TestCase a la que pertenecen. Cada método de prueba (instancia TestCase) tiene un nombre y un criterio de aprobado/no aprobado.

Lo que mi gestión requiere es el concepto de elementos individuales TestStep , cada uno de los cuales informa sus propios criterios de aprobación/reprobación. El fracaso de cualquier etapa de prueba no impedirá la ejecución de las etapas de prueba posteriores.

En el pasado, los desarrolladores de test en mi posición organizaban las clases TestCase en paquetes que correspondían a la(s) parte (s) del producto bajo prueba, creaban una clase TestCase para cada prueba, e hacían de cada método de prueba un "paso" separado en la prueba, completo con sus propios criterios de aprobación/fallo en la salida JUnit. Cada caso de prueba es una "prueba" independiente, pero el los métodos individuales, o "pasos" de prueba dentro del caso de prueba, deben ocurrir en un orden específico.

Los métodos TestCase eran los pasos del TestCase, y los diseñadores de pruebas obtuvieron un criterio de aprobado/no aprobado por separado por paso de prueba. Ahora los pasos de la prueba están mezclados, y las pruebas (por supuesto) fallan.

Por ejemplo:

Class testStateChanges extends TestCase

public void testCreateObjectPlacesTheObjectInStateA()
public void testTransitionToStateBAndValidateStateB()
public void testTransitionToStateCAndValidateStateC()
public void testTryToDeleteObjectinStateCAndValidateObjectStillExists()
public void testTransitionToStateAAndValidateStateA()
public void testDeleteObjectInStateAAndObjectDoesNotExist()
public void cleanupIfAnythingWentWrong()

Cada método de ensayo afirma e informa de sus propios criterios de aprobación/reprobación. Colapsar esto en "un gran método de prueba" por el bien de ordenar pierde el pase / suspenso criterios granularidad de cada "paso" en el informe de resumen de JUnit. ...y eso molesta a mis gerentes. Actualmente están exigiendo otra alternativa.

¿Puede alguien explicar cómo un JUnit con orden de método de prueba codificado soportaría criterios de aprobación/reprobación separados de cada paso de prueba secuencial, como se ejemplificó anteriormente y requerido por mi administración?

Independientemente de la documentación, veo esto como una regresión seria en el marco de JUnit que está haciendo la vida difícil para muchos desarrolladores de pruebas.

 6
Author: Anonymous Developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-24 19:00:29

Lo que desea es perfectamente razonable cuando los casos de prueba se ejecutan como una suite.

Desafortunadamente no hay tiempo para dar una solución completa en este momento, pero echa un vistazo a la clase:

org.junit.runners.Suite

Que le permite llamar casos de prueba (desde cualquier clase de prueba) en un orden específico.

Estos pueden ser utilizados para crear pruebas funcionales, de integración o del sistema.

Esto deja sus pruebas unitarias como están sin un orden específico (como se recomienda), ya sea que las ejecute de esa manera o no, y luego reutilizar las pruebas como parte de un panorama más amplio.

Reutilizamos/heredamos el mismo código para pruebas de unidad, integración y sistema, a veces basadas en datos, a veces basadas en confirmaciones y a veces ejecutadas como una suite.

 3
Author: CharlieS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-27 00:58:21

No estoy seguro de estar de acuerdo, Si quiero probar 'File Upload' y luego probar 'Data Inserted by File Upload' ¿por qué no querría que estos fueran independientes unos de otros? Creo que es perfectamente razonable poder ejecutarlos por separado en lugar de tener ambos en un caso de prueba de Goliat.

 3
Author: Mattk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-19 12:11:44

Vea mi solución aquí: "Junit and java 7."

En este artículo describo cómo ejecutar pruebas junit en orden - "al igual que en su código fuente". Las pruebas se ejecutarán, en el orden en que sus métodos de prueba aparezcan en el archivo de clase.

Http://intellijava.blogspot.com/2012/05/junit-and-java-7.html

Pero como dijo Pascal Thivent, esta no es una buena práctica.

 2
Author: kornero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-05 10:12:22

He leído algunas respuestas y estoy de acuerdo en que no es la mejor práctica, pero la forma más fácil de ordenar sus pruebas - y la forma en que JUnit ejecuta las pruebas por defecto es por nombre alfabético ascendente.

Así que simplemente nombra tus pruebas en el orden alfabético que quieras. También tenga en cuenta que el nombre de la prueba debe comenzar con la palabra prueba. Solo ten cuidado con los números

Test12 se ejecutará antes de test2

Entonces:

TestA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond

 1
Author: pstorli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-10 20:01:20

Por favor, echa un vistazo a este: https://github.com/TransparentMarket/junit . Ejecuta la prueba en el orden en que se especifica (definido dentro del archivo de clase compilado). También cuenta con una suite AllTests para ejecutar pruebas definidas por subpaquete primero. Usando la implementación de AllTests se puede extender la solución también filtrando propiedades (solíamos usar anotaciones @ Fast, pero aún no se habían publicado).

 0
Author: Martin Kersten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-30 14:20:01

Aquí hay una extensión de JUnit que puede producir el comportamiento deseado: https://github.com/aafuks/aaf-junit

Sé que esto va en contra de los autores de la filosofía JUnit, pero cuando se utiliza JUnit en entornos que no son pruebas unitarias estrictas (como se practica en Java) esto puede ser muy útil.

 0
Author: shlomi33,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-25 15:28:02

Terminé aquí pensando que mis pruebas no se ejecutaban en orden, pero la verdad es que el lío estaba en mis trabajos asincrónicos. Al trabajar con concurrencia, también debe realizar comprobaciones de concurrencia entre las pruebas. En mi caso, los trabajos y las pruebas comparten un semáforo, por lo que las siguientes pruebas se cuelgan hasta que el trabajo en ejecución libere el bloqueo.

Sé que esto no está completamente relacionado con esta pregunta, pero tal vez podría ayudar a apuntar al problema correcto

 0
Author: McCoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-01 15:44:06

Puedes usar uno de estos códigos:

@FixMethodOrder(MethodSorters.JVM)OR `@FixMethodOrder(MethodSorters.DEFAULT)` OR `@FixMethodOrder(MethodSorters.NAME_ASCENDING)` before your test class like this:


@FixMethodOrder(MethodSorters.NAME_ASCENDING)


public class BookTest { ...}
 0
Author: Arezoo Bagherzadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-04 11:41:37

JUnit actualmente permite que los métodos de prueba ejecuten el orden usando anotaciones de clase:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FixMethodOrder(MethodSorters.JVM)
@FixMethodOrder(MethodSorters.DEFAULT)

Para establecer el orden de los métodos, puede nombrarlos como:

A_testWorkUnit_WithCertainState_ShouldDoSomething b_testWorkUnit_WithCertainState_ShouldDoSomething c_testWorkUnit_WithCertainState_ShouldDoSomething

Puedes encontrar ejemplos aquí.

 0
Author: Zon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-22 09:15:34