Lorsqu'un test d'instrumentation est démarré, son package cible est
redémarré avec du code d'instrumentation
injecté et lancé pour l'exécution. Un
Exception : le package cible ne peut pas être l'application Android
comme le package android
, car cela aboutit
une situation paradoxale dans laquelle le framework Android devrait être redémarré, ce qui
est ce qui soutient les fonctions du système, y compris l'instrumentation elle-même.
Cela signifie qu'un test d'instrumentation ne peut pas s'injecter dans Android
(ou serveur système) pour exécution. Pour tester l'application Android
le code de test ne peut appeler que les surfaces d'API publiques ou celles exposées
à l'aide du langage de définition d'interface Android
AIDL
dans l'arborescence source de la plate-forme. Pour cette catégorie de tests, il n'est pas pertinent de cibler un package en particulier. Par conséquent, il est de coutume
d'instrumentation à déclarer pour cibler son propre package d'application de test,
défini dans sa propre balise <manifest>
de AndroidManifest.xml
.
En fonction des exigences, les packages d'applications de test de cette catégorie peuvent également:
- Regroupez les activités nécessaires aux tests.
- Partagez l'ID utilisateur avec le système.
- être signées avec la clé de plate-forme ;
- être compilé avec la source du framework plutôt qu'avec le SDK public ;
Cette catégorie de tests d'instrumentation est parfois appelée l'auto-instrumentation. Voici quelques exemples de tests d'auto-instrumentation la source de la plate-forme:
L'exemple présenté ici consiste à écrire un nouveau test d'instrumentation avec dans son propre package d'application de test. Ce guide utilise les éléments suivants : à titre d'exemple:
Nous vous recommandons de commencer par parcourir le code pour obtenir une impression approximative avant de continuer.
Choisir un emplacement source
En règle générale, votre équipe aura déjà établi un modèle établi de lieux de vérification dans le code, et où ajouter des tests. La plupart des équipes possèdent un seul dépôt Git. partagez-en un avec d'autres équipes, mais avez un sous-répertoire dédié qui contient le code source du composant.
En supposant que l'emplacement racine de la source de votre composant se trouve à <component source
root>
, la plupart des composants comportent des dossiers src
et tests
, et certains
des fichiers supplémentaires tels que Android.mk
(ou divisés en fichiers .mk
supplémentaires) ;
le fichier manifeste AndroidManifest.xml
et le fichier de configuration de test
"AndroidTest.xml".
Étant donné que vous ajoutez un tout nouveau test, vous devrez probablement créer le
tests
à côté de votre composant src
, puis remplissez-le avec du contenu.
Dans certains cas, votre équipe peut disposer d'autres structures de répertoires sous tests
.
en raison de la nécessité d'empaqueter différentes suites de tests dans des APK individuels. Et
Dans ce cas, vous devez créer un sous-répertoire sous tests
.
Quelle que soit la structure, vous finirez par remplir le répertoire tests
ou
le sous-répertoire nouvellement créé avec
des fichiers similaires à ce qu'il y a dans
instrumentation
dans l'exemple de modification de gerrit. Le détail de chaque
sont expliqués plus loin dans ce document.
Fichier manifeste
Comme pour un projet d'application, chaque module de test d'instrumentation nécessite
fichier manifeste nommé AndroidManifest.xml
. Pour inclure automatiquement
à l'aide du fichier makefile principalBUILD_PACKAGE
, fournissez-le à côté de
Android.mk
pour votre module de test.
Si vous ne connaissez pas bien le fichier AndroidManifest.xml
, consultez
Présentation du fichier manifeste d'application
Voici un exemple de fichier AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="android.uid.system"
package="android.test.example.helloworld" >
<application>
<uses-library android:name="android.test.runner"/>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.test.example.helloworld"
android:label="Hello World Test"/>
</manifest>
Quelques remarques concernant le fichier manifeste:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.test.example.helloworld" >
L'attribut package
correspond au nom du package de l'application: il s'agit de l'attribut
que le framework d'application Android utilise pour identifier
application (ou, dans ce contexte, votre application de test). Chaque utilisateur du système
ne peut installer qu’une seule application
avec ce nom de package.
De plus, cet attribut package
est identique à ce que vous
ComponentName#getPackageName()
ainsi que pour interagir avec différents sous-ensembles pm
utilisent adb shell
.
Notez que même si le nom du package est généralement dans le même style, en tant que nom de package Java, il a en fait très peu de choses à faire avec. Dans d'autres votre package d'application (ou de test) peut contenir des classes avec n'importe quel package de noms de domaine. D'un autre côté, vous pouvez opter pour la simplicité et faire en sorte du package Java du niveau de service dans votre application ou test identique à l'application nom du package.
android:sharedUserId="android.uid.system"
Il déclare qu'au moment de l'installation, ce fichier APK doit disposer du rôle
le même ID utilisateur, c'est-à-dire l'identité d'exécution, que la plate-forme principale. Notez qu'il s'agit
dépend de la signature de l'APK avec le même certificat que celui de la plate-forme principale.
(voir LOCAL_CERTIFICATE
dans une section précédente), mais elles sont différentes.
concepts:
- certaines autorisations ou API sont protégées par une signature, ce qui nécessite certificat de signature
- certaines autorisations ou API nécessitent l'identité d'utilisateur
system
de l'appelant, qui nécessite que le package appelant partage l'ID utilisateur avecsystem
, s'il s'agit d'un un package distinct de la plate-forme principale elle-même.
<uses-library android:name="android.test.runner" />
Cela est obligatoire pour tous les tests d'instrumentation, car les classes associées sont empaquetés dans un fichier de bibliothèque JAR de framework distinct, nécessite donc Entrées classpath lorsque le package de test est appelé par le framework d'application
android:targetPackage="android.test.example.helloworld"
Vous avez peut-être remarqué que targetPackage
ici est déclaré de la même manière que
L'attribut package
a été déclaré dans la balise manifest
de ce fichier. Comme indiqué dans
principes de base des tests, cette catégorie de tests d'instrumentation
sert généralement à tester les API de framework. Il n'est donc pas très utile
d’avoir un package d’application ciblé
spécifique, autre que lui-même.
Fichier de configuration simple
Chaque nouveau module de test doit disposer d'un fichier de configuration le système de compilation avec les métadonnées du module, les dépendances au moment de la compilation et le packaging instructions. Dans la plupart des cas, l’option de fichier de plan basée sur Soong est suffisant. Pour en savoir plus, consultez Configuration de test simple.
Fichier de configuration complexe
Pour ces cas plus complexes, vous devez également écrire une configuration de test pour l'outil de test d'Android, Fédération de commerce.
La configuration de test peut spécifier des options de configuration d'appareil spéciales et des paramètres par défaut pour fournir la classe de test. Consultez l'exemple sur la page /platform_testing/tests/example/instrumentation/AndroidTest.xml.
Un instantané est inclus ici pour plus de commodité:
<configuration description="Runs sample instrumentation test.">
<target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
<option name="test-suite-tag" value="apct"/>
<option name="test-tag" value="SampleInstrumentationTest"/>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="android.test.example.helloworld"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>
</configuration>
Remarques importantes concernant le fichier de configuration du test:
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>
Cela indique à la fédération commerciale d'installer le HelloWorldTests.apk sur la cible appareil à l'aide d'un target_preparer spécifié. Il existe de nombreux préparateurs cibles à la disposition des développeurs de la Fédération commerciale l'appareil est correctement configuré avant l'exécution du test.
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="android.test.example.helloworld"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>
Cela spécifie la classe de test de la fédération de commerce à utiliser pour exécuter le test et transmet le package sur l'appareil à exécuter et le lanceur de test qui est JUnit dans ce cas.
Pour en savoir plus, consultez Tester les configurations de module
Fonctionnalités de JUnit4
L'utilisation de la bibliothèque android-support-test
en tant qu'exécuteur de test permet d'adopter de nouvelles
à des classes de test de style JUnit4, et l'exemple de modification de gerrit contient des éléments
de ses fonctionnalités. Consultez l'exemple sur la page
/platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java.
Bien que les modèles de test soient généralement spécifiques aux équipes de composants, il existe des modèles d'utilisation généralement utiles.
@RunWith(JUnit4.class)
public class HelloWorldTest {
Une différence significative dans JUnit4 est que les tests ne sont plus nécessaires pour hériter d'une classe de test de base commune ; vous écrivez les tests en langage Java et utilisent des annotations pour indiquer certaines contraintes et configuration de test. Dans Dans cet exemple, nous indiquons que cette classe doit être exécutée en tant que test JUnit4.
@BeforeClass
public static void beforeClass() {
...
@AfterClass
public static void afterClass() {
...
@Before
public void before() {
...
@After
public void after() {
...
@Test
@SmallTest
public void testHelloWorld() {
...
Les annotations @Before
et @After
sont utilisées sur les méthodes par JUnit4 pour effectuer
la configuration avant et après
le test. De même, @BeforeClass
et
Les annotations @AfterClass
sont utilisées sur les méthodes de JUnit4 pour effectuer la configuration avant
exécuter tous les tests d'une classe de test, puis les supprimer. Notez que
les méthodes de configuration et de suppression à l'échelle de la classe doivent être statiques. Concernant les méthodes de test,
contrairement à la version précédente de JUnit, il n'est plus nécessaire de commencer le nom de la méthode
avec test
, chacun d'eux doit être annoté avec @Test
. Comme d'habitude,
les méthodes de test doivent être publiques, ne déclarer aucune valeur renvoyée, n'accepter aucun paramètre ;
peut générer des exceptions.
Accès à la classe d'instrumentation
Bien qu'il ne soit pas abordé dans l'exemple de base "Hello World", il est assez courant pour une
Test Android nécessitant l'accès à l'instance Instrumentation
: il s'agit de l'API principale
permettant d'accéder aux contextes d'application, au cycle de vie de l'activité
les API de test associées, etc.
Comme les tests JUnit4 ne nécessitent plus de classe de base commune, il n'est plus nécessaire
nécessaire pour obtenir l'instance Instrumentation
via
InstrumentationTestCase#getInstrumentation()
, à la place, le nouveau lanceur de test
le gère via InstrumentationRegistry
où la configuration contextuelle et environnementale créée par le framework d'instrumentation
stockées.
Pour accéder à l'instance de la classe Instrumentation
, il suffit d'appeler la méthode statique.
getInstrumentation()
sur InstrumentationRegistry
:
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()
Compiler et tester en local
Pour les cas d'utilisation les plus courants, utilisez Confirmer :
Pour les cas plus complexes nécessitant une personnalisation plus poussée, suivez le instructions d'instrumentation.