android - unit - testing aplicaciones moviles
¿Cómo determinar si la aplicación de Android se inicia con la instrumentación de prueba de JUnit? (3)
Necesito determinar en tiempo de ejecución desde el código si la aplicación se ejecuta bajo TestInstrumentation.
Podría inicializar el entorno de prueba con alguna variable env / system, pero la configuración de lanzamiento de Eclipse ADK no me permitiría hacerlo.
Las propiedades y el entorno predeterminados del sistema Android no tienen ningún dato al respecto. Además, son idénticamente iguales, ya sea que la aplicación se inicie regularmente o bajo prueba.
Esta podría ser una solución: es posible averiguar si una aplicación de Android se ejecuta como parte de una prueba de instrumentación, pero como no pruebo las actividades, todos los métodos propuestos no funcionarán. El método ActivityManager.isRunningInTestHarness() usa esto bajo el capó:
SystemProperties.getBoolean("ro.test_harness")
Lo que siempre devuelve falso en mi caso. (Para trabajar con la clase oculta de android.os.SystemProperties, uso la reflexión).
¿Qué más puedo hacer para tratar de determinar desde dentro de la aplicación si está bajo prueba?
Creamos una solución para pasar parámetros a MainActivity y usarla dentro del método onCreate, lo que le permite definir cómo se creará la Actividad.
En la clase MainActivity
, creamos algunas constantes, que también podrían ser una enumeración. También creamos un atributo estático.
public class MainActivity {
public static final int APPLICATION_MODE = 5;
public static final int UNIT_TEST_MODE = 10;
public static final int OTHER_MODE = 15;
public static int activityMode = APPLICATION_MODE;
(...)
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
switch (activityMode) {
case OTHER_MODE:
(...)
break;
case UNIT_TEST_MODE:
Log.d(TAG, "Is in Test Mode!");
break;
case APPLICATION_MODE:
(...)
break;
}
(...)
}
(...)
}
Hicimos el MainActivityTest
clase MainActivityTest
, creamos un setApplicationMode
y llamamos a este método dentro del método setUp()
, antes de llamar al método super.setUp()
.
public abstract class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
protected void setUp() throws Exception {
setApplicationMode(); // <=====
super.setUp();
getActivity();
(...)
}
(...)
public void setApplicationMode() {
MainActivity.activityMode = MainActivity.UNIT_TEST_MODE;
}
}
Todas las demás clases de prueba se heredan de MainActivityTest
, si queremos que tenga otro comportamiento, simplemente podemos anular el método setApplicationMode
.
public class OtherMainActivityTest extends MainActivityTest {
(...)
@Override
public void setApplicationMode() {
MainActivity.activityMode = MainActivity.OTHER_MODE;
}
}
El usuario nathan-almeida es el amigo que es coautor de esta solución.
He encontrado una solución pirata: desde la aplicación se puede intentar cargar una clase desde el paquete de prueba. El cargador de clases de aplicaciones sorprendentemente puede cargar clases por nombre del proyecto de prueba si se ejecutó bajo prueba. En otro caso no se encuentra la clase.
private static boolean isTestMode() {
boolean result;
try {
application.getClassLoader().loadClass("foo.bar.test.SomeTest");
// alternatively (see the comment below):
// Class.forName("foo.bar.test.SomeTest");
result = true;
} catch (final Exception e) {
result = false;
}
return result;
}
Admito que esto no es elegante pero funciona. Estaremos agradecidos por la solución adecuada.
La solución isTestMode () no me funcionó en Android Studio 1.2.1.1. El Todopoderoso Krzysztof de nuestra compañía modificó su método utilizando:
Class.forName("foo.bar.test.SomeTest");
en lugar de getClassLoader (). Gracias por Krzysztof!