Écrire les tests d'instrumentation

1. Avant de commencer

Dans un précédent atelier de programmation, vous avez appris à créer et à exécuter des tests unitaires. Cet atelier de programmation porte sur les tests d'instrumentation. Vous verrez ce à quoi ils ressemblent et découvrirez comment en créer.

Conditions préalables

  • Vous avez créé un projet dans Android Studio.
  • Vous avez de l'expérience en écriture de code dans Android Studio.
  • Vous avez de l'expérience en navigation de projets dans Android Studio.
  • Vous avez écrit des tests unitaires simples dans Android Studio.

Points abordés

  • Présentation des tests d'instrumentation
  • Exécuter des tests d'instrumentation
  • Écrire des tests d'instrumentation

Ce dont vous avez besoin

  • Un ordinateur sur lequel est installé Android Studio
  • Code de solution de l'application Tip Time

Télécharger le code de démarrage pour cet atelier de programmation

Dans cet atelier de programmation, vous ajouterez des tests d'instrumentation à l'application Tip Time à partir d'un code de solution précédent.

  1. Accédez à la page du dépôt GitHub fournie pour le projet.
  2. Vérifiez que le nom de la branche correspond à celui spécifié dans l'atelier de programmation. Par exemple, dans la capture d'écran suivante, le nom de la branche est main.

1e4c0d2c081a8fd2.png

  1. Sur la page GitHub du projet, cliquez sur le bouton Code pour afficher une fenêtre pop-up.

1debcf330fd04c7b.png

  1. Dans la fenêtre pop-up, cliquez sur le bouton Download ZIP (Télécharger le fichier ZIP) pour enregistrer le projet sur votre ordinateur. Attendez la fin du téléchargement.
  2. Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
  3. Double-cliquez sur le fichier ZIP pour le décompresser. Un dossier contenant les fichiers du projet est alors créé.

Ouvrir le projet dans Android Studio

  1. Lancez Android Studio.
  2. Dans la fenêtre Welcome to Android Studio (Bienvenue dans Android Studio), cliquez sur Open (Ouvrir).

d8e9dbdeafe9038a.png

Remarque : Si Android Studio est déjà ouvert, sélectionnez l'option de menu File > Open (Fichier > Ouvrir).

8d1fda7396afe8e5.png

  1. Dans l'explorateur de fichiers, accédez à l'emplacement du dossier du projet décompressé (il se trouve probablement dans le dossier Téléchargements).
  2. Double-cliquez sur le dossier de ce projet.
  3. Attendez qu'Android Studio ouvre le projet.
  4. Cliquez sur le bouton Run (Exécuter) 8de56cba7583251f.png pour créer et exécuter l'application. Assurez-vous qu'elle fonctionne correctement.

2. Présentation de l'application de démarrage

L'application Tip Time se compose d'un écran qui présente à l'utilisateur un champ de saisie du montant de la facture, des cases d'option permettant de sélectionner le pourcentage de pourboire et un bouton permettant de calculer le pourboire.

3. Créer le répertoire des tests d'instrumentation

Le code de démarrage de cet atelier de programmation est entièrement fonctionnel, mais il lui manque les tests et les répertoires de test. Avant d'écrire des tests de tout type, nous devons ajouter un répertoire pour y héberger les tests d'instrumentation. Une fois que vous avez téléchargé le code de démarrage, procédez comme suit pour ajouter une classe à vos tests d'instrumentation.

  1. Pour ce faire, le moyen le plus simple consiste à passer d'abord de la vue Android à la vue Project (Projet). Dans le volet du projet, en haut à gauche, cliquez sur la liste déroulante Android, puis sélectionnez Project (Projet).

20055afdc5d38e69.png

  1. La vue de votre projet se présente alors comme suit :

7e933e8dd546458e.png

  1. Cliquez sur la première liste déroulante, puis accédez à app -> src.

65dd6a80920623ef.png

  1. Effectuez un clic droit sur src et sélectionnez New -> Directory (Nouveau -> Répertoire).

73b014c84f89b0f0.png

  1. La fenêtre suivante devrait s'afficher :

921d8a0df6310383.png

  1. Sélectionnez androidTest/java.

c4b99c44611ae609.png

  1. Le répertoire androidTest s'affiche maintenant dans la structure du projet.

5f6643d80a7ef0f8.png

  1. Effectuez un clic droit sur le répertoire java, puis sélectionnez New -> Package (Nouveau -> Package).

8f8a590b7bdc01b3.png

  1. La fenêtre suivante s'affiche :

