test studio run dependency aplicaciones aplicacion android android-studio junit logcat

studio - test aplicaciones android



Registrar mensajes en la prueba junit de android studio (2)

¿Hay alguna manera de imprimir mensajes Logcat (Log.i, Log.d) cuando se ejecuta una prueba JUnit (método) en Android Studio?

Puedo ver el mensaje System.out.print pero no hay impresiones de logcat.

En la configuración de ejecución (ventana de GUI de Android Studio) hay opciones de logcat para las pruebas en las pruebas de Android pero no para las pruebas de JUnit.

¿Es esto posible de alguna manera? Gracias por cualquier pista!


La salida de Logcat no se verá en pruebas unitarias porque Logcat es una función de Android: las pruebas JUnit solo pueden usar Java estándar, por lo tanto, las características de Android no funcionarán.

Lo que puede hacer en las pruebas unitarias es inyectar "dobles de prueba" en los componentes probados. Pero Log.x llamadas Log.x son estáticas, por lo que no puede anularlas (sin resolver, por ejemplo, PowerMock, que debe evitar a toda costa).

Por lo tanto, el primer paso será introducir una clase no estática que se comportará como un proxy para Log.x llamadas Log.x :

/** * This class is a non-static logger */ public class Logger { public void e(String tag, String message) { Log.e(tag, message); } public void w(String tag, String message) { Log.w(tag, message); } public void v(String tag, String message) { Log.v(tag, message); } public void d(String tag, String message) { Log.d(tag, message); } }

Utilice esta clase en cada lugar donde tenga llamadas Log.x ahora.

El segundo paso sería escribir una implementación de doble prueba de Logger que redirecciona al resultado estándar:

public class UnitTestLogger extends Logger{ @Override public void e(String tag, String message) { System.out.println("E " + tag + ": " + message); } // similar for other methods }

El último paso es inyectar UnitTestLogger lugar de Logger en pruebas unitarias:

@RunWith(MockitoJUnitRunner.class) public class SomeClassTest { private Logger mLogger = new UnitTestLogger(); private SomeClass SUT; @Before public void setup() throws Exception { SUT = new SomeClass(/* other dependencies here */ mLogger); } }

Si quiere ser rigurosamente estricto con los conceptos de OOP, puede extraer una interfaz común para Logger y UnitTestLogger .

Dicho esto, nunca encontré la necesidad de investigar llamadas Log.x en pruebas unitarias. Sospecho que tampoco lo necesitas. Puede ejecutar pruebas unitarias en modo de depuración y pasar el código línea por línea en el depurador, que es mucho más rápido que intentar investigar la salida del logcat ...

Consejo general:

Si el código que está probando contiene Log.x estáticas Log.x y las pruebas de su unidad no se bloquean, tiene un problema.

Supongo que todas las pruebas se están ejecutando con Robolectric , o tiene esta declaración en build.gradle: unitTests.returnDefaultValues = true .

Si ejecuta todas las pruebas con Robolectric , entonces es simplemente ineficaz, pero si todas las llamadas de Android devuelven los valores predeterminados, entonces la suite de prueba no es confiable. Le sugiero que solucione este problema antes de continuar porque le morderá en el futuro de una forma u otra.


Estaba buscando lo mismo y nunca encontré una respuesta directa. Sé que esta pregunta tiene más de un año, pero aún así, sería bueno tener una respuesta aquí para referencia futura.

La clase android.util.Log se registra directamente en Logcat y la implementación de android.util.Log no está disponible cuando se ejecutan las pruebas unitarias en la JVM local. Recibirá un error al intentar usar la clase Log en las pruebas de su unidad porque "el archivo android.jar utilizado para ejecutar las pruebas unitarias no contiene ningún código real (esas API solo las proporciona la imagen del sistema Android en un dispositivo) "
Consulte la documentación de Android en Pruebas unitarias

Entonces, si realmente quieres usar android.util.Log, deberás burlarlo localmente y utilizar System.out.print para imprimir en la consola. Para comenzar, agregue PowerMockito a su proyecto. Si está utilizando Gradle, puede agregar las siguientes dependencias:

testCompile ''junit:junit:4.12'' testCompile ''org.powermock:powermock:1.6.5'' testCompile ''org.powermock:powermock-module-junit4:1.6.5'' testCompile ''org.powermock:powermock-api-mockito:1.6.5''

Luego usé la respuesta de Steve aquí para descubrir cómo devolver un parámetro pasado a un objeto simulado usando Mockito.

El resultado fue algo así como:

import android.util.Log; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.mockito.Matchers.anyString; import static org.powermock.api.mockito.PowerMockito.when; @RunWith(PowerMockRunner.class) @PrepareForTest({Log.class}) public class SomeUnitTest { @Test public void testSomething() { System.out.println("Running test"); PowerMockito.mockStatic(Log.class); // Log warnings to the console when(Log.w(anyString(), anyString())).thenAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); if (args.length > 1) { //cause I''m paranoid System.out.println("Tag:" + args[0] + " Msg: " + args[1]); } return null; } }); Log.w("My Tag", "This is a warning"); } }

¡Espero que esto ayude a alguien!