2010-10-27 13 views
46

Hay un método fail() en la biblioteca JUnit4. Me gusta, pero experimenta una falta de método pass() que no está presente en la biblioteca. ¿Por que es esto entonces?JUnit4 fail() está aquí, pero ¿dónde está pass()?

Descubrí que puedo usar assertTrue(true) en su lugar, pero aún luce poco lógico.

@Test 
public void testSetterForeignWord(){ 
    try { 
    card.setForeignWord(""); 
    fail(); 
    } catch (IncorrectArgumentForSetter ex){ 
    } 

// assertTrue(true); 
} 
+7

Simplemente use declaración de devolución - en la mayoría de los casos que pasará como pase(). – topchef

+0

@topchef ese solo comentario golpeó el martillo en la cabeza, mientras todos los demás debaten qué es aceptable y cuál no. –

+0

Algunos sistemas de prueba (Perl Test :: Simple) cuentan las afirmaciones pasadas y fallidas. Sin embargo, Junit cuenta el número de _test methods_ que pasan y fallan. Por lo tanto, Junit no tiene el mismo uso para un método de 'pase'. –

Respuesta

51

Mientras la prueba no produce una excepción, que pasa, a menos que su @Test anotación especifica una excepción esperada. Supongo que un pass() podría arrojar una excepción especial que JUnit siempre interpreta como pasar, con el fin de cortocircuitar la prueba, pero eso iría en contra del diseño habitual de las pruebas (es decir, asumir el éxito y solo fallar si falla una afirmación) y, si las personas Si tuviera la idea de que era preferible usar pass(), se ralentizaría significativamente un gran conjunto de pruebas de aprobación (debido a la sobrecarga de la creación de excepciones). Las pruebas fallidas no deberían ser la norma, por lo que no es un gran problema si tienen esa sobrecarga.

en cuenta que su ejemplo podría reescribirse así:

@Test(expected=IncorrectArgumentForSetter.class) 
public void testSetterForeignWord("") throws Exception { 
    card.setForeignWord(""); 
} 

Además, debe favorecer el uso de las excepciones de Java estándar. Su IncorrectArgumentForSetter probablemente sea IllegalArgumentException.

+4

El método fail() y los métodos assertX() realmente solo lanzan un AssertionError, que hace que el método de prueba salga imprudentemente. Es por eso que un retorno exitoso indica éxito ... –

+0

-1 - El método pass() no está haciendo nada: es una prueba para dejar de fumar inmediatamente sin excepciones. Eso sería efectivamente equivalente a la declaración de devolución en la mayoría de los casos (excepto excepciones esperadas, tiempos de espera, etc.). – topchef

+1

@grigory: Tiene razón en que un método 'pass()' no podría simplemente no hacer nada, para que no sea posible que una prueba falle después de llamarla. Entonces eliminé esa oración. – ColinD

2

No es necesario el método de pase porque cuando no se arroja AssertionFailedException del código de prueba, se pasa el caso de prueba de la unidad.

El método fail() en realidad arroja una AssertionFailedException para fallar el testCase si el control llega a ese punto.

+0

Creo que en realidad es un junit.framework.AssertionFailedError. – Kyle

+0

¿Qué pasa con los casos de errores. decir iam obteniendo elemento no visible excepción de webdriver. Debería atrapar la excepción y regresar. – sasikumar

50

Llamada return declaración cada vez que finalice o supere su prueba.

+1

+1 debe haber sido la respuesta correcta (en la mayoría de los casos con excepción de los tiempos de espera esperados, etc.) – topchef

3

Creo que esta pregunta necesita una respuesta actualizada, ya que la mayoría de las respuestas aquí están bastante desfasadas.

primer lugar a la pregunta de la OP:

Creo que es muy bien aceptado que la introducción del concepto "excepetion espera" en JUnit fue un mal movimiento, ya que la excepción podría ser levantado en cualquier lugar, y pasará la prueba. Funciona si lanzas (y afirmas) excepciones muy específicas del dominio, pero solo lanzo ese tipo de excepciones cuando estoy trabajando en un código que debe ser absolutamente inmaculado, - APIS simplemente lanzará las excepciones incorporadas como IllegalArgumentException o IllegalStateException. Si dos llamadas su creación podría arrojar potentitalmente estas excepciones, entonces la anotación @ExpectedException pondrá su prueba en barra verde, incluso si es la línea incorrecta que arroja la excepción.

Para esta situación que he escrito una clase que estoy seguro que muchos otros han escrito aquí, que es un método assertThrows:

public class Exceptions { 
    private Exceptions(){} 

    public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){ 
     try{ 
      actionThatShouldThrow.run(); 
      fail("expected action to throw " + expectedException.getSimpleName() + " but it did not."); 
     } 
     catch(Exception e){ 
      if (! expectedException.isInstance(e)) { 
       throw e; 
      } 
     } 
    } 
} 