4d154746de968ccf.png

  1. Dans la fenêtre, saisissez le texte ci-dessous et appuyez sur Entrée :
com.example.tiptime
  1. La fenêtre de votre projet devrait se présenter comme suit :

7bb036a4bc3be441.png

  1. Enfin, effectuez un clic droit sur com.example.tiptime, puis sélectionnez New -> Kotlin Class/File (Nouveau -> Classe/Fichier Kotlin).

26ff162c120e18d1.png

  1. Dans la fenêtre qui s'affiche, saisissez CalculatorTests, sélectionnez Class (Classe) dans le menu déroulant, puis appuyez sur Entrée.

4. Écrire votre premier test d'instrumentation

L'heure est venue d'écrire un test d'instrumentation. Les étapes suivantes testent la fonctionnalité pour un pourboire de 20 %.

  1. Ouvrez le fichier que vous venez de créer. Il devrait se présenter comme suit :
package com.example.tiptime

class CalculatorTests {
}
  1. Les tests d'instrumentation nécessitent un exécuteur InstrumentationTestRunner, qui permet de les exécuter sur un appareil ou un émulateur. Il existe plusieurs autres exécuteurs d'instrumentation, mais pour ce test, nous utiliserons le lanceur de test AndroidJUnit4. Pour spécifier le lanceur de test, nous devons annoter la classe avec les éléments suivants :
@RunWith(AndroidJUnit4::class)
class CalculatorTests {
}

Par précaution, voici les importations dont vous avez besoin :

import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith

Tout est maintenant configuré pour commencer à écrire la logique de test.

  1. L'application Tip Time se compose d'une seule activité, MainActivity. Pour interagir avec l'activité, le scénario de test doit d'abord la lancer. Ajoutez le code suivant dans la classe CalculatorTests.
@get:Rule()
val activity = ActivityScenarioRule(MainActivity::class.java)

