Exemple de tests d'auto-instrumentation

Lorsqu'un test d'instrumentation est lancé, son package cible est redémarré avec le code d'instrumentation injecté et lancé pour exécution. Une exception est que le package cible ici ne peut pas être le cadre de l' application Android lui - même, à savoir le package android , car cela conduirait à la situation paradoxale où le cadre Android devrait être redémarré, ce qui est ce qui soutient les fonctions du système, y compris l'instrumentation lui-même.

Cela signifie qu'un test d'instrumentation ne peut pas s'injecter dans le framework Android, alias le serveur système, pour l'exécution. Afin de tester le cadre Android, le code de test peut invoquer uniquement des surfaces API publiques, ou ceux qui sont exposés via Android Interface Definition Language AIDL disponible dans l'arbre source de la plate - forme. Pour cette catégorie de tests, il n'est pas significatif de cibler un package en particulier. Par conséquent, il est d' usage de ces instrumentations à déclarer pour cibler son propre dossier de demande d'essai, tel que défini dans son propre <manifest> balise de AndroidManifest.xml .

Selon les exigences, les packages d'application de test de cette catégorie peuvent également :

  • Regroupez les activités nécessaires pour les tests.
  • Partagez l'ID utilisateur avec le système.
  • Être signé avec la clé de la plate-forme.
  • Être compilé par rapport à la source du framework plutôt qu'au SDK public.

Cette catégorie de tests d'instrumentation est parfois appelée auto-instrumentation. Voici quelques exemples de tests d'auto-instrumentation dans le source de la plateforme :

L'exemple couvert ici est l'écriture d'un nouveau test d'instrumentation avec un package cible défini dans son propre package d'application de test. Ce guide utilise le test suivant pour servir d'exemple :

Il est recommandé de parcourir le code d'abord pour avoir une idée approximative avant de continuer.

Décider d'un emplacement source

En règle générale, votre équipe aura déjà un modèle établi d'endroits pour enregistrer le code et d'endroits pour ajouter des tests. La plupart des équipes possèdent un seul référentiel git ou en partagent un avec d'autres équipes, mais disposent d'un sous-répertoire dédié contenant le code source du composant.

En supposant que l'emplacement racine pour votre source composant est à <component source root> , la plupart des composants ont src et des tests sous-dossiers et des fichiers supplémentaires tels que Android.mk (ou morcelée en d' autres .mk fichiers), le fichier manifeste AndroidManifest.xml et le fichier de configuration de test 'AndroidTest.xml'.

Puisque vous ajoutez une nouvelle marque test, vous aurez probablement besoin de créer des tests répertoire à côté de votre composant src , et le remplir avec le contenu.

Dans certains cas, votre équipe pourrait avoir d' autres structures de répertoires sous tests en raison de la nécessité d'emballer différentes suites de tests dans les APK individuels. Et dans ce cas, vous devrez créer un nouveau sous - répertoire sous des tests .

Quelle que soit la structure, vous finirez par peuplant les tests de répertoire ou le sous - répertoire nouvellement créé avec des fichiers similaires à ce qui est dans l' instrumentation répertoire dans le changement échantillon de Gerrit. Les sections ci-dessous expliqueront plus en détail chaque fichier.

Fichier manifeste

Tout comme une application normale, chaque module de test d'instrumentation a besoin d'un fichier manifeste. Si vous nommez le fichier comme AndroidManifest.xml et fournissez à côté de Android.mk pour votre module de test, il s'inclus automatiquement par le BUILD_PACKAGE makefile de base.

Avant d' aller plus loin, il est fortement recommandé de passer par l' App Manifest Vue d' ensemble d' abord.

Cela donne un aperçu des composants de base d'un fichier manifeste et de leurs fonctionnalités. Voir l'exemple à platform_testing / tests / exemple / instrumentation / AndroidManifest.xml .

Un instantané est inclus ici pour plus de commodité :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

Quelques remarques sélectionnées sur le fichier manifeste :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

Le package attribut est le nom du package d'application: il est l'identifiant unique que l'utilisation du cadre d'application Android pour identifier une 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, ce package attribut est le même que ce que ComponentName#getPackageName() retourne, et aussi le même que vous utilisez pour interagir avec différentes pm commandes sous via adb shell .

Veuillez également noter que bien que le nom du package soit généralement dans le même style qu'un nom de package Java, il a en fait très peu de choses à voir avec cela. En d'autres termes, votre package d'application (ou de test) peut contenir des classes avec n'importe quel nom de package, mais d'un autre côté, vous pouvez opter pour la simplicité et avoir votre nom de package Java de niveau supérieur dans votre application ou test identique au nom du package d'application.

android:sharedUserId="android.uid.system"

