Esta categoría de prueba de instrumentación no es muy diferente de las que se orientan a las aplicaciones normales de Android. Vale la pena señalar que la aplicación de prueba que incluyó la instrumentación debe estar firmada con el mismo certificado que la aplicación a la que se segmenta.
Ten en cuenta que, en esta guía, se da por sentado que ya tienes algunos conocimientos sobre el flujo de trabajo del árbol de origen de la plataforma. De lo contrario, consulta los Requisitos. En el ejemplo que se describe aquí, se escribe una nueva prueba de instrumentación con el paquete de destino configurado en su propio paquete de aplicación de prueba. Si no estás familiarizado con el concepto, lee la Introducción a las pruebas de la plataforma.
En esta guía, se usa la siguiente prueba como ejemplo:
- frameworks/base/paquetes/Shell/pruebas
Se recomienda explorar el código primero para obtener una impresión aproximada antes de continuar.
Elige una ubicación de origen
Debido a que la prueba de instrumentación se orientará a una aplicación, la convención es colocar el código fuente de prueba en un directorio tests
debajo de la raíz de tu directorio de origen de componentes en el árbol de origen de la plataforma.
Consulta más debates sobre la ubicación de la fuente en el ejemplo de extremo a extremo para pruebas de instrumentación automática.
Archivo de manifiesto
Al igual que una aplicación normal, cada módulo de prueba de instrumentación necesita un archivo de manifiesto. Si le asignas el nombre AndroidManifest.xml
al archivo y lo proporcionas junto a Android.mk
para tu módulo de prueba, el archivo de configuración de make principal BUILD_PACKAGE
lo incluirá automáticamente.
Antes de continuar, te recomendamos que consultes la descripción general del manifiesto de la app.
Aquí se proporciona una descripción general de los componentes básicos de un archivo de manifiesto y sus funciones.
Puedes acceder a la versión más reciente del archivo de manifiesto del cambio de Gerrit de muestra en https://android.googlesource.com/platform/frameworks/base/+/main/packages/Shell/tests/AndroidManifest.xml.
Aquí se incluye un resumen para tu comodidad:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.shell.tests">
<application>
<uses-library android:name="android.test.runner" />
<activity
android:name="com.android.shell.ActionSendMultipleConsumerActivity"
android:label="ActionSendMultipleConsumer"
android:theme="@android:style/Theme.NoDisplay"
android:noHistory="true"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.shell"
android:label="Tests for Shell" />
</manifest>
Algunas observaciones seleccionadas sobre el archivo de manifiesto:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.shell.tests">
El atributo package
es el nombre del paquete de la aplicación: es el identificador único que el framework de aplicaciones para Android usa para identificar una aplicación (o, en este contexto, la aplicación de prueba). Cada usuario del sistema solo puede instalar una aplicación con ese nombre de paquete.
Como este es un paquete de aplicación de prueba, independiente del paquete de aplicación en prueba, se debe usar un nombre de paquete diferente: una convención común es agregar un sufijo .test
.
Además, este atributo package
es el mismo que muestra ComponentName#getPackageName()
y el mismo que usarías para interactuar con varios subcomandos pm
a través de adb shell
.
Ten en cuenta también que, aunque el nombre del paquete suele tener el mismo estilo que un nombre de paquete de Java, en realidad tiene muy poco que ver con él. En otras palabras, el paquete de tu aplicación (o prueba) puede contener clases con cualquier nombre de paquete, aunque, por otro lado, puedes optar por la simplicidad y tener el nombre de paquete de Java de nivel superior en tu aplicación o prueba idéntico al nombre de paquete de la aplicación.
<uses-library android:name="android.test.runner" />
Esto es obligatorio para todas las pruebas de instrumentación, ya que las clases relacionadas se empaquetan en un archivo de biblioteca de jar de framework independiente y, por lo tanto, requieren entradas de ruta de clase adicionales cuando el framework de la aplicación invoca el paquete de prueba.
android:targetPackage="com.android.shell"
De esta manera, se establece el paquete de destino de la instrumentación en com.android.shell
.
Cuando se invoca la instrumentación a través del comando am instrument
, el framework reinicia el proceso com.android.shell
y, luego, inserta el código de instrumentación en el proceso para la ejecución de la prueba. Esto también significa que el código de prueba tendrá acceso a todas las instancias de clase que se ejecutan en la aplicación que se está probando y puede manipular el estado según los hooks de prueba expuestos.
Archivo de configuración simple
Cada módulo de prueba nuevo debe tener un archivo de configuración para dirigir el sistema de compilación con metadatos del módulo, instrucciones de empaquetado y dependencias del tiempo de compilación. En la mayoría de los casos, la opción de archivo de Blueprint basada en Soong es suficiente. Consulta Configuración de prueba simple para obtener más detalles.
Archivo de configuración complejo
Para pruebas más complejas, también debes escribir un archivo de configuración de pruebas para el conjunto de pruebas de Android, Trade Federation.
La configuración de prueba puede especificar opciones especiales de configuración del dispositivo y argumentos predeterminados para proporcionar la clase de prueba.
Puedes acceder a la versión más reciente del archivo de configuración del cambio de Gerrit de muestra en frameworks/base/packages/Shell/tests/AndroidTest.xml.
Aquí se incluye un resumen para tu comodidad:
<configuration description="Runs Tests for Shell.">
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="ShellTests.apk" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
<option name="test-tag" value="ShellTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.shell.tests" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
</test>
</configuration>
Estas son algunas observaciones sobre el archivo de configuración de prueba:
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="ShellTests.apk"/>
</target_preparer>
Esto le indica a Trade Federation que instale ShellTests.apk en el dispositivo de destino con un target_preparer especificado. Hay muchos preparadores de destino disponibles para los desarrolladores en Trade Federation, que se pueden usar para garantizar que el dispositivo esté configurado correctamente antes de ejecutar la prueba.
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.shell.tests"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>
Esto especifica la clase de prueba de Trade Federation que se usará para ejecutar la prueba y pasa el paquete en el dispositivo que se ejecutará y el framework del ejecutor de pruebas, que es JUnit en este caso.
Consulta aquí para obtener más información sobre las configuraciones de los módulos de prueba.
Funciones de JUnit4
El uso de la biblioteca android-support-test
como ejecutor de pruebas permite la adopción de nuevas clases de prueba de estilo JUnit4, y el cambio de gerrit de muestra contiene un uso muy básico de sus funciones.
Puedes acceder al código fuente más reciente para el cambio de gerrit de muestra en frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
Si bien los patrones de prueba suelen ser específicos de los equipos de componentes, existen algunos patrones de uso generalmente útiles.
@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {
Una diferencia significativa en JUnit4 es que las pruebas ya no deben heredar de una clase de prueba base común. En su lugar, escribes pruebas en clases de Java simples y usas anotaciones para indicar ciertas configuraciones y restricciones de prueba. En este ejemplo, indicamos que esta clase se debe ejecutar como una prueba de AndroidJUnit4.
La anotación @SmallTest
especifica un tamaño de prueba para toda la clase de prueba: todos los métodos de prueba que se agregan a esta clase heredan esta anotación de tamaño de prueba. Configuración de la clase previa a la prueba, baja después de la prueba y baja después de la clase de prueba: similar a los métodos setUp
y tearDown
en JUnit4.
La anotación Test
se usa para anotar la prueba real.
@Before
public void setup() {
...
@Test
public void testGetProvider_shouldCacheProvider() {
...
JUnit4 usa la anotación @Before
en los métodos para realizar la configuración previa a la prueba.
Aunque no se usa en este ejemplo, también hay @After
para la eliminación posterior a la prueba.
Del mismo modo, JUnit4 puede usar las anotaciones @BeforeClass
y @AfterClass
en métodos para realizar la configuración antes de ejecutar todas las pruebas en una clase de prueba y, luego, realizar la eliminación. Ten en cuenta que los métodos de configuración y desmontaje del alcance de clase deben ser estáticos.
En cuanto a los métodos de prueba, a diferencia de las versiones anteriores de JUnit, ya no es necesario comenzar el nombre del método con test
. En su lugar, cada uno de ellos debe anotarse con @Test
. Como de costumbre, los métodos de prueba deben ser públicos, no declarar ningún valor que se muestre, no tomar parámetros y pueden generar excepciones.
Context context = InstrumentationRegistry.getTargetContext();
Debido a que las pruebas de JUnit4 ya no requieren una clase base común, ya no es necesario obtener instancias de Context
a través de getContext()
o getTargetContext()
a través de métodos de clase base. En su lugar, el nuevo ejecutor de pruebas los administra a través de InstrumentationRegistry
, donde se almacena la configuración contextual y ambiental creada por el framework de instrumentación. A través de esta clase, también puedes llamar a lo siguiente:
getInstrumentation()
: Es la instancia de la claseInstrumentation
.getArguments()
: Los argumentos de la línea de comandos que se pasan aam instrument
a través de-e <key> <value>
Compila y prueba de manera local
Para los casos de uso más comunes, emplea Atest.
Para casos más complejos que requieran una personalización más pesada, sigue las instrucciones de instrumentación.