L'élément ActivityScenarioRule provient de la bibliothèque de test AndroidX. Il indique à l'appareil qu'il doit lancer une activité spécifiée par le développeur. Vous devez l'annoter avec @get:Rule, qui indique que la règle suivante (dans ce cas, le lancement d'une activité) doit s'exécuter avant chaque test de cette classe. Les règles sont essentielles pour les tests. Vous finirez d'ailleurs par apprendre à écrire les vôtres.

  1. Vous devez maintenant écrire la logique de test elle-même. Créez une fonction et appelez-la calculate_20_percent_tip(), puis accompagnez-la de l'annotation @Test.
@Test
fun calculate_20_percent_tip() {
}

Espresso

Ce cours utilise principalement Espresso pour les tests d'instrumentation. Espresso est une bibliothèque qui peut être utilisée avec un projet Android lorsqu'elle est créée avec Android Studio. Elle vous permet d'interagir avec les composants de l'interface utilisateur à l'aide de code.

À ce stade, vous avez peut-être remarqué qu'Android Studio propose de nombreuses fonctionnalités de saisie semi-automatique. L'un des aspects les plus complexes liés à l'utilisation d'Espresso est que les méthodes ne permettent pas la saisie semi-automatique si la bibliothèque n'a pas été importée. Il peut donc être difficile de parcourir les méthodes disponibles dans Espresso sans avoir à effectuer des recherches dans la documentation. Au cours de ces leçons, nous vous fournirons les méthodes nécessaires pour effectuer les tests.

Tout d'abord, vous devez écrire du code pour saisir le montant de la facture dans le champ de texte Cost of Service (Coût du service). Accédez à app -> src -> main -> res -> layout -> activity_main.xml pour indiquer que l'ID de TextInputEditText est cost_of_service_edit_text. Copiez le nom de l'ID, dont nous aurons besoin ultérieurement pour le test.

a113fb63b50f7674.png

Implémenter la fonction de test

Maintenant, dans la fonction calculate_20_percent_tip() de votre classe de test, vous pouvez écrire la logique de test.

  1. La première étape consiste à rechercher un composant d'interface utilisateur avec lequel interagir (dans le cas présent, TextInputEditText) à l'aide de la fonction onView(). La fonction onView() utilise un paramètre d'objet ViewMatcher. ViewMatcher est essentiellement un composant d'interface utilisateur qui correspond à un critère particulier. Dans le cas présent, il s'agit d'un composant dont l'ID est R.id.cost_of_service_edit_text.

La fonction withId() renvoie un élément ViewMatcher qui est le composant d'UI avec l'ID qui lui est transmis. onView() renvoie ViewInteraction, qui est un objet avec lequel nous pouvons interagir, comme si nous contrôlions l'appareil nous-mêmes. Pour saisir du texte, appelez perform() au niveau de ViewInteraction. perform() utilise ensuite un objet ViewAction. Plusieurs méthodes renvoient ViewAction, mais pour le moment, nous choisirons la méthode typeText(). Dans activity_main.xml, nous constatons que l'option de pourboire par défaut est de 20 %. Vous n'avez donc pas besoin de spécifier l'option de pourboire à utiliser pour le moment.

onView(withId(R.id.cost_of_service_edit_text))
    .perform(typeText("50.00"))

L'instruction complète devrait alors se présenter comme suit :

onView(withId(R.id.cost_of_service_edit_text))
    .perform(typeText("50.00"))
    .perform(ViewActions.closeSoftKeyboard())
  1. Le texte est désormais saisi, et le test doit cliquer sur le bouton Calculate (Calculer). Le code permettant d'atteindre cet objectif suit un format semblable à celui que nous avons utilisé pour saisir du texte. Le composant d'interface utilisateur est différent. Par conséquent, le nom de l'ID transmis à la fonction withId() n'est pas le même. Cependant, la seule différence dans cette approche est que ViewAction est différent. La fonction click() est utilisée à la place de typeText().
onView(withId(R.id.calculate_button))
    .perform(click())
  1. Pour finir, vous devez confirmer que le pourboire approprié s'affiche. Le montant du pourboire devrait être de 10 USD. Pour ce test, assurez-vous que TextView, dont l'ID est tip_result, contient la valeur de pourboire attendue sous forme de chaîne.
onView(withId(R.id.tip_result))
    .check(matches(withText(containsString("$10.00"))))

Sélectionnez les importations suivantes lorsque vous y êtes invité :

import androidx.test.espresso.assertion.ViewAssertions.matches
import org.hamcrest.Matchers.containsString

Ici, vous avez utilisé une autre interaction appelée check(), qui nécessite un élément ViewAssertion. Un élément ViewAssertion peut être considéré comme une assertion Espresso spéciale utilisée pour les composants de l'interface utilisateur. L'assertion est que le contenu de TextView correspond au texte qui contient la chaîne "$10.00".

Avant d'exécuter le test, assurez-vous que vos importations et votre code sont corrects. Ils devraient se présenter comme suit (pas de problème si les importations sont dans un ordre différent) :

package com.example.tiptime

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.hamcrest.Matchers.containsString
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class CalculatorTests {

   @get:Rule()
   val activity = ActivityScenarioRule(MainActivity::class.java)

   @Test
   fun calculate_20_percent_tip() {
       onView(withId(R.id.cost_of_service_edit_text))
           .perform(typeText("50.00"))

       onView(withId(R.id.calculate_button)).perform(click())

       onView(withId(R.id.tip_result))
           .check(matches(withText(containsString("$10.00"))))
   }
}

Si vous utilisez un émulateur, assurez-vous que l'émulateur et la fenêtre Android Studio s'affichent en même temps. Exécutez le test de la même manière que vous effectuez des tests unitaires (en effectuant un clic droit sur la flèche rouge/verte à gauche de la fonction, puis en sélectionnant la première option) et observez le résultat.

36684dfa8a17a2c9.gif

Comme vous pouvez le voir, le test s'exécute comme si quelqu'un interagissait avec l'application elle-même.

5. Élargir votre suite de tests

Félicitations ! Vous avez réussi votre premier test d'instrumentation.

Si vous aimez les défis, vous pouvez élargir la suite de tests en ajoutant des fonctions qui testent les autres pourcentages de pourboire. Utilisez le même format que celui de la fonction que nous avons écrite précédemment. La seule modification à apporter consiste à écrire le code pour sélectionner une option de pourcentage différente et à modifier la valeur transmise à containsString() pour tenir compte des différents résultats attendus. N'oubliez pas qu'il existe également une option permettant d'arrondir le résultat. Pour activer le bouton permettant d'arrondir le montant du pourboire à la valeur supérieure, recherchez le composant à l'aide de son ID, comme indiqué dans onView(withId()), puis cliquez dessus.

6. Code de solution

7. Résumé

  • Android Studio génère les classes de test nécessaires lors de la création du projet. Toutefois, si un projet n'en a pas, vous pouvez les créer manuellement.
  • Les règles de test sont exécutées avant chaque test d'une classe de test.
  • Espresso est un composant fondamental des tests d'instrumentation. Il permet d'interagir avec les composants de l'interface utilisateur à l'aide de code.

Cette leçon était longue. Vous pouvez être fier de vous.

En savoir plus