Junit4: El método @Parameters se ejecuta antes de la inicialización de @ClassRule. ¿Podría ser al revés?

Creado en 2 may. 2013  ·  9Comentarios  ·  Fuente: junit-team/junit4

Tengo el siguiente problema (usando _junit 4.11_):

    <strong i="6">@ClassRule</strong>
    public static TemporaryFolder tmp = new TemporaryFolder();
    ...
    <strong i="7">@Parameters</strong>
    public static Collection<Object[]> data() throws Exception {
        return java.util.Arrays.asList(new Object[][] {
            {0, tmp.getRoot().getPath()}
        });
    }

Esto da como resultado initializationError

java.lang.IllegalStateException: the temporary folder has not yet been created
    at org.junit.rules.TemporaryFolder.getRoot(TemporaryFolder.java:127)

Parece que el método _@Parameters_ se ejecuta antes de la fase de inicialización de _ClassRule_, lo que complica un poco los escenarios como el anterior.

Comentario más útil

Solución actual:

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

Funciona pero necesita esa limpieza manual...

Todos 9 comentarios

Solución actual:

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

Funciona pero necesita esa limpieza manual...

+1

Pensándolo un poco, supongo que una buena manera de implementar esto sería introducir una anotación para esto:

<strong i="7">@Parameters</strong>
<strong i="8">@AfterClassRules</strong>
public Object[][] generateParameters() {
    // do stuff
}

Esto garantizaría que ambas variantes aún se puedan usar y que el código existente no se rompa. Si este diseño es aceptable para los mantenedores, comenzaría a trabajar en una solicitud de extracción para esto.

Estoy escribiendo un comentario adicional porque no estoy seguro de si una actualización de un comentario activa una notificación.

¿El diseño propuesto en mi comentario anterior sería aceptable para los mantenedores? Si es así, comenzaría a trabajar en una solicitud de extracción.

Aquí hay un problema de arquitectura bastante difícil: JUnit promete a los corredores como Eclipse que puede enumerar cuántas pruebas hay antes de ejecutar cualquiera de las pruebas, pero también quiere minimizar los recursos consumidos durante esta fase de planificación. Entonces, realmente queremos saber cuántos parámetros habrá antes de, por ejemplo, crear carpetas temporales o hacer las cosas aún más drásticas que aparecen en ClassRules, como iniciar servidores.

Quizás mi respuesta favorita sería habilitar algo como @DataPoints en Theories: puede haber campos estáticos o métodos estáticos con el prefijo @ParameterSet , que se unen para formar el conjunto completo de parámetros. Así que tu ejemplo sería:

@ClassRule public static TemporaryFolder tmp = new TemporaryFolder();
@ParameterSet public static Object[] first = new Object[] { 0 };
@ParameterSet objeto estático público [] segundo () {
devolver nuevo Objeto[] { tmp.getRoot().getPath(); }
}

El punto aquí es que podríamos contar el método como "segundo" sin ejecutarlo realmente.

¿Qué piensas?

Hm, supongo que ahora que lo pienso, el problema es más un olor en mi código de prueba. Me estoy conectando a un servicio remoto y ejecutando pruebas dependiendo de cómo esté configurado. En su lugar, probablemente debería arreglar la configuración esperada en mi prueba.

Aquí está la prueba en la que originalmente enfrenté el problema: CryptoAppExecReturnCodeTest.java

@dsaff Pensaré un poco en tu sugerencia. La impresión inicial es: dividir pares en matrices separadas requiere un cuidado especial de las posiciones de los elementos (un poco propenso a errores). Así que puedo terminar llenando _primero_ con algunas cosas ficticias (simplemente manteniendo la cantidad de elementos); y en _segundo_, me gustaría mantener los elementos del par uno al lado del otro:

{ 0, tmp...getPath() },
{ 1, ... }

¿Hay algo más que los corredores necesiten además del número de pruebas? (Por ejemplo, ¿tal vez nombres de prueba?)

@javornikolov , me acabo de dar cuenta de que leí mal su publicación inicial, por lo que mi respuesta probablemente fue confusa. Estaba leyendo su prueba como dos instancias diferentes de una clase de prueba que se construye con un parámetro; ahora que lo leí de nuevo, en realidad es una instanciación de una clase de prueba que se construye con dos parámetros. Para ajustar mi propuesta entonces, el código sugerido sería:

<strong i="7">@ClassRule</strong> public static TemporaryFolder tmp = new TemporaryFolder();
<strong i="8">@ParameterSet</strong> public static Object[] only() {
return new Object[] { 0, tmp.getRoot().getPath(); }
}

Espero que eso aclare mi intención; perdón por mi confusión inicial.

(pasando por algunos errores antiguos)

¿Quizás deberíamos cambiar el nombre de este problema a "Habilitar algo como @DataPoints en teorías"?

(pasando por algunos errores antiguos)

¿Quizás deberíamos cambiar el nombre de este problema a "Habilitar algo como @DataPoints en teorías"?

Diría que el problema es tener la capacidad de usar Rule recursos en la lista de parámetros para pruebas parametrizadas. El enfoque con @ParameterSet propuesto por @dsaff me parece viable (suponiendo que las evaluaciones ocurran en una secuencia tal que se resuelva el problema original).
Pero si "Algo como @DataPoints" es lo suficientemente claro y no hay riesgo de divergir en alguna dirección que no cubra el escenario original: está bien para mí.
La razón por la que prefiero las pruebas parametrizadas sobre las teorías (que usan puntos de datos) es que los resultados de estas últimas no se informan de forma independiente para cada conjunto de parámetros, y esa primera falla aborta la ejecución de los parámetros posteriores.

¿Fue útil esta página
0 / 5 - 0 calificaciones