tutorial pruebas español java unit-testing junit

java - pruebas - Obtener el nombre de la prueba actualmente en ejecución en JUnit 4



junit4 @parameters (13)

En JUnit 3, podría obtener el nombre de la prueba actualmente en ejecución de la siguiente manera:

public class MyTest extends TestCase { public void testSomething() { System.out.println("Current test is " + getName()); ... } }

que imprimiría "prueba actual es algo de prueba".

¿Hay alguna forma simple o sencilla de hacer esto en JUnit 4?

Antecedentes: Obviamente, no quiero simplemente imprimir el nombre de la prueba. Quiero cargar datos específicos de la prueba que se almacenan en un recurso con el mismo nombre que la prueba. Ya sabes, la convención sobre la configuración y todo eso.


JUnit 4.9.x y superior

Desde JUnit 4.9, la clase TestWatchman ha quedado en desuso a favor de la clase TestWatcher , que tiene invocación:

@Rule public TestRule watcher = new TestWatcher() { protected void starting(Description description) { System.out.println("Starting test: " + description.getMethodName()); } };

JUnit 4.7.x - 4.8.x

El siguiente enfoque imprimirá los nombres de los métodos para todas las pruebas en una clase:

@Rule public MethodRule watchman = new TestWatchman() { public void starting(FrameworkMethod method) { System.out.println("Starting test: " + method.getName()); } };


Basándome en el comentario anterior y considerando más a fondo, creé una extensión de TestWather que puede usar en sus métodos de prueba JUnit con esto:

public class ImportUtilsTest { private static final Logger LOGGER = Logger.getLogger(ImportUtilsTest.class); @Rule public TestWatcher testWatcher = new JUnitHelper(LOGGER); @Test public test1(){ ... } }

La clase de ayudante de prueba es la siguiente:

public class JUnitHelper extends TestWatcher { private Logger LOGGER; public JUnitHelper(Logger LOGGER) { this.LOGGER = LOGGER; } @Override protected void starting(final Description description) { LOGGER.info("STARTED " + description.getMethodName()); } @Override protected void succeeded(Description description) { LOGGER.info("SUCCESSFUL " + description.getMethodName()); } @Override protected void failed(Throwable e, Description description) { LOGGER.error("FAILURE " + description.getMethodName()); } }

¡Disfrutar!


Considere el uso de SLF4J (Simple Logging Facade para Java) proporciona algunas mejoras ordenadas utilizando mensajes parametrizados. La combinación de SLF4J con las implementaciones de la regla JUnit 4 puede proporcionar técnicas de registro de clase de prueba más eficientes.

import org.junit.Rule; import org.junit.Test; import org.junit.rules.MethodRule; import org.junit.rules.TestWatchman; import org.junit.runners.model.FrameworkMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LoggingTest { @Rule public MethodRule watchman = new TestWatchman() { public void starting(FrameworkMethod method) { logger.info("{} being run...", method.getName()); } }; final Logger logger = LoggerFactory.getLogger(LoggingTest.class); @Test public void testA() { } @Test public void testB() { } }


En JUnit 5 hay TestInfo inyección TestInfo que simplifica los metadatos de prueba al proporcionar métodos de prueba. Por ejemplo:

@Test @DisplayName("This is my test") @Tag("It is my tag") void test1(TestInfo testInfo) { assertEquals("This is my test", testInfo.getDisplayName()); assertTrue(testInfo.getTags().contains("It is my tag")); }

Ver más: Guía de usuario JUnit 5 , TestInfo javadoc .


En JUnit 5, TestInfo actúa como un reemplazo directo de la regla TestName de JUnit 4.

De la documentación:

TestInfo se usa para inyectar información sobre la prueba o el contenedor actual en @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, @BeforeEach, @AfterEach, @BeforeAll y @AfterAll.

Para recuperar el nombre del método de la prueba ejecutada actual, tiene dos opciones: String TestInfo.getDisplayName() y Method TestInfo.getTestMethod() .

Para recuperar solo el nombre del método de prueba actual, TestInfo.getDisplayName() puede no ser suficiente, ya que el nombre de visualización predeterminado del método de prueba es methodName(TypeArg1, TypeArg2, ... TypeArg3) .
La duplicación de nombres de métodos en @DisplayName("..") no es una buena idea necesaria.

Como alternativa, puede usar TestInfo.getTestMethod() que devuelve un objeto Optional<Method> .
Si el método de recuperación se utiliza dentro de un método de prueba, ni siquiera necesita probar el valor envuelto Optional .