este método simplemente devuelve si se produce la excepción, que le permite hacer otras afirmaciones/verificación en su prueba.

con sintaxis java 8 su prueba se ve muy bien.A continuación se muestra una de las pruebas más sencillas en nuestro modelo que utiliza el método:

@Test 
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() { 
    //setup 
    AxisRange range = new AxisRange(0,100); 

    //act 
    Runnable act =() -> range.setLowerBound(200); 

    //assert 
    assertThrows(IllegalArgumentException.class, act); 
} 

estas pruebas son un poco torcidas debido a que el "acto" paso en realidad no realiza ninguna acción, pero creo que el significado es todavía bastante claro.

También hay una pequeña biblioteca pequeña en maven llamada catch-exception que usa la sintaxis de estilo mockito para verificar que se lanzan las excepciones. Se ve bonito, pero no soy fanático de los proxies dinámicos. Dicho esto, hay sintaxis es tan hábil que sigue siendo tentadora:

// given: an empty list 
List myList = new ArrayList(); 

// when: we try to get the first element of the list 
// then: catch the exception if any is thrown 
catchException(myList).get(1); 

// then: we expect an IndexOutOfBoundsException 
assert caughtException() instanceof IndexOutOfBoundsException; 

Por último, por la situación que me encontré al llegar a este hilo, hay una manera de ignorar pruebas si se cumple alguna conidition.

En este momento estoy trabajando para obtener algunos archivos DLL llamados a través de una biblioteca nativa java-cargando-biblioteca llamada JNA, pero nuestro servidor de compilación está en ubuntu. Me gusta tratar de impulsar este tipo de desarrollo con pruebas de JUnit, aunque están lejos de ser "unidades" en este momento. Lo que quiero hacer es ejecutar la prueba si estoy en una máquina local, pero ignorar la prueba si estamos en Ubuntu. JUnit 4 tiene una disposición de este, llamado Assume:

@Test 
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException { 
    //this line will cause the test to be branded as "ignored" when "isCircleCI" 
    //(the machine running ubuntu is running this test) is true. 
    Assume.assumeFalse(BootstrappingUtilities.isCircleCI()); 
    //an ignored test will typically result in some qualifier being put on the results, 
    //but will also not typically prevent a green-ton most platforms. 

    //setup 
    URL url = DLLTestFixture.class.getResource("USERDLL.dll"); 
    String path = url.toURI().getPath(); 
    path = path.substring(0, path.lastIndexOf("/")); 

    //act 
    NativeLibrary.addSearchPath("USERDLL", path); 
    Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class); 

    //assert 
    assertThat(dll).isNotNull(); 
} 
1

creo que esta pregunta es el resultado de un pequeño malentendido del proceso de ejecución de la prueba. En JUnit (y otras herramientas de prueba) los resultados se cuentan por método, no por llamada afirmativa. No hay un contador, que realice un seguimiento de cuántos pases/fallas assertX se ejecutó.

JUnit ejecuta cada método de prueba por separado. Si el método retorna exitosamente, entonces la prueba se registra como "aprobada". Si se produce una excepción, la prueba se registró como "fallida". En este último caso, son posibles dos subcajas: 1) una excepción de afirmación JUnit, 2) cualquier otro tipo de excepciones. El estado será "fallido" en el primer caso, y "error" en el segundo caso.

En la clase Assert, muchos métodos de taquigrafía están disponibles para arrojar excepciones de afirmación. En otras palabras, Assert es una capa de abstracción sobre las excepciones de JUnit.

Por ejemplo, este es el código fuente de assertEquals en GitHub:

/** 
* Asserts that two Strings are equal. 
*/ 
static public void assertEquals(String message, String expected, String actual) { 
    if (expected == null && actual == null) { 
     return; 
    } 
    if (expected != null && expected.equals(actual)) { 
     return; 
    } 
    String cleanMessage = message == null ? "" : message; 
    throw new ComparisonFailure(cleanMessage, expected, actual); 
} 

Como se puede ver, en caso de igualdad no pasa nada, de lo contrario se lanzará una excepion.

Así:

assertEqual("Oh!", "Some string", "Another string!"); 

simplemente emite una excepción ComparisonFailure, que será atrapado por JUnit, y

assertEqual("Oh?", "Same string", "Same string"); 

no hace nada.

En resumen, algo como pass() no tendría ningún sentido, porque no hizo nada.

0

Estaba buscando el método pass para JUnit también, por lo que podría cortocircuitar algunas pruebas que no eran aplicables en algunos escenarios (hay pruebas de integración, en lugar de pruebas de unidades puras). Tan mal que no está allí.

Afortunadamente, hay una manera de tener una prueba condicional ignorado, que en realidad se adapta aún mejor en mi caso usando assumeTrue método:

Assume.assumeTrue (isTestApplicable);

Aquí la prueba se ejecutará solo si isTestApplicable es verdadero, de lo contrario la prueba se ignorará.