2010-04-14 20 views
124

He encontrado el uso correcto (o al menos la documentación) de JUnit muy confuso. Esta pregunta sirve como una referencia futura y como una pregunta real.Confusión de JUnit: use 'extends TestCase' o '@Test'?

Si he entendido bien, hay dos enfoques principales para crear y ejecutar una prueba JUnit:

Enfoque A (JUnit 3-estilo): crear una clase que se extiende TestCase, y empezar a métodos de prueba con la palabra test. Al ejecutar la clase como una Prueba JUnit (en Eclipse), todos los métodos que comienzan con la palabra test se ejecutan automáticamente.

import junit.framework.TestCase; 

public class DummyTestA extends TestCase { 

    public void testSum() { 
     int a = 5; 
     int b = 10; 
     int result = a + b; 
     assertEquals(15, result); 
    } 
} 

Enfoque B (JUnit 4-estilo): crear una clase 'normal' y anteponer una anotación de @Test al método. Tenga en cuenta que NO es necesario iniciar el método con la palabra test.

import org.junit.*; 
import static org.junit.Assert.*; 

public class DummyTestB { 

    @Test 
    public void Sum() { 
     int a = 5; 
     int b = 10; 
     int result = a + b; 
     assertEquals(15, result); 
    } 
} 

Mezclar los dos parece no ser una buena idea, ver p. this stackoverflow question:

Ahora, mis preguntas (s):

  1. ¿Cuál es el enfoque preferido, o cuándo se usa uno en lugar de otro?
  2. El enfoque B permite probar excepciones al extender la anotación @Test como en @Test(expected = ArithmeticException.class). ¿Pero cómo se verifican las excepciones cuando se utiliza el enfoque A?
  3. Al utilizar el enfoque A, puede agrupar una serie de clases de prueba en un conjunto de pruebas de la siguiente manera:

    TestSuite suite = new TestSuite("All tests");
    suite.addTestSuite(DummyTestA.class);
    suite.addTestSuite(DummyTestAbis.class);

    Pero esto no puede ser utilizado con el enfoque B (ya que cada clase de prueba debe subclasificar TestCase). ¿Cuál es la forma correcta de agrupar las pruebas para el enfoque B?

Editar: ¡Tengo las versiones JUnit a ambos enfoques

Respuesta

96

La distinción es bastante fácil:

  • extendiéndose TestCase es el las pruebas de unidad de ruta se escribieron en JUnit 3 (por supuesto todavía se admite en JUnit 4)
  • utilizando la anotación @Test es la forma introducida por JUnit 4

Generalmente debe elegir la ruta de anotación, a menos que sea necesaria la compatibilidad con JUnit 3 (y/o una versión de Java anterior a Java 5). La nueva forma tiene varias ventajas:

Para probar las excepciones que se esperan de un JUnit 3 TestCase que tendría que hacer el texto más explícito.

public void testMyException() { 
    try { 
    objectUnderTest.myMethod(EVIL_ARGUMENT); 
    fail("myMethod did not throw an Exception!"); 
    } catch (MyException e) { 
    // ok! 
    // check for properties of exception here, if desired 
    } 
} 
+0

Respuesta útil y completa, pero no entiendo completamente "verificar mensaje de excepción". Verificar una cadena codificada va a ser una pesadilla de mantenimiento. Debes haber querido decir "verificar las propiedades de tu tipo de excepción específico". – thSoft

+3

@thSoft: no es frecuente que se use, pero ocasionalmente quiero asegurarme de que el método de excepción menciona el campo ofensivo, por ejemplo. Entonces, un simple 'assertTrue (e.getMessage(). Contains (" foo "))' podría ser útil. –

+1

Incluso en JUnit4, este es un idioma importante cuando tiene que verificar el mensaje o alguna otra propiedad de la excepción (como la causa). El método 'expected' solo comprueba el tipo. – Yishai

21

tengo una preferencia por JUnit 4 (Modo anotación) porque me resulta más flexible.

Si usted quiere construir banco de pruebas de JUnit 4, usted tiene que crear una clase que agrupa todas las pruebas de este tipo:

import org.junit.runner.RunWith; 
import org.junit.runners.Suite; 
import org.junit.runners.Suite.SuiteClasses; 


@RunWith(Suite.class) 
@SuiteClasses({ 
    Test1.class, 
    Test2.class, 
    Test3.class, 
    Test4.class 
})public class TestSuite 
{ 
/* empty class */ 
} 
1
  1. El enfoque de "preferido" sería el uso de anotaciones que se han introducido desde Junit 4. Ellos hacen un montón de cosas más fácil (ver su segunda pregunta)

  2. Se puede utilizar una sencilla bloque try/catch para ello:


public void testForException() { 
    try { 
     Integer.parseInt("just a string"); 
     fail("Exception should have been thrown"); 
    } catch (final Exception e) { 
     // expected 
    } 
} 
3

debe utilizar JUnit 4. es mejor.

Muchos frameworks han comenzado a depreciar el soporte de JUnit 3.8.

Esto es de la primavera documentación de referencia 3.0:

[Aviso] Legado JUnit 3.8 clase jerarquía está en desuso

En general, siempre se debe tratar de utilizar la última versión estable de un marco cuando comienzas algo nuevo.

14

Hay una parte no respondida a su pregunta, y esa es "¿Cuál es la forma correcta de agrupar las pruebas para el enfoque B?"

La respuesta oficial es que anota una clase con @RunWith (Suite.clase) y luego use la anotación @ Suite.SuiteClasses para listar las clases. Así es como lo hacen los desarrolladores de JUnit (enumerando todas las clases en una suite de forma manual). En muchos sentidos, este enfoque es una mejora, ya que es trivial e intuitivo agregar comportamientos before suite y after suite (simplemente agregue un método @BeforeClass y @AfterClass a la clase anotada con @RunWith, mucho mejor que la antigua TestFixture)

Sin embargo, tiene un paso atrás, en que las anotaciones no permiten crear dinámicamente la lista de clases, y trabajar alrededor de ese problema se pone un poco feo. Debe subclasificar la clase Suite y crear dinámicamente la matriz de clases en la subclase y pasarla al constructor de Suite, pero esta es una solución incompleta en la que otras subclases de Suite (como Categorías) no funcionan con ella y, esencialmente, no es compatible con la colección de clase de prueba dinámica.

+1

+1 para esto. Después de embarcarme en una tarea para escribir una solución dinámica para agregar Pruebas a una TestSuite, tuve que extender TestCase en cada una de mis Pruebas. Esto a su vez ha roto las pruebas de unidad de trabajo anteriores que utilizaban anotaciones JUnit4 para definir las excepciones esperadas. Mi búsqueda de una forma de rellenar dinámicamente un Test Suite me ha llevado a este hilo, y específicamente a su respuesta, que creo que es una de las pocas razones deseables para continuar con JUnit 3. – 8bitjunkie

Cuestiones relacionadas