Cela déclare qu'au moment de l'installation, cet apk doit recevoir le même identifiant d'utilisateur, c'est-à-dire l'identité d'exécution, que la plate-forme principale. Notez que cela dépend de l'APK étant signé avec un même certificat que la plate - forme de base (voir LOCAL_CERTIFICATE dans la section ci - dessus), mais ils sont différents concepts:

  • certaines autorisations ou API sont protégées par signature, ce qui nécessite le même certificat de signature
  • certaines autorisations ou API nécessite le system identité de l' utilisateur de l'appelant, ce qui nécessite le paquet appelant à partager ID utilisateur avec le system , si elle est un ensemble distinct de la plate - forme de noyau lui - même
<uses-library android:name="android.test.runner" />

Ceci est requis pour tous les tests d'instrumentation, car les classes associées sont empaquetées dans un fichier de bibliothèque jar de framework séparé, ce qui nécessite donc des entrées de chemin de classe supplémentaires lorsque le package de test est appelé par le framework d'application.

android:targetPackage="android.test.example.helloworld"

Vous avez peut - être remarqué que le targetPackage est déclaré ici même que le package attribut déclaré dans le manifest étiquette de ce fichier. Comme mentionné dans base de tests , cette catégorie de tests d'instrumentation sont généralement destinée à tester les API cadres, il est donc pas très significatif pour eux d'avoir une trousse de demande ciblée spécifique, puis d' autres lui - même.

Fichier de configuration simple

Chaque nouveau module de test doit avoir un fichier de configuration pour diriger le système de construction avec les métadonnées du module, les dépendances au moment de la compilation et les instructions d'empaquetage. Dans la plupart des cas, l'option de fichier Blueprint basée sur Soong est suffisante. Pour plus de détails, voir Configuration de test simple .

Fichier de configuration complexe

Pour ces cas plus complexes, vous devez également écrire un fichier de configuration de test pour harnais de test d'Android, la Fédération du Commerce .

La configuration de test peut spécifier des options de configuration de périphérique spéciales et des arguments par défaut pour fournir la classe de test. Voir l'exemple à /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>

Quelques remarques sélectives sur le fichier de configuration de test :

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>

Cela indique à Trade Federation d'installer HelloWorldTests.apk sur l'appareil cible à l'aide d'un target_preparer spécifié. Il existe de nombreux préparateurs cibles disponibles pour les développeurs dans Trade Federation et ceux-ci peuvent être utilisés pour s'assurer que 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 Trade Federation à utiliser pour exécuter le test et transmet le package sur le périphérique à exécuter et le framework de testeur qui est JUnit dans ce cas.

Pour plus d' informations, voir le module de test Configs .

Fonctionnalités de JUnit4

En utilisant android-support-test de bibliothèque comme lanceur de test permet l' adoption de nouvelles classes d'essai de style junit4, et le changement de l' échantillon Gerrit contient une utilisation très basique de ses caractéristiques. Voir l'exemple à /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 obligés d'hériter d'une classe de test de base commune ; à la place, vous écrivez des tests dans des classes Java simples et utilisez des annotations pour indiquer certaines configurations et contraintes de test. 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 @Before et @After annotations sont utilisées sur les méthodes par junit4 pour effectuer la configuration de test pré et post test désassemblage. De même, les @BeforeClass et @AfterClass annotations sont utilisées sur les méthodes par junit4 pour effectuer l' installation avant d' exécuter tous les tests dans une classe de test, et après désassemblage. Notez que les méthodes de configuration et de suppression de la portée de la classe doivent être statiques. En ce qui concerne les méthodes d'essai, contrairement à la version antérieure de JUnit, ils ne ont plus besoin de lancer le nom de la méthode avec test , au contraire, chacun d'eux doit être annotés avec @Test . Comme d'habitude, les méthodes de test doivent être publiques, ne déclarer aucune valeur de retour, ne prendre aucun paramètre et peuvent lever des exceptions.

Important: les méthodes d'essai se sont annotés avec @Test annotation; et notez que pour les tests à exécuter via APCT, ils doivent être annotées avec des tailles d'essai: l'exemple méthode annotée testHelloWorld comme @SmallTest . L'annotation peut être appliquée à la portée de la méthode ou à la portée de la classe.

Accès à l' instrumentation

Bien que ne sont pas couverts dans l'exemple du monde bonjour de base, il est assez commun pour un test Android à exiger l' accès Instrumentation exemple: ceci est l'interface API de base qui permet d' accéder à des contextes d'application, cycle de vie activité API de test liées et plus.

Parce que le junit4 teste ne nécessitent plus une classe de base commune, il est plus nécessaire d'obtenir Instrumentation exemple via InstrumentationTestCase#getInstrumentation() , à la place, le nouveau coureur de test gère via InstrumentationRegistry où la configuration contextuelle et l' environnement créé par le cadre d'instrumentation est stocké.

Pour accéder à l'instance de Instrumentation classe, il suffit d' appeler la méthode statique getInstrumentation() sur InstrumentationRegistry classe:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

Construire et tester localement

Pour la plupart des cas d'utilisation commune, emploi Atest .

Pour les cas plus complexes nécessitant plus lourd personnalisation, suivez les instructions d'instrumentation .