Confusión de JUnit: use ‘extends TestCase’ o ‘@Test’?

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.

Si entendí correctamente, existen dos enfoques principales para crear y ejecutar una prueba JUnit:

Enfoque A (estilo JUnit 3): cree una clase que extienda TestCase, e inicie métodos de prueba con la palabra test . Cuando se ejecuta 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 (estilo JUnit 4): crea una clase “normal” y @Test una anotación @Test al método. Tenga en cuenta que NO tiene que 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, por ejemplo, esta pregunta stackoverflow :

Ahora, mi pregunta (s):

  1. ¿Cuál es el enfoque preferido o cuándo usarías 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 prueban las excepciones cuando se utiliza el enfoque A?
  3. Al usar el enfoque A, puede agrupar varias clases de prueba en un conjunto de pruebas como este:

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

    Pero esto no se puede usar 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: he agregado las versiones JUnit a ambos enfoques

La distinción es bastante fácil:

  • la extensión de TestCase es la forma en que se escribieron las pruebas unitarias en JUnit 3 (por supuesto, todavía es compatible con JUnit 4)
  • usar la anotación @Test es la forma introducida por JUnit 4

En general, 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:

  • La @Test es más explícita y es más fácil de admitir en las herramientas (por ejemplo, es fácil buscar todas las pruebas de esta manera)
  • Múltiples métodos pueden ser anotados con @Before / @BeforeClass y @BeforeClass @Before / @BeforeClass @AfterClass proporcionando más flexibilidad
  • Soporte para anotaciones @Rule en cosas como ExpectedException
  • Soporte para la anotación @Ignored
  • Soporte para corredores de prueba alternativos usando @RunWith

Para probar las excepciones esperadas en un JUnit 3 TestCase , tendrías que hacer que el texto sea 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 } } 

Tengo una preferencia por JUnit 4 (enfoque de anotación) porque me resulta más flexible.

Si desea construir un conjunto de pruebas en JUnit 4, debe crear una clase que agrupe todas las pruebas como esta:

 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 */ } 

Hay una parte no respondida de 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.class) y luego usa 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 el sentido de que las anotaciones no le permiten crear dinámicamente la lista de clases, y trabajar en torno a ese problema se pone un poco desagradable. 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.

Deberías usar JUnit 4. Es mejor.

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

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

[Advertencia] La jerarquía de clases heredada JUnit 3.8 está en desuso

En general, siempre debe intentar usar la última versión estable de un marco cuando comience algo nuevo.

  1. El enfoque “preferido” sería utilizar anotaciones que se han introducido desde Junit 4. Facilitan mucho las cosas (consulte su segunda pregunta)

  2. Puedes usar un simple bloque try / catch para eso:

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