import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.Test; @Test void doThat(TestInfo testInfo) throws Exception { Assertions.assertEquals("doThat(TestInfo)",testInfo.getDisplayName()); Assertions.assertEquals("doThat",testInfo.getTestMethod().get().getName()); }


Intenta esto en su lugar:

public class MyTest { @Rule public TestName testName = new TestName(); @Rule public TestWatcher testWatcher = new TestWatcher() { @Override protected void starting(final Description description) { String methodName = description.getMethodName(); String className = description.getClassName(); className = className.substring(className.lastIndexOf(''.'') + 1); System.err.println("Starting JUnit-test: " + className + " " + methodName); } }; @Test public void testA() { assertEquals("testA", testName.getMethodName()); } @Test public void testB() { assertEquals("testB", testName.getMethodName()); } }

La salida se ve así:

Starting JUnit-test: MyTest testA Starting JUnit-test: MyTest testB

NOTA: ¡Esto NO funciona si su prueba es una subclase de TestCase ! La prueba se ejecuta pero el código @Rule nunca se ejecuta.


JUnit 4 no tiene ningún mecanismo listo para usar para que un caso de prueba obtenga su propio nombre (incluso durante la configuración y el desmontaje).


JUnit 4.7 agregó esta característica, parece que usa TestName-Rule . Parece que esto te dará el nombre del método:

import org.junit.Rule; public class NameRuleTest { @Rule public TestName name = new TestName(); @Test public void testA() { assertEquals("testA", name.getMethodName()); } @Test public void testB() { assertEquals("testB", name.getMethodName()); } }


Le sugiero que desacople el nombre del método de prueba de su conjunto de datos de prueba. Yo modelaría una clase DataLoaderFactory que carga / almacena en caché los conjuntos de datos de prueba de sus recursos, y luego, en su caso de prueba, invoca algún método de interfaz que devuelve un conjunto de datos de prueba para el caso de prueba. Si los datos de la prueba están vinculados al nombre del método de prueba, se supone que los datos de la prueba solo se pueden usar una vez, y en la mayoría de los casos, sugiero que se utilicen los mismos datos de prueba en varias pruebas para verificar diversos aspectos de la lógica de su negocio.


Puedes lograr esto usando Slf4j y TestWatcher

private static Logger _log = LoggerFactory.getLogger(SampleTest.class.getName()); @Rule public TestWatcher watchman = new TestWatcher() { @Override public void starting(final Description method) { _log.info("being run..." + method.getMethodName()); } };


Una forma complicada es crear su propio Runner subclasificando org.junit.runners.BlockJUnit4ClassRunner.

Entonces puedes hacer algo como esto:

public class NameAwareRunner extends BlockJUnit4ClassRunner { public NameAwareRunner(Class<?> aClass) throws InitializationError { super(aClass); } @Override protected Statement methodBlock(FrameworkMethod frameworkMethod) { System.err.println(frameworkMethod.getName()); return super.methodBlock(frameworkMethod); } }

Luego, para cada clase de prueba, deberá agregar una anotación @RunWith (NameAwareRunner.class). Alternativamente, puede poner esa anotación en una superclase de Prueba si no quiere recordarla cada vez. Esto, por supuesto, limita su selección de corredores, pero eso puede ser aceptable.

Además, puede tomar un poco de kung fu obtener el nombre de la prueba actual fuera del Runner y en su marco, pero al menos esto le da el nombre.


@ClassRule public static TestRule watchman = new TestWatcher() { @Override protected void starting( final Description description ) { String mN = description.getMethodName(); if ( mN == null ) { mN = "setUpBeforeClass.."; } final String s = StringTools.toString( "starting..JUnit-Test: %s.%s", description.getClassName(), mN ); System.err.println( s ); } };


String testName = null; StackTraceElement[] trace = Thread.currentThread().getStackTrace(); for (int i = trace.length - 1; i > 0; --i) { StackTraceElement ste = trace[i]; try { Class<?> cls = Class.forName(ste.getClassName()); Method method = cls.getDeclaredMethod(ste.getMethodName()); Test annotation = method.getAnnotation(Test.class); if (annotation != null) { testName = ste.getClassName() + "." + ste.getMethodName(); break; } } catch (ClassNotFoundException e) { } catch (NoSuchMethodException e) { } catch (SecurityException e) { } }